diff options
Diffstat (limited to 'sound/soc/codecs')
74 files changed, 18149 insertions, 1820 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0edca93af3b0..1743d565e996 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -15,12 +15,15 @@ config SND_SOC_ALL_CODECS | |||
15 | select SND_SOC_AD1836 if SPI_MASTER | 15 | select SND_SOC_AD1836 if SPI_MASTER |
16 | select SND_SOC_AD1938 if SPI_MASTER | 16 | select SND_SOC_AD1938 if SPI_MASTER |
17 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 17 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
18 | select SND_SOC_ADS117X | ||
18 | select SND_SOC_AD73311 if I2C | 19 | select SND_SOC_AD73311 if I2C |
19 | select SND_SOC_AK4104 if SPI_MASTER | 20 | select SND_SOC_AK4104 if SPI_MASTER |
20 | select SND_SOC_AK4535 if I2C | 21 | select SND_SOC_AK4535 if I2C |
21 | select SND_SOC_AK4642 if I2C | 22 | select SND_SOC_AK4642 if I2C |
23 | select SND_SOC_AK4671 if I2C | ||
22 | select SND_SOC_CS4270 if I2C | 24 | select SND_SOC_CS4270 if I2C |
23 | select SND_SOC_MAX9877 if I2C | 25 | select SND_SOC_MAX9877 if I2C |
26 | select SND_SOC_DA7210 if I2C | ||
24 | select SND_SOC_PCM3008 | 27 | select SND_SOC_PCM3008 |
25 | select SND_SOC_SPDIF | 28 | select SND_SOC_SPDIF |
26 | select SND_SOC_SSM2602 if I2C | 29 | select SND_SOC_SSM2602 if I2C |
@@ -28,14 +31,19 @@ config SND_SOC_ALL_CODECS | |||
28 | select SND_SOC_TLV320AIC23 if I2C | 31 | select SND_SOC_TLV320AIC23 if I2C |
29 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 32 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
30 | select SND_SOC_TLV320AIC3X if I2C | 33 | select SND_SOC_TLV320AIC3X if I2C |
34 | select SND_SOC_TPA6130A2 if I2C | ||
35 | select SND_SOC_TLV320DAC33 if I2C | ||
31 | select SND_SOC_TWL4030 if TWL4030_CORE | 36 | select SND_SOC_TWL4030 if TWL4030_CORE |
32 | select SND_SOC_UDA134X | 37 | select SND_SOC_UDA134X |
33 | select SND_SOC_UDA1380 if I2C | 38 | select SND_SOC_UDA1380 if I2C |
39 | select SND_SOC_WM2000 if I2C | ||
34 | select SND_SOC_WM8350 if MFD_WM8350 | 40 | select SND_SOC_WM8350 if MFD_WM8350 |
35 | select SND_SOC_WM8400 if MFD_WM8400 | 41 | select SND_SOC_WM8400 if MFD_WM8400 |
36 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI | 42 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI |
37 | select SND_SOC_WM8523 if I2C | 43 | select SND_SOC_WM8523 if I2C |
38 | select SND_SOC_WM8580 if I2C | 44 | select SND_SOC_WM8580 if I2C |
45 | select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI | ||
46 | select SND_SOC_WM8727 | ||
39 | select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI | 47 | select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI |
40 | select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI | 48 | select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI |
41 | select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI | 49 | select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI |
@@ -43,14 +51,18 @@ config SND_SOC_ALL_CODECS | |||
43 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI | 51 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI |
44 | select SND_SOC_WM8900 if I2C | 52 | select SND_SOC_WM8900 if I2C |
45 | select SND_SOC_WM8903 if I2C | 53 | select SND_SOC_WM8903 if I2C |
54 | select SND_SOC_WM8904 if I2C | ||
46 | select SND_SOC_WM8940 if I2C | 55 | select SND_SOC_WM8940 if I2C |
56 | select SND_SOC_WM8955 if I2C | ||
47 | select SND_SOC_WM8960 if I2C | 57 | select SND_SOC_WM8960 if I2C |
48 | select SND_SOC_WM8961 if I2C | 58 | select SND_SOC_WM8961 if I2C |
49 | select SND_SOC_WM8971 if I2C | 59 | select SND_SOC_WM8971 if I2C |
50 | select SND_SOC_WM8974 if I2C | 60 | select SND_SOC_WM8974 if I2C |
61 | select SND_SOC_WM8978 if I2C | ||
51 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI | 62 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI |
52 | select SND_SOC_WM8990 if I2C | 63 | select SND_SOC_WM8990 if I2C |
53 | select SND_SOC_WM8993 if I2C | 64 | select SND_SOC_WM8993 if I2C |
65 | select SND_SOC_WM8994 if MFD_WM8994 | ||
54 | select SND_SOC_WM9081 if I2C | 66 | select SND_SOC_WM9081 if I2C |
55 | select SND_SOC_WM9705 if SND_SOC_AC97_BUS | 67 | select SND_SOC_WM9705 if SND_SOC_AC97_BUS |
56 | select SND_SOC_WM9712 if SND_SOC_AC97_BUS | 68 | select SND_SOC_WM9712 if SND_SOC_AC97_BUS |
@@ -86,6 +98,9 @@ config SND_SOC_AD1980 | |||
86 | 98 | ||
87 | config SND_SOC_AD73311 | 99 | config SND_SOC_AD73311 |
88 | tristate | 100 | tristate |
101 | |||
102 | config SND_SOC_ADS117X | ||
103 | tristate | ||
89 | 104 | ||
90 | config SND_SOC_AK4104 | 105 | config SND_SOC_AK4104 |
91 | tristate | 106 | tristate |
@@ -96,10 +111,16 @@ config SND_SOC_AK4535 | |||
96 | config SND_SOC_AK4642 | 111 | config SND_SOC_AK4642 |
97 | tristate | 112 | tristate |
98 | 113 | ||
114 | config SND_SOC_AK4671 | ||
115 | tristate | ||
116 | |||
99 | # Cirrus Logic CS4270 Codec | 117 | # Cirrus Logic CS4270 Codec |
100 | config SND_SOC_CS4270 | 118 | config SND_SOC_CS4270 |
101 | tristate | 119 | tristate |
102 | 120 | ||
121 | config SND_SOC_DA7210 | ||
122 | tristate | ||
123 | |||
103 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata | 124 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata |
104 | # Select if you are affected by the errata where the part will not function | 125 | # Select if you are affected by the errata where the part will not function |
105 | # if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will | 126 | # if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will |
@@ -136,7 +157,11 @@ config SND_SOC_TLV320AIC26 | |||
136 | config SND_SOC_TLV320AIC3X | 157 | config SND_SOC_TLV320AIC3X |
137 | tristate | 158 | tristate |
138 | 159 | ||
160 | config SND_SOC_TLV320DAC33 | ||
161 | tristate | ||
162 | |||
139 | config SND_SOC_TWL4030 | 163 | config SND_SOC_TWL4030 |
164 | select TWL4030_CODEC | ||
140 | tristate | 165 | tristate |
141 | 166 | ||
142 | config SND_SOC_UDA134X | 167 | config SND_SOC_UDA134X |
@@ -160,6 +185,12 @@ config SND_SOC_WM8523 | |||
160 | config SND_SOC_WM8580 | 185 | config SND_SOC_WM8580 |
161 | tristate | 186 | tristate |
162 | 187 | ||
188 | config SND_SOC_WM8711 | ||
189 | tristate | ||
190 | |||
191 | config SND_SOC_WM8727 | ||
192 | tristate | ||
193 | |||
163 | config SND_SOC_WM8728 | 194 | config SND_SOC_WM8728 |
164 | tristate | 195 | tristate |
165 | 196 | ||
@@ -181,9 +212,15 @@ config SND_SOC_WM8900 | |||
181 | config SND_SOC_WM8903 | 212 | config SND_SOC_WM8903 |
182 | tristate | 213 | tristate |
183 | 214 | ||
215 | config SND_SOC_WM8904 | ||
216 | tristate | ||
217 | |||
184 | config SND_SOC_WM8940 | 218 | config SND_SOC_WM8940 |
185 | tristate | 219 | tristate |
186 | 220 | ||
221 | config SND_SOC_WM8955 | ||
222 | tristate | ||
223 | |||
187 | config SND_SOC_WM8960 | 224 | config SND_SOC_WM8960 |
188 | tristate | 225 | tristate |
189 | 226 | ||
@@ -196,6 +233,9 @@ config SND_SOC_WM8971 | |||
196 | config SND_SOC_WM8974 | 233 | config SND_SOC_WM8974 |
197 | tristate | 234 | tristate |
198 | 235 | ||
236 | config SND_SOC_WM8978 | ||
237 | tristate | ||
238 | |||
199 | config SND_SOC_WM8988 | 239 | config SND_SOC_WM8988 |
200 | tristate | 240 | tristate |
201 | 241 | ||
@@ -205,6 +245,9 @@ config SND_SOC_WM8990 | |||
205 | config SND_SOC_WM8993 | 245 | config SND_SOC_WM8993 |
206 | tristate | 246 | tristate |
207 | 247 | ||
248 | config SND_SOC_WM8994 | ||
249 | tristate | ||
250 | |||
208 | config SND_SOC_WM9081 | 251 | config SND_SOC_WM9081 |
209 | tristate | 252 | tristate |
210 | 253 | ||
@@ -220,3 +263,9 @@ config SND_SOC_WM9713 | |||
220 | # Amp | 263 | # Amp |
221 | config SND_SOC_MAX9877 | 264 | config SND_SOC_MAX9877 |
222 | tristate | 265 | tristate |
266 | |||
267 | config SND_SOC_TPA6130A2 | ||
268 | tristate | ||
269 | |||
270 | config SND_SOC_WM2000 | ||
271 | tristate | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fb4af28486ba..dd5ce6df6292 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -3,11 +3,14 @@ snd-soc-ad1836-objs := ad1836.o | |||
3 | snd-soc-ad1938-objs := ad1938.o | 3 | snd-soc-ad1938-objs := ad1938.o |
4 | snd-soc-ad1980-objs := ad1980.o | 4 | snd-soc-ad1980-objs := ad1980.o |
5 | snd-soc-ad73311-objs := ad73311.o | 5 | snd-soc-ad73311-objs := ad73311.o |
6 | snd-soc-ads117x-objs := ads117x.o | ||
6 | snd-soc-ak4104-objs := ak4104.o | 7 | snd-soc-ak4104-objs := ak4104.o |
7 | snd-soc-ak4535-objs := ak4535.o | 8 | snd-soc-ak4535-objs := ak4535.o |
8 | snd-soc-ak4642-objs := ak4642.o | 9 | snd-soc-ak4642-objs := ak4642.o |
10 | snd-soc-ak4671-objs := ak4671.o | ||
9 | snd-soc-cs4270-objs := cs4270.o | 11 | snd-soc-cs4270-objs := cs4270.o |
10 | snd-soc-cx20442-objs := cx20442.o | 12 | snd-soc-cx20442-objs := cx20442.o |
13 | snd-soc-da7210-objs := da7210.o | ||
11 | snd-soc-l3-objs := l3.o | 14 | snd-soc-l3-objs := l3.o |
12 | snd-soc-pcm3008-objs := pcm3008.o | 15 | snd-soc-pcm3008-objs := pcm3008.o |
13 | snd-soc-spdif-objs := spdif_transciever.o | 16 | snd-soc-spdif-objs := spdif_transciever.o |
@@ -16,6 +19,7 @@ snd-soc-stac9766-objs := stac9766.o | |||
16 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 19 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
17 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 20 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
18 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 21 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o |
22 | snd-soc-tlv320dac33-objs := tlv320dac33.o | ||
19 | snd-soc-twl4030-objs := twl4030.o | 23 | snd-soc-twl4030-objs := twl4030.o |
20 | snd-soc-uda134x-objs := uda134x.o | 24 | snd-soc-uda134x-objs := uda134x.o |
21 | snd-soc-uda1380-objs := uda1380.o | 25 | snd-soc-uda1380-objs := uda1380.o |
@@ -24,6 +28,8 @@ snd-soc-wm8400-objs := wm8400.o | |||
24 | snd-soc-wm8510-objs := wm8510.o | 28 | snd-soc-wm8510-objs := wm8510.o |
25 | snd-soc-wm8523-objs := wm8523.o | 29 | snd-soc-wm8523-objs := wm8523.o |
26 | snd-soc-wm8580-objs := wm8580.o | 30 | snd-soc-wm8580-objs := wm8580.o |
31 | snd-soc-wm8711-objs := wm8711.o | ||
32 | snd-soc-wm8727-objs := wm8727.o | ||
27 | snd-soc-wm8728-objs := wm8728.o | 33 | snd-soc-wm8728-objs := wm8728.o |
28 | snd-soc-wm8731-objs := wm8731.o | 34 | snd-soc-wm8731-objs := wm8731.o |
29 | snd-soc-wm8750-objs := wm8750.o | 35 | snd-soc-wm8750-objs := wm8750.o |
@@ -31,14 +37,18 @@ snd-soc-wm8753-objs := wm8753.o | |||
31 | snd-soc-wm8776-objs := wm8776.o | 37 | snd-soc-wm8776-objs := wm8776.o |
32 | snd-soc-wm8900-objs := wm8900.o | 38 | snd-soc-wm8900-objs := wm8900.o |
33 | snd-soc-wm8903-objs := wm8903.o | 39 | snd-soc-wm8903-objs := wm8903.o |
40 | snd-soc-wm8904-objs := wm8904.o | ||
34 | snd-soc-wm8940-objs := wm8940.o | 41 | snd-soc-wm8940-objs := wm8940.o |
42 | snd-soc-wm8955-objs := wm8955.o | ||
35 | snd-soc-wm8960-objs := wm8960.o | 43 | snd-soc-wm8960-objs := wm8960.o |
36 | snd-soc-wm8961-objs := wm8961.o | 44 | snd-soc-wm8961-objs := wm8961.o |
37 | snd-soc-wm8971-objs := wm8971.o | 45 | snd-soc-wm8971-objs := wm8971.o |
38 | snd-soc-wm8974-objs := wm8974.o | 46 | snd-soc-wm8974-objs := wm8974.o |
47 | snd-soc-wm8978-objs := wm8978.o | ||
39 | snd-soc-wm8988-objs := wm8988.o | 48 | snd-soc-wm8988-objs := wm8988.o |
40 | snd-soc-wm8990-objs := wm8990.o | 49 | snd-soc-wm8990-objs := wm8990.o |
41 | snd-soc-wm8993-objs := wm8993.o | 50 | snd-soc-wm8993-objs := wm8993.o |
51 | snd-soc-wm8994-objs := wm8994.o | ||
42 | snd-soc-wm9081-objs := wm9081.o | 52 | snd-soc-wm9081-objs := wm9081.o |
43 | snd-soc-wm9705-objs := wm9705.o | 53 | snd-soc-wm9705-objs := wm9705.o |
44 | snd-soc-wm9712-objs := wm9712.o | 54 | snd-soc-wm9712-objs := wm9712.o |
@@ -47,17 +57,22 @@ snd-soc-wm-hubs-objs := wm_hubs.o | |||
47 | 57 | ||
48 | # Amp | 58 | # Amp |
49 | snd-soc-max9877-objs := max9877.o | 59 | snd-soc-max9877-objs := max9877.o |
60 | snd-soc-tpa6130a2-objs := tpa6130a2.o | ||
61 | snd-soc-wm2000-objs := wm2000.o | ||
50 | 62 | ||
51 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 63 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
52 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | 64 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o |
53 | obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o | 65 | obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o |
54 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 66 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
55 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 67 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
68 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | ||
56 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 69 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
57 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 70 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
58 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 71 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
72 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | ||
59 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 73 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
60 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 74 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
75 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | ||
61 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 76 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
62 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 77 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
63 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 78 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o |
@@ -66,6 +81,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | |||
66 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 81 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
67 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 82 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
68 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 83 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o |
84 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o | ||
69 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 85 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
70 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 86 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
71 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 87 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
@@ -74,6 +90,8 @@ obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o | |||
74 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o | 90 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
75 | obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o | 91 | obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o |
76 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o | 92 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o |
93 | obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o | ||
94 | obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o | ||
77 | obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o | 95 | obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o |
78 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o | 96 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o |
79 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o | 97 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o |
@@ -81,14 +99,18 @@ obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o | |||
81 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o | 99 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o |
82 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o | 100 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o |
83 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o | 101 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o |
84 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o | 102 | obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o |
85 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o | ||
86 | obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o | 103 | obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o |
104 | obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o | ||
87 | obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o | 105 | obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o |
88 | obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o | 106 | obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o |
107 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o | ||
108 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o | ||
109 | obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o | ||
89 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o | 110 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o |
90 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o | 111 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o |
91 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o | 112 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o |
113 | obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o | ||
92 | obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o | 114 | obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o |
93 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o | 115 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o |
94 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o | 116 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o |
@@ -97,3 +119,5 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o | |||
97 | 119 | ||
98 | # Amp | 120 | # Amp |
99 | obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o | 121 | obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o |
122 | obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o | ||
123 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | ||
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 932299bb5d1e..1f5e57a4bb7a 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
17 | #include <linux/device.h> | 18 | #include <linux/device.h> |
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
@@ -80,9 +81,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
80 | static int ac97_soc_probe(struct platform_device *pdev) | 81 | static int ac97_soc_probe(struct platform_device *pdev) |
81 | { | 82 | { |
82 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 83 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
84 | struct snd_soc_card *card = socdev->card; | ||
83 | struct snd_soc_codec *codec; | 85 | struct snd_soc_codec *codec; |
84 | struct snd_ac97_bus *ac97_bus; | 86 | struct snd_ac97_bus *ac97_bus; |
85 | struct snd_ac97_template ac97_template; | 87 | struct snd_ac97_template ac97_template; |
88 | int i; | ||
86 | int ret = 0; | 89 | int ret = 0; |
87 | 90 | ||
88 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); | 91 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); |
@@ -117,9 +120,13 @@ static int ac97_soc_probe(struct platform_device *pdev) | |||
117 | if (ret < 0) | 120 | if (ret < 0) |
118 | goto bus_err; | 121 | goto bus_err; |
119 | 122 | ||
120 | ret = snd_soc_init_card(socdev); | 123 | for (i = 0; i < card->num_links; i++) { |
121 | if (ret < 0) | 124 | if (card->dai_link[i].codec_dai->ac97_control) { |
122 | goto bus_err; | 125 | snd_ac97_dev_add_pdata(codec->ac97, |
126 | card->dai_link[i].cpu_dai->ac97_pdata); | ||
127 | } | ||
128 | } | ||
129 | |||
123 | return 0; | 130 | return 0; |
124 | 131 | ||
125 | bus_err: | 132 | bus_err: |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c48485f2c55d..11b62dee842c 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
22 | #include <linux/device.h> | 23 | #include <linux/device.h> |
@@ -171,57 +172,35 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
171 | return 0; | 172 | return 0; |
172 | } | 173 | } |
173 | 174 | ||
174 | 175 | #ifdef CONFIG_PM | |
175 | /* | 176 | static int ad1836_soc_suspend(struct platform_device *pdev, |
176 | * interface to read/write ad1836 register | 177 | pm_message_t state) |
177 | */ | ||
178 | #define AD1836_SPI_REG_SHFT 12 | ||
179 | #define AD1836_SPI_READ (1 << 11) | ||
180 | #define AD1836_SPI_VAL_MSK 0x3FF | ||
181 | |||
182 | /* | ||
183 | * write to the ad1836 register space | ||
184 | */ | ||
185 | |||
186 | static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg, | ||
187 | unsigned int value) | ||
188 | { | 178 | { |
189 | u16 *reg_cache = codec->reg_cache; | 179 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
190 | int ret = 0; | 180 | struct snd_soc_codec *codec = socdev->card->codec; |
191 | 181 | ||
192 | if (value != reg_cache[reg]) { | 182 | /* reset clock control mode */ |
193 | unsigned short buf; | 183 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
194 | struct spi_transfer t = { | 184 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
195 | .tx_buf = &buf, | ||
196 | .len = 2, | ||
197 | }; | ||
198 | struct spi_message m; | ||
199 | |||
200 | buf = (reg << AD1836_SPI_REG_SHFT) | | ||
201 | (value & AD1836_SPI_VAL_MSK); | ||
202 | spi_message_init(&m); | ||
203 | spi_message_add_tail(&t, &m); | ||
204 | ret = spi_sync(codec->control_data, &m); | ||
205 | if (ret == 0) | ||
206 | reg_cache[reg] = value; | ||
207 | } | ||
208 | 185 | ||
209 | return ret; | 186 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
210 | } | 187 | } |
211 | 188 | ||
212 | /* | 189 | static int ad1836_soc_resume(struct platform_device *pdev) |
213 | * read from the ad1836 register space cache | ||
214 | */ | ||
215 | static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec, | ||
216 | unsigned int reg) | ||
217 | { | 190 | { |
218 | u16 *reg_cache = codec->reg_cache; | 191 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
192 | struct snd_soc_codec *codec = socdev->card->codec; | ||
219 | 193 | ||
220 | if (reg >= codec->reg_cache_size) | 194 | /* restore clock control mode */ |
221 | return -EINVAL; | 195 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
196 | adc_ctrl2 |= AD1836_ADC_AUX; | ||
222 | 197 | ||
223 | return reg_cache[reg]; | 198 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
224 | } | 199 | } |
200 | #else | ||
201 | #define ad1836_soc_suspend NULL | ||
202 | #define ad1836_soc_resume NULL | ||
203 | #endif | ||
225 | 204 | ||
226 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | 205 | static int __devinit ad1836_spi_probe(struct spi_device *spi) |
227 | { | 206 | { |
@@ -306,32 +285,38 @@ static int ad1836_register(struct ad1836_priv *ad1836) | |||
306 | codec->owner = THIS_MODULE; | 285 | codec->owner = THIS_MODULE; |
307 | codec->dai = &ad1836_dai; | 286 | codec->dai = &ad1836_dai; |
308 | codec->num_dai = 1; | 287 | codec->num_dai = 1; |
309 | codec->write = ad1836_write_reg; | ||
310 | codec->read = ad1836_read_reg_cache; | ||
311 | INIT_LIST_HEAD(&codec->dapm_widgets); | 288 | INIT_LIST_HEAD(&codec->dapm_widgets); |
312 | INIT_LIST_HEAD(&codec->dapm_paths); | 289 | INIT_LIST_HEAD(&codec->dapm_paths); |
313 | 290 | ||
314 | ad1836_dai.dev = codec->dev; | 291 | ad1836_dai.dev = codec->dev; |
315 | ad1836_codec = codec; | 292 | ad1836_codec = codec; |
316 | 293 | ||
294 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | ||
295 | if (ret < 0) { | ||
296 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
297 | ret); | ||
298 | kfree(ad1836); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
317 | /* default setting for ad1836 */ | 302 | /* default setting for ad1836 */ |
318 | /* de-emphasis: 48kHz, power-on dac */ | 303 | /* de-emphasis: 48kHz, power-on dac */ |
319 | codec->write(codec, AD1836_DAC_CTRL1, 0x300); | 304 | snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); |
320 | /* unmute dac channels */ | 305 | /* unmute dac channels */ |
321 | codec->write(codec, AD1836_DAC_CTRL2, 0x0); | 306 | snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); |
322 | /* high-pass filter enable, power-on adc */ | 307 | /* high-pass filter enable, power-on adc */ |
323 | codec->write(codec, AD1836_ADC_CTRL1, 0x100); | 308 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); |
324 | /* unmute adc channles, adc aux mode */ | 309 | /* unmute adc channles, adc aux mode */ |
325 | codec->write(codec, AD1836_ADC_CTRL2, 0x180); | 310 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); |
326 | /* left/right diff:PGA/MUX */ | 311 | /* left/right diff:PGA/MUX */ |
327 | codec->write(codec, AD1836_ADC_CTRL3, 0x3A); | 312 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); |
328 | /* volume */ | 313 | /* volume */ |
329 | codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF); | 314 | snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); |
330 | codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF); | 315 | snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); |
331 | codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF); | 316 | snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); |
332 | codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF); | 317 | snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); |
333 | codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 318 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); |
334 | codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 319 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); |
335 | 320 | ||
336 | ret = snd_soc_register_codec(codec); | 321 | ret = snd_soc_register_codec(codec); |
337 | if (ret != 0) { | 322 | if (ret != 0) { |
@@ -385,19 +370,7 @@ static int ad1836_probe(struct platform_device *pdev) | |||
385 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, | 370 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, |
386 | ARRAY_SIZE(ad1836_dapm_widgets)); | 371 | ARRAY_SIZE(ad1836_dapm_widgets)); |
387 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 372 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
388 | snd_soc_dapm_new_widgets(codec); | ||
389 | 373 | ||
390 | ret = snd_soc_init_card(socdev); | ||
391 | if (ret < 0) { | ||
392 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
393 | goto card_err; | ||
394 | } | ||
395 | |||
396 | return ret; | ||
397 | |||
398 | card_err: | ||
399 | snd_soc_free_pcms(socdev); | ||
400 | snd_soc_dapm_free(socdev); | ||
401 | pcm_err: | 374 | pcm_err: |
402 | return ret; | 375 | return ret; |
403 | } | 376 | } |
@@ -416,6 +389,8 @@ static int ad1836_remove(struct platform_device *pdev) | |||
416 | struct snd_soc_codec_device soc_codec_dev_ad1836 = { | 389 | struct snd_soc_codec_device soc_codec_dev_ad1836 = { |
417 | .probe = ad1836_probe, | 390 | .probe = ad1836_probe, |
418 | .remove = ad1836_remove, | 391 | .remove = ad1836_remove, |
392 | .suspend = ad1836_soc_suspend, | ||
393 | .resume = ad1836_soc_resume, | ||
419 | }; | 394 | }; |
420 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); | 395 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); |
421 | 396 | ||
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 7660ee6973c0..e9d90d3951c5 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define AD1836_ADC_SERFMT_MASK (7 << 6) | 54 | #define AD1836_ADC_SERFMT_MASK (7 << 6) |
55 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) | 55 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) |
56 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) | 56 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) |
57 | #define AD1836_ADC_AUX (0x6 << 6) | ||
57 | 58 | ||
58 | #define AD1836_ADC_CTRL3 14 | 59 | #define AD1836_ADC_CTRL3 14 |
59 | 60 | ||
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c index 34b30efc3cb0..240cd155b313 100644 --- a/sound/soc/codecs/ad1938.c +++ b/sound/soc/codecs/ad1938.c | |||
@@ -27,6 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
32 | #include <linux/device.h> | 33 | #include <linux/device.h> |
@@ -46,6 +47,11 @@ struct ad1938_priv { | |||
46 | u8 reg_cache[AD1938_NUM_REGS]; | 47 | u8 reg_cache[AD1938_NUM_REGS]; |
47 | }; | 48 | }; |
48 | 49 | ||
50 | /* ad1938 register cache & default register settings */ | ||
51 | static const u8 ad1938_reg[AD1938_NUM_REGS] = { | ||
52 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, | ||
53 | }; | ||
54 | |||
49 | static struct snd_soc_codec *ad1938_codec; | 55 | static struct snd_soc_codec *ad1938_codec; |
50 | struct snd_soc_codec_device soc_codec_dev_ad1938; | 56 | struct snd_soc_codec_device soc_codec_dev_ad1938; |
51 | static int ad1938_register(struct ad1938_priv *ad1938); | 57 | static int ad1938_register(struct ad1938_priv *ad1938); |
@@ -97,6 +103,7 @@ static const struct snd_kcontrol_new ad1938_snd_controls[] = { | |||
97 | static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = { | 103 | static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = { |
98 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1), | 104 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1), |
99 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 105 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
106 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD1938_PLL_CLK_CTRL0, 0, 1, NULL, 0), | ||
100 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0), | 107 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0), |
101 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | 108 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), |
102 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | 109 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), |
@@ -107,6 +114,8 @@ static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = { | |||
107 | }; | 114 | }; |
108 | 115 | ||
109 | static const struct snd_soc_dapm_route audio_paths[] = { | 116 | static const struct snd_soc_dapm_route audio_paths[] = { |
117 | { "DAC", NULL, "PLL_PWR" }, | ||
118 | { "ADC", NULL, "PLL_PWR" }, | ||
110 | { "DAC", NULL, "ADC_PWR" }, | 119 | { "DAC", NULL, "ADC_PWR" }, |
111 | { "ADC", NULL, "ADC_PWR" }, | 120 | { "ADC", NULL, "ADC_PWR" }, |
112 | { "DAC1OUT", "DAC1 Switch", "DAC" }, | 121 | { "DAC1OUT", "DAC1 Switch", "DAC" }, |
@@ -126,30 +135,20 @@ static int ad1938_mute(struct snd_soc_dai *dai, int mute) | |||
126 | struct snd_soc_codec *codec = dai->codec; | 135 | struct snd_soc_codec *codec = dai->codec; |
127 | int reg; | 136 | int reg; |
128 | 137 | ||
129 | reg = codec->read(codec, AD1938_DAC_CTRL2); | 138 | reg = snd_soc_read(codec, AD1938_DAC_CTRL2); |
130 | reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg & | 139 | reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg & |
131 | (~AD1938_DAC_MASTER_MUTE); | 140 | (~AD1938_DAC_MASTER_MUTE); |
132 | codec->write(codec, AD1938_DAC_CTRL2, reg); | 141 | snd_soc_write(codec, AD1938_DAC_CTRL2, reg); |
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd) | ||
138 | { | ||
139 | int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0); | ||
140 | reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg | | ||
141 | AD1938_PLL_POWERDOWN; | ||
142 | codec->write(codec, AD1938_PLL_CLK_CTRL0, reg); | ||
143 | 142 | ||
144 | return 0; | 143 | return 0; |
145 | } | 144 | } |
146 | 145 | ||
147 | static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | 146 | static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
148 | unsigned int mask, int slots, int width) | 147 | unsigned int rx_mask, int slots, int width) |
149 | { | 148 | { |
150 | struct snd_soc_codec *codec = dai->codec; | 149 | struct snd_soc_codec *codec = dai->codec; |
151 | int dac_reg = codec->read(codec, AD1938_DAC_CTRL1); | 150 | int dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1); |
152 | int adc_reg = codec->read(codec, AD1938_ADC_CTRL2); | 151 | int adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2); |
153 | 152 | ||
154 | dac_reg &= ~AD1938_DAC_CHAN_MASK; | 153 | dac_reg &= ~AD1938_DAC_CHAN_MASK; |
155 | adc_reg &= ~AD1938_ADC_CHAN_MASK; | 154 | adc_reg &= ~AD1938_ADC_CHAN_MASK; |
@@ -175,8 +174,8 @@ static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
175 | return -EINVAL; | 174 | return -EINVAL; |
176 | } | 175 | } |
177 | 176 | ||
178 | codec->write(codec, AD1938_DAC_CTRL1, dac_reg); | 177 | snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg); |
179 | codec->write(codec, AD1938_ADC_CTRL2, adc_reg); | 178 | snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg); |
180 | 179 | ||
181 | return 0; | 180 | return 0; |
182 | } | 181 | } |
@@ -187,8 +186,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
187 | struct snd_soc_codec *codec = codec_dai->codec; | 186 | struct snd_soc_codec *codec = codec_dai->codec; |
188 | int adc_reg, dac_reg; | 187 | int adc_reg, dac_reg; |
189 | 188 | ||
190 | adc_reg = codec->read(codec, AD1938_ADC_CTRL2); | 189 | adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2); |
191 | dac_reg = codec->read(codec, AD1938_DAC_CTRL1); | 190 | dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1); |
192 | 191 | ||
193 | /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S | 192 | /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S |
194 | * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) | 193 | * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) |
@@ -265,8 +264,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
265 | return -EINVAL; | 264 | return -EINVAL; |
266 | } | 265 | } |
267 | 266 | ||
268 | codec->write(codec, AD1938_ADC_CTRL2, adc_reg); | 267 | snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg); |
269 | codec->write(codec, AD1938_DAC_CTRL1, dac_reg); | 268 | snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg); |
270 | 269 | ||
271 | return 0; | 270 | return 0; |
272 | } | 271 | } |
@@ -295,134 +294,13 @@ static int ad1938_hw_params(struct snd_pcm_substream *substream, | |||
295 | break; | 294 | break; |
296 | } | 295 | } |
297 | 296 | ||
298 | reg = codec->read(codec, AD1938_DAC_CTRL2); | 297 | reg = snd_soc_read(codec, AD1938_DAC_CTRL2); |
299 | reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len; | 298 | reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len; |
300 | codec->write(codec, AD1938_DAC_CTRL2, reg); | 299 | snd_soc_write(codec, AD1938_DAC_CTRL2, reg); |
301 | 300 | ||
302 | reg = codec->read(codec, AD1938_ADC_CTRL1); | 301 | reg = snd_soc_read(codec, AD1938_ADC_CTRL1); |
303 | reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len; | 302 | reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len; |
304 | codec->write(codec, AD1938_ADC_CTRL1, reg); | 303 | snd_soc_write(codec, AD1938_ADC_CTRL1, reg); |
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int ad1938_set_bias_level(struct snd_soc_codec *codec, | ||
310 | enum snd_soc_bias_level level) | ||
311 | { | ||
312 | switch (level) { | ||
313 | case SND_SOC_BIAS_ON: | ||
314 | ad1938_pll_powerctrl(codec, 1); | ||
315 | break; | ||
316 | case SND_SOC_BIAS_PREPARE: | ||
317 | break; | ||
318 | case SND_SOC_BIAS_STANDBY: | ||
319 | case SND_SOC_BIAS_OFF: | ||
320 | ad1938_pll_powerctrl(codec, 0); | ||
321 | break; | ||
322 | } | ||
323 | codec->bias_level = level; | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * interface to read/write ad1938 register | ||
329 | */ | ||
330 | |||
331 | #define AD1938_SPI_ADDR 0x4 | ||
332 | #define AD1938_SPI_READ 0x1 | ||
333 | #define AD1938_SPI_BUFLEN 3 | ||
334 | |||
335 | /* | ||
336 | * write to the ad1938 register space | ||
337 | */ | ||
338 | |||
339 | static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg, | ||
340 | unsigned int value) | ||
341 | { | ||
342 | u8 *reg_cache = codec->reg_cache; | ||
343 | int ret = 0; | ||
344 | |||
345 | if (value != reg_cache[reg]) { | ||
346 | uint8_t buf[AD1938_SPI_BUFLEN]; | ||
347 | struct spi_transfer t = { | ||
348 | .tx_buf = buf, | ||
349 | .len = AD1938_SPI_BUFLEN, | ||
350 | }; | ||
351 | struct spi_message m; | ||
352 | |||
353 | buf[0] = AD1938_SPI_ADDR << 1; | ||
354 | buf[1] = reg; | ||
355 | buf[2] = value; | ||
356 | spi_message_init(&m); | ||
357 | spi_message_add_tail(&t, &m); | ||
358 | ret = spi_sync(codec->control_data, &m); | ||
359 | if (ret == 0) | ||
360 | reg_cache[reg] = value; | ||
361 | } | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * read from the ad1938 register space cache | ||
368 | */ | ||
369 | |||
370 | static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec, | ||
371 | unsigned int reg) | ||
372 | { | ||
373 | u8 *reg_cache = codec->reg_cache; | ||
374 | |||
375 | if (reg >= codec->reg_cache_size) | ||
376 | return -EINVAL; | ||
377 | |||
378 | return reg_cache[reg]; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * read from the ad1938 register space | ||
383 | */ | ||
384 | |||
385 | static unsigned int ad1938_read_reg(struct snd_soc_codec *codec, | ||
386 | unsigned int reg) | ||
387 | { | ||
388 | char w_buf[AD1938_SPI_BUFLEN]; | ||
389 | char r_buf[AD1938_SPI_BUFLEN]; | ||
390 | int ret; | ||
391 | |||
392 | struct spi_transfer t = { | ||
393 | .tx_buf = w_buf, | ||
394 | .rx_buf = r_buf, | ||
395 | .len = AD1938_SPI_BUFLEN, | ||
396 | }; | ||
397 | struct spi_message m; | ||
398 | |||
399 | w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ; | ||
400 | w_buf[1] = reg; | ||
401 | w_buf[2] = 0; | ||
402 | |||
403 | spi_message_init(&m); | ||
404 | spi_message_add_tail(&t, &m); | ||
405 | ret = spi_sync(codec->control_data, &m); | ||
406 | if (ret == 0) | ||
407 | return r_buf[2]; | ||
408 | else | ||
409 | return -EIO; | ||
410 | } | ||
411 | |||
412 | static int ad1938_fill_cache(struct snd_soc_codec *codec) | ||
413 | { | ||
414 | int i; | ||
415 | u8 *reg_cache = codec->reg_cache; | ||
416 | struct spi_device *spi = codec->control_data; | ||
417 | |||
418 | for (i = 0; i < codec->reg_cache_size; i++) { | ||
419 | int ret = ad1938_read_reg(codec, i); | ||
420 | if (ret == -EIO) { | ||
421 | dev_err(&spi->dev, "AD1938 SPI read failure\n"); | ||
422 | return ret; | ||
423 | } | ||
424 | reg_cache[i] = ret; | ||
425 | } | ||
426 | 304 | ||
427 | return 0; | 305 | return 0; |
428 | } | 306 | } |
@@ -512,32 +390,37 @@ static int ad1938_register(struct ad1938_priv *ad1938) | |||
512 | codec->owner = THIS_MODULE; | 390 | codec->owner = THIS_MODULE; |
513 | codec->dai = &ad1938_dai; | 391 | codec->dai = &ad1938_dai; |
514 | codec->num_dai = 1; | 392 | codec->num_dai = 1; |
515 | codec->write = ad1938_write_reg; | ||
516 | codec->read = ad1938_read_reg_cache; | ||
517 | codec->set_bias_level = ad1938_set_bias_level; | ||
518 | INIT_LIST_HEAD(&codec->dapm_widgets); | 393 | INIT_LIST_HEAD(&codec->dapm_widgets); |
519 | INIT_LIST_HEAD(&codec->dapm_paths); | 394 | INIT_LIST_HEAD(&codec->dapm_paths); |
520 | 395 | ||
521 | ad1938_dai.dev = codec->dev; | 396 | ad1938_dai.dev = codec->dev; |
522 | ad1938_codec = codec; | 397 | ad1938_codec = codec; |
523 | 398 | ||
399 | memcpy(codec->reg_cache, ad1938_reg, AD1938_NUM_REGS); | ||
400 | |||
401 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_SPI); | ||
402 | if (ret < 0) { | ||
403 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
404 | ret); | ||
405 | kfree(ad1938); | ||
406 | return ret; | ||
407 | } | ||
408 | |||
524 | /* default setting for ad1938 */ | 409 | /* default setting for ad1938 */ |
525 | 410 | ||
526 | /* unmute dac channels */ | 411 | /* unmute dac channels */ |
527 | codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0); | 412 | snd_soc_write(codec, AD1938_DAC_CHNL_MUTE, 0x0); |
528 | /* de-emphasis: 48kHz, powedown dac */ | 413 | /* de-emphasis: 48kHz, powedown dac */ |
529 | codec->write(codec, AD1938_DAC_CTRL2, 0x1A); | 414 | snd_soc_write(codec, AD1938_DAC_CTRL2, 0x1A); |
530 | /* powerdown dac, dac in tdm mode */ | 415 | /* powerdown dac, dac in tdm mode */ |
531 | codec->write(codec, AD1938_DAC_CTRL0, 0x41); | 416 | snd_soc_write(codec, AD1938_DAC_CTRL0, 0x41); |
532 | /* high-pass filter enable */ | 417 | /* high-pass filter enable */ |
533 | codec->write(codec, AD1938_ADC_CTRL0, 0x3); | 418 | snd_soc_write(codec, AD1938_ADC_CTRL0, 0x3); |
534 | /* sata delay=1, adc aux mode */ | 419 | /* sata delay=1, adc aux mode */ |
535 | codec->write(codec, AD1938_ADC_CTRL1, 0x43); | 420 | snd_soc_write(codec, AD1938_ADC_CTRL1, 0x43); |
536 | /* pll input: mclki/xi */ | 421 | /* pll input: mclki/xi */ |
537 | codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); | 422 | snd_soc_write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); |
538 | codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04); | 423 | snd_soc_write(codec, AD1938_PLL_CLK_CTRL1, 0x04); |
539 | |||
540 | ad1938_fill_cache(codec); | ||
541 | 424 | ||
542 | ret = snd_soc_register_codec(codec); | 425 | ret = snd_soc_register_codec(codec); |
543 | if (ret != 0) { | 426 | if (ret != 0) { |
@@ -559,7 +442,6 @@ static int ad1938_register(struct ad1938_priv *ad1938) | |||
559 | 442 | ||
560 | static void ad1938_unregister(struct ad1938_priv *ad1938) | 443 | static void ad1938_unregister(struct ad1938_priv *ad1938) |
561 | { | 444 | { |
562 | ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF); | ||
563 | snd_soc_unregister_dai(&ad1938_dai); | 445 | snd_soc_unregister_dai(&ad1938_dai); |
564 | snd_soc_unregister_codec(&ad1938->codec); | 446 | snd_soc_unregister_codec(&ad1938->codec); |
565 | kfree(ad1938); | 447 | kfree(ad1938); |
@@ -592,21 +474,8 @@ static int ad1938_probe(struct platform_device *pdev) | |||
592 | snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, | 474 | snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, |
593 | ARRAY_SIZE(ad1938_dapm_widgets)); | 475 | ARRAY_SIZE(ad1938_dapm_widgets)); |
594 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 476 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
595 | snd_soc_dapm_new_widgets(codec); | ||
596 | 477 | ||
597 | ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
598 | 478 | ||
599 | ret = snd_soc_init_card(socdev); | ||
600 | if (ret < 0) { | ||
601 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
602 | goto card_err; | ||
603 | } | ||
604 | |||
605 | return ret; | ||
606 | |||
607 | card_err: | ||
608 | snd_soc_free_pcms(socdev); | ||
609 | snd_soc_dapm_free(socdev); | ||
610 | pcm_err: | 479 | pcm_err: |
611 | return ret; | 480 | return ret; |
612 | } | 481 | } |
@@ -622,37 +491,9 @@ static int ad1938_remove(struct platform_device *pdev) | |||
622 | return 0; | 491 | return 0; |
623 | } | 492 | } |
624 | 493 | ||
625 | #ifdef CONFIG_PM | ||
626 | static int ad1938_suspend(struct platform_device *pdev, | ||
627 | pm_message_t state) | ||
628 | { | ||
629 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
630 | struct snd_soc_codec *codec = socdev->card->codec; | ||
631 | |||
632 | ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static int ad1938_resume(struct platform_device *pdev) | ||
637 | { | ||
638 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
639 | struct snd_soc_codec *codec = socdev->card->codec; | ||
640 | |||
641 | if (codec->suspend_bias_level == SND_SOC_BIAS_ON) | ||
642 | ad1938_set_bias_level(codec, SND_SOC_BIAS_ON); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | #else | ||
647 | #define ad1938_suspend NULL | ||
648 | #define ad1938_resume NULL | ||
649 | #endif | ||
650 | |||
651 | struct snd_soc_codec_device soc_codec_dev_ad1938 = { | 494 | struct snd_soc_codec_device soc_codec_dev_ad1938 = { |
652 | .probe = ad1938_probe, | 495 | .probe = ad1938_probe, |
653 | .remove = ad1938_remove, | 496 | .remove = ad1938_remove, |
654 | .suspend = ad1938_suspend, | ||
655 | .resume = ad1938_resume, | ||
656 | }; | 497 | }; |
657 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938); | 498 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938); |
658 | 499 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index d7440a982d22..042072738cdc 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
17 | #include <linux/device.h> | 18 | #include <linux/device.h> |
@@ -257,11 +258,6 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
257 | 258 | ||
258 | snd_soc_add_controls(codec, ad1980_snd_ac97_controls, | 259 | snd_soc_add_controls(codec, ad1980_snd_ac97_controls, |
259 | ARRAY_SIZE(ad1980_snd_ac97_controls)); | 260 | ARRAY_SIZE(ad1980_snd_ac97_controls)); |
260 | ret = snd_soc_init_card(socdev); | ||
261 | if (ret < 0) { | ||
262 | printk(KERN_ERR "ad1980: failed to register card\n"); | ||
263 | goto reset_err; | ||
264 | } | ||
265 | 261 | ||
266 | return 0; | 262 | return 0; |
267 | 263 | ||
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index e61dac5e7b8f..475807bea2c2 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
@@ -64,16 +65,8 @@ static int ad73311_soc_probe(struct platform_device *pdev) | |||
64 | goto pcm_err; | 65 | goto pcm_err; |
65 | } | 66 | } |
66 | 67 | ||
67 | ret = snd_soc_init_card(socdev); | ||
68 | if (ret < 0) { | ||
69 | printk(KERN_ERR "ad73311: failed to register card\n"); | ||
70 | goto register_err; | ||
71 | } | ||
72 | |||
73 | return ret; | 68 | return ret; |
74 | 69 | ||
75 | register_err: | ||
76 | snd_soc_free_pcms(socdev); | ||
77 | pcm_err: | 70 | pcm_err: |
78 | kfree(socdev->card->codec); | 71 | kfree(socdev->card->codec); |
79 | socdev->card->codec = NULL; | 72 | socdev->card->codec = NULL; |
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c new file mode 100644 index 000000000000..f8e75edb27b7 --- /dev/null +++ b/sound/soc/codecs/ads117x.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * ads117x.c -- Driver for ads1174/8 ADC chips | ||
3 | * | ||
4 | * Copyright 2009 ShotSpotter Inc. | ||
5 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/initval.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "ads117x.h" | ||
23 | |||
24 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) | ||
25 | |||
26 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | ||
27 | |||
28 | struct snd_soc_dai ads117x_dai = { | ||
29 | /* ADC */ | ||
30 | .name = "ADS117X ADC", | ||
31 | .id = 1, | ||
32 | .capture = { | ||
33 | .stream_name = "Capture", | ||
34 | .channels_min = 1, | ||
35 | .channels_max = 32, | ||
36 | .rates = ADS117X_RATES, | ||
37 | .formats = ADS117X_FORMATS,}, | ||
38 | }; | ||
39 | EXPORT_SYMBOL_GPL(ads117x_dai); | ||
40 | |||
41 | static int ads117x_probe(struct platform_device *pdev) | ||
42 | { | ||
43 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
44 | struct snd_soc_codec *codec; | ||
45 | int ret; | ||
46 | |||
47 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
48 | if (codec == NULL) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | socdev->card->codec = codec; | ||
52 | mutex_init(&codec->mutex); | ||
53 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
54 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
55 | codec->name = "ADS117X"; | ||
56 | codec->owner = THIS_MODULE; | ||
57 | codec->dai = &ads117x_dai; | ||
58 | codec->num_dai = 1; | ||
59 | |||
60 | /* register pcms */ | ||
61 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
62 | if (ret < 0) { | ||
63 | printk(KERN_ERR "ads117x: failed to create pcms\n"); | ||
64 | kfree(codec); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int ads117x_remove(struct platform_device *pdev) | ||
72 | { | ||
73 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
74 | struct snd_soc_codec *codec = socdev->card->codec; | ||
75 | |||
76 | snd_soc_free_pcms(socdev); | ||
77 | kfree(codec); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | struct snd_soc_codec_device soc_codec_dev_ads117x = { | ||
83 | .probe = ads117x_probe, | ||
84 | .remove = ads117x_remove, | ||
85 | }; | ||
86 | EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x); | ||
87 | |||
88 | static __devinit int ads117x_platform_probe(struct platform_device *pdev) | ||
89 | { | ||
90 | ads117x_dai.dev = &pdev->dev; | ||
91 | return snd_soc_register_dai(&ads117x_dai); | ||
92 | } | ||
93 | |||
94 | static int __devexit ads117x_platform_remove(struct platform_device *pdev) | ||
95 | { | ||
96 | snd_soc_unregister_dai(&ads117x_dai); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct platform_driver ads117x_codec_driver = { | ||
101 | .driver = { | ||
102 | .name = "ads117x", | ||
103 | .owner = THIS_MODULE, | ||
104 | }, | ||
105 | |||
106 | .probe = ads117x_platform_probe, | ||
107 | .remove = __devexit_p(ads117x_platform_remove), | ||
108 | }; | ||
109 | |||
110 | static int __init ads117x_init(void) | ||
111 | { | ||
112 | return platform_driver_register(&ads117x_codec_driver); | ||
113 | } | ||
114 | module_init(ads117x_init); | ||
115 | |||
116 | static void __exit ads117x_exit(void) | ||
117 | { | ||
118 | platform_driver_unregister(&ads117x_codec_driver); | ||
119 | } | ||
120 | module_exit(ads117x_exit); | ||
121 | |||
122 | MODULE_DESCRIPTION("ASoC ads117x driver"); | ||
123 | MODULE_AUTHOR("Graeme Gregory"); | ||
124 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h new file mode 100644 index 000000000000..dbcf50ec9bd1 --- /dev/null +++ b/sound/soc/codecs/ads117x.h | |||
@@ -0,0 +1,13 @@ | |||
1 | /* | ||
2 | * ads117x.h -- Driver for ads1174/8 ADC chips | ||
3 | * | ||
4 | * Copyright 2009 ShotSpotter Inc. | ||
5 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | extern struct snd_soc_dai ads117x_dai; | ||
13 | extern struct snd_soc_codec_device soc_codec_dev_ads117x; | ||
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 4d47bc4f7428..bdeb10dfd887 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | ||
13 | #include <sound/core.h> | 14 | #include <sound/core.h> |
14 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
15 | #include <sound/initval.h> | 16 | #include <sound/initval.h> |
@@ -90,12 +91,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, | |||
90 | if (reg >= codec->reg_cache_size) | 91 | if (reg >= codec->reg_cache_size) |
91 | return -EINVAL; | 92 | return -EINVAL; |
92 | 93 | ||
93 | reg &= AK4104_REG_MASK; | ||
94 | reg |= AK4104_WRITE; | ||
95 | |||
96 | /* only write to the hardware if value has changed */ | 94 | /* only write to the hardware if value has changed */ |
97 | if (cache[reg] != value) { | 95 | if (cache[reg] != value) { |
98 | u8 tmp[2] = { reg, value }; | 96 | u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value }; |
97 | |||
99 | if (spi_write(spi, tmp, sizeof(tmp))) { | 98 | if (spi_write(spi, tmp, sizeof(tmp))) { |
100 | dev_err(&spi->dev, "SPI write failed\n"); | 99 | dev_err(&spi->dev, "SPI write failed\n"); |
101 | return -EIO; | 100 | return -EIO; |
@@ -185,9 +184,7 @@ struct snd_soc_dai ak4104_dai = { | |||
185 | .stream_name = "Playback", | 184 | .stream_name = "Playback", |
186 | .channels_min = 2, | 185 | .channels_min = 2, |
187 | .channels_max = 2, | 186 | .channels_max = 2, |
188 | .rates = SNDRV_PCM_RATE_44100 | | 187 | .rates = SNDRV_PCM_RATE_8000_192000, |
189 | SNDRV_PCM_RATE_48000 | | ||
190 | SNDRV_PCM_RATE_32000, | ||
191 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 188 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
192 | SNDRV_PCM_FMTBIT_S24_3LE | | 189 | SNDRV_PCM_FMTBIT_S24_3LE | |
193 | SNDRV_PCM_FMTBIT_S24_LE | 190 | SNDRV_PCM_FMTBIT_S24_LE |
@@ -313,14 +310,6 @@ static int ak4104_probe(struct platform_device *pdev) | |||
313 | return ret; | 310 | return ret; |
314 | } | 311 | } |
315 | 312 | ||
316 | /* Register the socdev */ | ||
317 | ret = snd_soc_init_card(socdev); | ||
318 | if (ret < 0) { | ||
319 | dev_err(codec->dev, "failed to register card\n"); | ||
320 | snd_soc_free_pcms(socdev); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | return 0; | 313 | return 0; |
325 | } | 314 | } |
326 | 315 | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 0abec0d29a96..352d1d08dbd9 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -294,7 +295,6 @@ static int ak4535_add_widgets(struct snd_soc_codec *codec) | |||
294 | 295 | ||
295 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 296 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
296 | 297 | ||
297 | snd_soc_dapm_new_widgets(codec); | ||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
@@ -485,17 +485,9 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
485 | snd_soc_add_controls(codec, ak4535_snd_controls, | 485 | snd_soc_add_controls(codec, ak4535_snd_controls, |
486 | ARRAY_SIZE(ak4535_snd_controls)); | 486 | ARRAY_SIZE(ak4535_snd_controls)); |
487 | ak4535_add_widgets(codec); | 487 | ak4535_add_widgets(codec); |
488 | ret = snd_soc_init_card(socdev); | ||
489 | if (ret < 0) { | ||
490 | printk(KERN_ERR "ak4535: failed to register card\n"); | ||
491 | goto card_err; | ||
492 | } | ||
493 | 488 | ||
494 | return ret; | 489 | return ret; |
495 | 490 | ||
496 | card_err: | ||
497 | snd_soc_free_pcms(socdev); | ||
498 | snd_soc_dapm_free(socdev); | ||
499 | pcm_err: | 491 | pcm_err: |
500 | kfree(codec->reg_cache); | 492 | kfree(codec->reg_cache); |
501 | 493 | ||
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index e057c7b578df..729859cf6ca8 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/slab.h> | ||
32 | #include <sound/core.h> | 33 | #include <sound/core.h> |
33 | #include <sound/pcm.h> | 34 | #include <sound/pcm.h> |
34 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
@@ -442,18 +443,9 @@ static int ak4642_probe(struct platform_device *pdev) | |||
442 | goto pcm_err; | 443 | goto pcm_err; |
443 | } | 444 | } |
444 | 445 | ||
445 | ret = snd_soc_init_card(socdev); | ||
446 | if (ret < 0) { | ||
447 | printk(KERN_ERR "ak4642: failed to register card\n"); | ||
448 | goto card_err; | ||
449 | } | ||
450 | |||
451 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); | 446 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); |
452 | return ret; | 447 | return ret; |
453 | 448 | ||
454 | card_err: | ||
455 | snd_soc_free_pcms(socdev); | ||
456 | snd_soc_dapm_free(socdev); | ||
457 | pcm_err: | 449 | pcm_err: |
458 | return ret; | 450 | return ret; |
459 | 451 | ||
@@ -479,7 +471,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); | |||
479 | 471 | ||
480 | static int __init ak4642_modinit(void) | 472 | static int __init ak4642_modinit(void) |
481 | { | 473 | { |
482 | int ret; | 474 | int ret = 0; |
483 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 475 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
484 | ret = i2c_add_driver(&ak4642_i2c_driver); | 476 | ret = i2c_add_driver(&ak4642_i2c_driver); |
485 | #endif | 477 | #endif |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c new file mode 100644 index 000000000000..926797a014c7 --- /dev/null +++ b/sound/soc/codecs/ak4671.c | |||
@@ -0,0 +1,816 @@ | |||
1 | /* | ||
2 | * ak4671.c -- audio driver for AK4671 | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include <sound/soc-dapm.h> | ||
21 | #include <sound/initval.h> | ||
22 | #include <sound/tlv.h> | ||
23 | |||
24 | #include "ak4671.h" | ||
25 | |||
26 | static struct snd_soc_codec *ak4671_codec; | ||
27 | |||
28 | /* codec private data */ | ||
29 | struct ak4671_priv { | ||
30 | struct snd_soc_codec codec; | ||
31 | u8 reg_cache[AK4671_CACHEREGNUM]; | ||
32 | }; | ||
33 | |||
34 | /* ak4671 register cache & default register settings */ | ||
35 | static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { | ||
36 | 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ | ||
37 | 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ | ||
38 | 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ | ||
39 | 0x02, /* AK4671_FORMAT_SELECT (0x03) */ | ||
40 | 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ | ||
41 | 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ | ||
42 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ | ||
43 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ | ||
44 | 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ | ||
45 | 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ | ||
46 | 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ | ||
47 | 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ | ||
48 | 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ | ||
49 | 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ | ||
50 | 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ | ||
51 | 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ | ||
52 | 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ | ||
53 | 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ | ||
54 | 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ | ||
55 | 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ | ||
56 | 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ | ||
57 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ | ||
58 | 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ | ||
59 | 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ | ||
60 | 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ | ||
61 | 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ | ||
62 | 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ | ||
63 | 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ | ||
64 | 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ | ||
65 | 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ | ||
66 | 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ | ||
67 | 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ | ||
68 | 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ | ||
69 | 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ | ||
70 | 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ | ||
71 | 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ | ||
72 | 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ | ||
73 | 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ | ||
74 | 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ | ||
75 | 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ | ||
76 | 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ | ||
77 | 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ | ||
78 | 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ | ||
79 | 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ | ||
80 | 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ | ||
81 | 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ | ||
82 | 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ | ||
83 | 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ | ||
84 | 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ | ||
85 | 0x00, /* this register not used */ | ||
86 | 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ | ||
87 | 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ | ||
88 | 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ | ||
89 | 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ | ||
90 | 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ | ||
91 | 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ | ||
92 | 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ | ||
93 | 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ | ||
94 | 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ | ||
95 | 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ | ||
96 | 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ | ||
97 | 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ | ||
98 | 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ | ||
99 | 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ | ||
100 | 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ | ||
101 | 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ | ||
102 | 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ | ||
103 | 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ | ||
104 | 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ | ||
105 | 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ | ||
106 | 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ | ||
107 | 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ | ||
108 | 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ | ||
109 | 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ | ||
110 | 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ | ||
111 | 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ | ||
112 | 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ | ||
113 | 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ | ||
114 | 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ | ||
115 | 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ | ||
116 | 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ | ||
117 | 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ | ||
118 | 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ | ||
119 | 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ | ||
120 | 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ | ||
121 | 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ | ||
122 | 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ | ||
123 | 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ | ||
124 | 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ | ||
125 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ | ||
126 | 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ | ||
127 | }; | ||
128 | |||
129 | /* | ||
130 | * LOUT1/ROUT1 output volume control: | ||
131 | * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB) | ||
132 | */ | ||
133 | static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1); | ||
134 | |||
135 | /* | ||
136 | * LOUT2/ROUT2 output volume control: | ||
137 | * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB) | ||
138 | */ | ||
139 | static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1); | ||
140 | |||
141 | /* | ||
142 | * LOUT3/ROUT3 output volume control: | ||
143 | * from -6 to 3 dB in 3 dB steps | ||
144 | */ | ||
145 | static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0); | ||
146 | |||
147 | /* | ||
148 | * Mic amp gain control: | ||
149 | * from -15 to 30 dB in 3 dB steps | ||
150 | * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not | ||
151 | * available | ||
152 | */ | ||
153 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0); | ||
154 | |||
155 | static const struct snd_kcontrol_new ak4671_snd_controls[] = { | ||
156 | /* Common playback gain controls */ | ||
157 | SOC_SINGLE_TLV("Line Output1 Playback Volume", | ||
158 | AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv), | ||
159 | SOC_SINGLE_TLV("Headphone Output2 Playback Volume", | ||
160 | AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv), | ||
161 | SOC_SINGLE_TLV("Line Output3 Playback Volume", | ||
162 | AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv), | ||
163 | |||
164 | /* Common capture gain controls */ | ||
165 | SOC_DOUBLE_TLV("Mic Amp Capture Volume", | ||
166 | AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv), | ||
167 | }; | ||
168 | |||
169 | /* event handlers */ | ||
170 | static int ak4671_out2_event(struct snd_soc_dapm_widget *w, | ||
171 | struct snd_kcontrol *kcontrol, int event) | ||
172 | { | ||
173 | struct snd_soc_codec *codec = w->codec; | ||
174 | u8 reg; | ||
175 | |||
176 | switch (event) { | ||
177 | case SND_SOC_DAPM_POST_PMU: | ||
178 | reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); | ||
179 | reg |= AK4671_MUTEN; | ||
180 | snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); | ||
181 | break; | ||
182 | case SND_SOC_DAPM_PRE_PMD: | ||
183 | reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT); | ||
184 | reg &= ~AK4671_MUTEN; | ||
185 | snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg); | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* Output Mixers */ | ||
193 | static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = { | ||
194 | SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0), | ||
195 | SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0), | ||
196 | SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0), | ||
197 | SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0), | ||
198 | SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0), | ||
199 | SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0), | ||
200 | }; | ||
201 | |||
202 | static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = { | ||
203 | SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0), | ||
204 | SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0), | ||
205 | SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0), | ||
206 | SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0), | ||
207 | SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0), | ||
208 | SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0), | ||
209 | }; | ||
210 | |||
211 | static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = { | ||
212 | SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0), | ||
213 | SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0), | ||
214 | SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0), | ||
215 | SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0), | ||
216 | SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0), | ||
217 | SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0), | ||
218 | }; | ||
219 | |||
220 | static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = { | ||
221 | SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0), | ||
222 | SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0), | ||
223 | SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0), | ||
224 | SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0), | ||
225 | SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0), | ||
226 | SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0), | ||
227 | }; | ||
228 | |||
229 | static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = { | ||
230 | SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0), | ||
231 | SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0), | ||
232 | SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0), | ||
233 | SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0), | ||
234 | SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0), | ||
235 | SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0), | ||
236 | }; | ||
237 | |||
238 | static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { | ||
239 | SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0), | ||
240 | SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0), | ||
241 | SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0), | ||
242 | SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0), | ||
243 | SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0), | ||
244 | SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0), | ||
245 | }; | ||
246 | |||
247 | /* Input MUXs */ | ||
248 | static const char *ak4671_lin_mux_texts[] = | ||
249 | {"LIN1", "LIN2", "LIN3", "LIN4"}; | ||
250 | static const struct soc_enum ak4671_lin_mux_enum = | ||
251 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, | ||
252 | ARRAY_SIZE(ak4671_lin_mux_texts), | ||
253 | ak4671_lin_mux_texts); | ||
254 | static const struct snd_kcontrol_new ak4671_lin_mux_control = | ||
255 | SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); | ||
256 | |||
257 | static const char *ak4671_rin_mux_texts[] = | ||
258 | {"RIN1", "RIN2", "RIN3", "RIN4"}; | ||
259 | static const struct soc_enum ak4671_rin_mux_enum = | ||
260 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, | ||
261 | ARRAY_SIZE(ak4671_rin_mux_texts), | ||
262 | ak4671_rin_mux_texts); | ||
263 | static const struct snd_kcontrol_new ak4671_rin_mux_control = | ||
264 | SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); | ||
265 | |||
266 | static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = { | ||
267 | /* Inputs */ | ||
268 | SND_SOC_DAPM_INPUT("LIN1"), | ||
269 | SND_SOC_DAPM_INPUT("RIN1"), | ||
270 | SND_SOC_DAPM_INPUT("LIN2"), | ||
271 | SND_SOC_DAPM_INPUT("RIN2"), | ||
272 | SND_SOC_DAPM_INPUT("LIN3"), | ||
273 | SND_SOC_DAPM_INPUT("RIN3"), | ||
274 | SND_SOC_DAPM_INPUT("LIN4"), | ||
275 | SND_SOC_DAPM_INPUT("RIN4"), | ||
276 | |||
277 | /* Outputs */ | ||
278 | SND_SOC_DAPM_OUTPUT("LOUT1"), | ||
279 | SND_SOC_DAPM_OUTPUT("ROUT1"), | ||
280 | SND_SOC_DAPM_OUTPUT("LOUT2"), | ||
281 | SND_SOC_DAPM_OUTPUT("ROUT2"), | ||
282 | SND_SOC_DAPM_OUTPUT("LOUT3"), | ||
283 | SND_SOC_DAPM_OUTPUT("ROUT3"), | ||
284 | |||
285 | /* DAC */ | ||
286 | SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback", | ||
287 | AK4671_AD_DA_POWER_MANAGEMENT, 6, 0), | ||
288 | SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback", | ||
289 | AK4671_AD_DA_POWER_MANAGEMENT, 7, 0), | ||
290 | |||
291 | /* ADC */ | ||
292 | SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture", | ||
293 | AK4671_AD_DA_POWER_MANAGEMENT, 4, 0), | ||
294 | SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture", | ||
295 | AK4671_AD_DA_POWER_MANAGEMENT, 5, 0), | ||
296 | |||
297 | /* PGA */ | ||
298 | SND_SOC_DAPM_PGA("LOUT2 Mix Amp", | ||
299 | AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0), | ||
300 | SND_SOC_DAPM_PGA("ROUT2 Mix Amp", | ||
301 | AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0), | ||
302 | |||
303 | SND_SOC_DAPM_PGA("LIN1 Mixing Circuit", | ||
304 | AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0), | ||
305 | SND_SOC_DAPM_PGA("RIN1 Mixing Circuit", | ||
306 | AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0), | ||
307 | SND_SOC_DAPM_PGA("LIN2 Mixing Circuit", | ||
308 | AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0), | ||
309 | SND_SOC_DAPM_PGA("RIN2 Mixing Circuit", | ||
310 | AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0), | ||
311 | SND_SOC_DAPM_PGA("LIN3 Mixing Circuit", | ||
312 | AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0), | ||
313 | SND_SOC_DAPM_PGA("RIN3 Mixing Circuit", | ||
314 | AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0), | ||
315 | SND_SOC_DAPM_PGA("LIN4 Mixing Circuit", | ||
316 | AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0), | ||
317 | SND_SOC_DAPM_PGA("RIN4 Mixing Circuit", | ||
318 | AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0), | ||
319 | |||
320 | /* Output Mixers */ | ||
321 | SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0, | ||
322 | &ak4671_lout1_mixer_controls[0], | ||
323 | ARRAY_SIZE(ak4671_lout1_mixer_controls)), | ||
324 | SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0, | ||
325 | &ak4671_rout1_mixer_controls[0], | ||
326 | ARRAY_SIZE(ak4671_rout1_mixer_controls)), | ||
327 | SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, | ||
328 | 0, 0, &ak4671_lout2_mixer_controls[0], | ||
329 | ARRAY_SIZE(ak4671_lout2_mixer_controls), | ||
330 | ak4671_out2_event, | ||
331 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), | ||
332 | SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, | ||
333 | 1, 0, &ak4671_rout2_mixer_controls[0], | ||
334 | ARRAY_SIZE(ak4671_rout2_mixer_controls), | ||
335 | ak4671_out2_event, | ||
336 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), | ||
337 | SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0, | ||
338 | &ak4671_lout3_mixer_controls[0], | ||
339 | ARRAY_SIZE(ak4671_lout3_mixer_controls)), | ||
340 | SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0, | ||
341 | &ak4671_rout3_mixer_controls[0], | ||
342 | ARRAY_SIZE(ak4671_rout3_mixer_controls)), | ||
343 | |||
344 | /* Input MUXs */ | ||
345 | SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0, | ||
346 | &ak4671_lin_mux_control), | ||
347 | SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0, | ||
348 | &ak4671_rin_mux_control), | ||
349 | |||
350 | /* Mic Power */ | ||
351 | SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0), | ||
352 | |||
353 | /* Supply */ | ||
354 | SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), | ||
355 | }; | ||
356 | |||
357 | static const struct snd_soc_dapm_route intercon[] = { | ||
358 | {"DAC Left", "NULL", "PMPLL"}, | ||
359 | {"DAC Right", "NULL", "PMPLL"}, | ||
360 | {"ADC Left", "NULL", "PMPLL"}, | ||
361 | {"ADC Right", "NULL", "PMPLL"}, | ||
362 | |||
363 | /* Outputs */ | ||
364 | {"LOUT1", "NULL", "LOUT1 Mixer"}, | ||
365 | {"ROUT1", "NULL", "ROUT1 Mixer"}, | ||
366 | {"LOUT2", "NULL", "LOUT2 Mix Amp"}, | ||
367 | {"ROUT2", "NULL", "ROUT2 Mix Amp"}, | ||
368 | {"LOUT3", "NULL", "LOUT3 Mixer"}, | ||
369 | {"ROUT3", "NULL", "ROUT3 Mixer"}, | ||
370 | |||
371 | {"LOUT1 Mixer", "DACL", "DAC Left"}, | ||
372 | {"ROUT1 Mixer", "DACR", "DAC Right"}, | ||
373 | {"LOUT2 Mixer", "DACHL", "DAC Left"}, | ||
374 | {"ROUT2 Mixer", "DACHR", "DAC Right"}, | ||
375 | {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"}, | ||
376 | {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"}, | ||
377 | {"LOUT3 Mixer", "DACSL", "DAC Left"}, | ||
378 | {"ROUT3 Mixer", "DACSR", "DAC Right"}, | ||
379 | |||
380 | /* Inputs */ | ||
381 | {"LIN MUX", "LIN1", "LIN1"}, | ||
382 | {"LIN MUX", "LIN2", "LIN2"}, | ||
383 | {"LIN MUX", "LIN3", "LIN3"}, | ||
384 | {"LIN MUX", "LIN4", "LIN4"}, | ||
385 | |||
386 | {"RIN MUX", "RIN1", "RIN1"}, | ||
387 | {"RIN MUX", "RIN2", "RIN2"}, | ||
388 | {"RIN MUX", "RIN3", "RIN3"}, | ||
389 | {"RIN MUX", "RIN4", "RIN4"}, | ||
390 | |||
391 | {"LIN1", NULL, "Mic Bias"}, | ||
392 | {"RIN1", NULL, "Mic Bias"}, | ||
393 | {"LIN2", NULL, "Mic Bias"}, | ||
394 | {"RIN2", NULL, "Mic Bias"}, | ||
395 | |||
396 | {"ADC Left", "NULL", "LIN MUX"}, | ||
397 | {"ADC Right", "NULL", "RIN MUX"}, | ||
398 | |||
399 | /* Analog Loops */ | ||
400 | {"LIN1 Mixing Circuit", "NULL", "LIN1"}, | ||
401 | {"RIN1 Mixing Circuit", "NULL", "RIN1"}, | ||
402 | {"LIN2 Mixing Circuit", "NULL", "LIN2"}, | ||
403 | {"RIN2 Mixing Circuit", "NULL", "RIN2"}, | ||
404 | {"LIN3 Mixing Circuit", "NULL", "LIN3"}, | ||
405 | {"RIN3 Mixing Circuit", "NULL", "RIN3"}, | ||
406 | {"LIN4 Mixing Circuit", "NULL", "LIN4"}, | ||
407 | {"RIN4 Mixing Circuit", "NULL", "RIN4"}, | ||
408 | |||
409 | {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"}, | ||
410 | {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"}, | ||
411 | {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"}, | ||
412 | {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"}, | ||
413 | {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"}, | ||
414 | {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"}, | ||
415 | |||
416 | {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"}, | ||
417 | {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"}, | ||
418 | {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"}, | ||
419 | {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"}, | ||
420 | {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"}, | ||
421 | {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"}, | ||
422 | |||
423 | {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"}, | ||
424 | {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"}, | ||
425 | {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"}, | ||
426 | {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"}, | ||
427 | {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"}, | ||
428 | {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"}, | ||
429 | |||
430 | {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"}, | ||
431 | {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"}, | ||
432 | {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"}, | ||
433 | {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"}, | ||
434 | {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"}, | ||
435 | {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, | ||
436 | }; | ||
437 | |||
438 | static int ak4671_add_widgets(struct snd_soc_codec *codec) | ||
439 | { | ||
440 | snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets, | ||
441 | ARRAY_SIZE(ak4671_dapm_widgets)); | ||
442 | |||
443 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int ak4671_hw_params(struct snd_pcm_substream *substream, | ||
449 | struct snd_pcm_hw_params *params, | ||
450 | struct snd_soc_dai *dai) | ||
451 | { | ||
452 | struct snd_soc_codec *codec = dai->codec; | ||
453 | u8 fs; | ||
454 | |||
455 | fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); | ||
456 | fs &= ~AK4671_FS; | ||
457 | |||
458 | switch (params_rate(params)) { | ||
459 | case 8000: | ||
460 | fs |= AK4671_FS_8KHZ; | ||
461 | break; | ||
462 | case 12000: | ||
463 | fs |= AK4671_FS_12KHZ; | ||
464 | break; | ||
465 | case 16000: | ||
466 | fs |= AK4671_FS_16KHZ; | ||
467 | break; | ||
468 | case 24000: | ||
469 | fs |= AK4671_FS_24KHZ; | ||
470 | break; | ||
471 | case 11025: | ||
472 | fs |= AK4671_FS_11_025KHZ; | ||
473 | break; | ||
474 | case 22050: | ||
475 | fs |= AK4671_FS_22_05KHZ; | ||
476 | break; | ||
477 | case 32000: | ||
478 | fs |= AK4671_FS_32KHZ; | ||
479 | break; | ||
480 | case 44100: | ||
481 | fs |= AK4671_FS_44_1KHZ; | ||
482 | break; | ||
483 | case 48000: | ||
484 | fs |= AK4671_FS_48KHZ; | ||
485 | break; | ||
486 | default: | ||
487 | return -EINVAL; | ||
488 | } | ||
489 | |||
490 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
496 | unsigned int freq, int dir) | ||
497 | { | ||
498 | struct snd_soc_codec *codec = dai->codec; | ||
499 | u8 pll; | ||
500 | |||
501 | pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); | ||
502 | pll &= ~AK4671_PLL; | ||
503 | |||
504 | switch (freq) { | ||
505 | case 11289600: | ||
506 | pll |= AK4671_PLL_11_2896MHZ; | ||
507 | break; | ||
508 | case 12000000: | ||
509 | pll |= AK4671_PLL_12MHZ; | ||
510 | break; | ||
511 | case 12288000: | ||
512 | pll |= AK4671_PLL_12_288MHZ; | ||
513 | break; | ||
514 | case 13000000: | ||
515 | pll |= AK4671_PLL_13MHZ; | ||
516 | break; | ||
517 | case 13500000: | ||
518 | pll |= AK4671_PLL_13_5MHZ; | ||
519 | break; | ||
520 | case 19200000: | ||
521 | pll |= AK4671_PLL_19_2MHZ; | ||
522 | break; | ||
523 | case 24000000: | ||
524 | pll |= AK4671_PLL_24MHZ; | ||
525 | break; | ||
526 | case 26000000: | ||
527 | pll |= AK4671_PLL_26MHZ; | ||
528 | break; | ||
529 | case 27000000: | ||
530 | pll |= AK4671_PLL_27MHZ; | ||
531 | break; | ||
532 | default: | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
542 | { | ||
543 | struct snd_soc_codec *codec = dai->codec; | ||
544 | u8 mode; | ||
545 | u8 format; | ||
546 | |||
547 | /* set master/slave audio interface */ | ||
548 | mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1); | ||
549 | |||
550 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
551 | case SND_SOC_DAIFMT_CBM_CFM: | ||
552 | mode |= AK4671_M_S; | ||
553 | break; | ||
554 | case SND_SOC_DAIFMT_CBM_CFS: | ||
555 | mode &= ~(AK4671_M_S); | ||
556 | break; | ||
557 | default: | ||
558 | return -EINVAL; | ||
559 | } | ||
560 | |||
561 | /* interface format */ | ||
562 | format = snd_soc_read(codec, AK4671_FORMAT_SELECT); | ||
563 | format &= ~AK4671_DIF; | ||
564 | |||
565 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
566 | case SND_SOC_DAIFMT_I2S: | ||
567 | format |= AK4671_DIF_I2S_MODE; | ||
568 | break; | ||
569 | case SND_SOC_DAIFMT_LEFT_J: | ||
570 | format |= AK4671_DIF_MSB_MODE; | ||
571 | break; | ||
572 | case SND_SOC_DAIFMT_DSP_A: | ||
573 | format |= AK4671_DIF_DSP_MODE; | ||
574 | format |= AK4671_BCKP; | ||
575 | format |= AK4671_MSBS; | ||
576 | break; | ||
577 | default: | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | /* set mode and format */ | ||
582 | snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode); | ||
583 | snd_soc_write(codec, AK4671_FORMAT_SELECT, format); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int ak4671_set_bias_level(struct snd_soc_codec *codec, | ||
589 | enum snd_soc_bias_level level) | ||
590 | { | ||
591 | u8 reg; | ||
592 | |||
593 | switch (level) { | ||
594 | case SND_SOC_BIAS_ON: | ||
595 | case SND_SOC_BIAS_PREPARE: | ||
596 | case SND_SOC_BIAS_STANDBY: | ||
597 | reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT); | ||
598 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, | ||
599 | reg | AK4671_PMVCM); | ||
600 | break; | ||
601 | case SND_SOC_BIAS_OFF: | ||
602 | snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); | ||
603 | break; | ||
604 | } | ||
605 | codec->bias_level = level; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | #define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
610 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
611 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
612 | SNDRV_PCM_RATE_48000) | ||
613 | |||
614 | #define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
615 | |||
616 | static struct snd_soc_dai_ops ak4671_dai_ops = { | ||
617 | .hw_params = ak4671_hw_params, | ||
618 | .set_sysclk = ak4671_set_dai_sysclk, | ||
619 | .set_fmt = ak4671_set_dai_fmt, | ||
620 | }; | ||
621 | |||
622 | struct snd_soc_dai ak4671_dai = { | ||
623 | .name = "AK4671", | ||
624 | .playback = { | ||
625 | .stream_name = "Playback", | ||
626 | .channels_min = 1, | ||
627 | .channels_max = 2, | ||
628 | .rates = AK4671_RATES, | ||
629 | .formats = AK4671_FORMATS,}, | ||
630 | .capture = { | ||
631 | .stream_name = "Capture", | ||
632 | .channels_min = 1, | ||
633 | .channels_max = 2, | ||
634 | .rates = AK4671_RATES, | ||
635 | .formats = AK4671_FORMATS,}, | ||
636 | .ops = &ak4671_dai_ops, | ||
637 | }; | ||
638 | EXPORT_SYMBOL_GPL(ak4671_dai); | ||
639 | |||
640 | static int ak4671_probe(struct platform_device *pdev) | ||
641 | { | ||
642 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
643 | struct snd_soc_codec *codec; | ||
644 | int ret = 0; | ||
645 | |||
646 | if (ak4671_codec == NULL) { | ||
647 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
648 | return -ENODEV; | ||
649 | } | ||
650 | |||
651 | socdev->card->codec = ak4671_codec; | ||
652 | codec = ak4671_codec; | ||
653 | |||
654 | /* register pcms */ | ||
655 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
656 | if (ret < 0) { | ||
657 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
658 | goto pcm_err; | ||
659 | } | ||
660 | |||
661 | snd_soc_add_controls(codec, ak4671_snd_controls, | ||
662 | ARRAY_SIZE(ak4671_snd_controls)); | ||
663 | ak4671_add_widgets(codec); | ||
664 | |||
665 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
666 | |||
667 | return ret; | ||
668 | |||
669 | pcm_err: | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | static int ak4671_remove(struct platform_device *pdev) | ||
674 | { | ||
675 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
676 | |||
677 | snd_soc_free_pcms(socdev); | ||
678 | snd_soc_dapm_free(socdev); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | struct snd_soc_codec_device soc_codec_dev_ak4671 = { | ||
684 | .probe = ak4671_probe, | ||
685 | .remove = ak4671_remove, | ||
686 | }; | ||
687 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); | ||
688 | |||
689 | static int ak4671_register(struct ak4671_priv *ak4671, | ||
690 | enum snd_soc_control_type control) | ||
691 | { | ||
692 | int ret; | ||
693 | struct snd_soc_codec *codec = &ak4671->codec; | ||
694 | |||
695 | if (ak4671_codec) { | ||
696 | dev_err(codec->dev, "Another AK4671 is registered\n"); | ||
697 | ret = -EINVAL; | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | mutex_init(&codec->mutex); | ||
702 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
703 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
704 | |||
705 | codec->private_data = ak4671; | ||
706 | codec->name = "AK4671"; | ||
707 | codec->owner = THIS_MODULE; | ||
708 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
709 | codec->set_bias_level = ak4671_set_bias_level; | ||
710 | codec->dai = &ak4671_dai; | ||
711 | codec->num_dai = 1; | ||
712 | codec->reg_cache_size = AK4671_CACHEREGNUM; | ||
713 | codec->reg_cache = &ak4671->reg_cache; | ||
714 | |||
715 | memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); | ||
716 | |||
717 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); | ||
718 | if (ret < 0) { | ||
719 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | ak4671_dai.dev = codec->dev; | ||
724 | ak4671_codec = codec; | ||
725 | |||
726 | ret = snd_soc_register_codec(codec); | ||
727 | if (ret != 0) { | ||
728 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
729 | goto err; | ||
730 | } | ||
731 | |||
732 | ret = snd_soc_register_dai(&ak4671_dai); | ||
733 | if (ret != 0) { | ||
734 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
735 | goto err_codec; | ||
736 | } | ||
737 | |||
738 | return 0; | ||
739 | |||
740 | err_codec: | ||
741 | snd_soc_unregister_codec(codec); | ||
742 | err: | ||
743 | kfree(ak4671); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static void ak4671_unregister(struct ak4671_priv *ak4671) | ||
748 | { | ||
749 | ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); | ||
750 | snd_soc_unregister_dai(&ak4671_dai); | ||
751 | snd_soc_unregister_codec(&ak4671->codec); | ||
752 | kfree(ak4671); | ||
753 | ak4671_codec = NULL; | ||
754 | } | ||
755 | |||
756 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | ||
757 | const struct i2c_device_id *id) | ||
758 | { | ||
759 | struct ak4671_priv *ak4671; | ||
760 | struct snd_soc_codec *codec; | ||
761 | |||
762 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); | ||
763 | if (ak4671 == NULL) | ||
764 | return -ENOMEM; | ||
765 | |||
766 | codec = &ak4671->codec; | ||
767 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
768 | |||
769 | i2c_set_clientdata(client, ak4671); | ||
770 | codec->control_data = client; | ||
771 | |||
772 | codec->dev = &client->dev; | ||
773 | |||
774 | return ak4671_register(ak4671, SND_SOC_I2C); | ||
775 | } | ||
776 | |||
777 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) | ||
778 | { | ||
779 | struct ak4671_priv *ak4671 = i2c_get_clientdata(client); | ||
780 | |||
781 | ak4671_unregister(ak4671); | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static const struct i2c_device_id ak4671_i2c_id[] = { | ||
787 | { "ak4671", 0 }, | ||
788 | { } | ||
789 | }; | ||
790 | MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); | ||
791 | |||
792 | static struct i2c_driver ak4671_i2c_driver = { | ||
793 | .driver = { | ||
794 | .name = "ak4671", | ||
795 | .owner = THIS_MODULE, | ||
796 | }, | ||
797 | .probe = ak4671_i2c_probe, | ||
798 | .remove = __devexit_p(ak4671_i2c_remove), | ||
799 | .id_table = ak4671_i2c_id, | ||
800 | }; | ||
801 | |||
802 | static int __init ak4671_modinit(void) | ||
803 | { | ||
804 | return i2c_add_driver(&ak4671_i2c_driver); | ||
805 | } | ||
806 | module_init(ak4671_modinit); | ||
807 | |||
808 | static void __exit ak4671_exit(void) | ||
809 | { | ||
810 | i2c_del_driver(&ak4671_i2c_driver); | ||
811 | } | ||
812 | module_exit(ak4671_exit); | ||
813 | |||
814 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); | ||
815 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
816 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h new file mode 100644 index 000000000000..e2fad964e88b --- /dev/null +++ b/sound/soc/codecs/ak4671.h | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * ak4671.h -- audio driver for AK4671 | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _AK4671_H | ||
15 | #define _AK4671_H | ||
16 | |||
17 | #define AK4671_AD_DA_POWER_MANAGEMENT 0x00 | ||
18 | #define AK4671_PLL_MODE_SELECT0 0x01 | ||
19 | #define AK4671_PLL_MODE_SELECT1 0x02 | ||
20 | #define AK4671_FORMAT_SELECT 0x03 | ||
21 | #define AK4671_MIC_SIGNAL_SELECT 0x04 | ||
22 | #define AK4671_MIC_AMP_GAIN 0x05 | ||
23 | #define AK4671_MIXING_POWER_MANAGEMENT0 0x06 | ||
24 | #define AK4671_MIXING_POWER_MANAGEMENT1 0x07 | ||
25 | #define AK4671_OUTPUT_VOLUME_CONTROL 0x08 | ||
26 | #define AK4671_LOUT1_SIGNAL_SELECT 0x09 | ||
27 | #define AK4671_ROUT1_SIGNAL_SELECT 0x0a | ||
28 | #define AK4671_LOUT2_SIGNAL_SELECT 0x0b | ||
29 | #define AK4671_ROUT2_SIGNAL_SELECT 0x0c | ||
30 | #define AK4671_LOUT3_SIGNAL_SELECT 0x0d | ||
31 | #define AK4671_ROUT3_SIGNAL_SELECT 0x0e | ||
32 | #define AK4671_LOUT1_POWER_MANAGERMENT 0x0f | ||
33 | #define AK4671_LOUT2_POWER_MANAGERMENT 0x10 | ||
34 | #define AK4671_LOUT3_POWER_MANAGERMENT 0x11 | ||
35 | #define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12 | ||
36 | #define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13 | ||
37 | #define AK4671_ALC_REFERENCE_SELECT 0x14 | ||
38 | #define AK4671_DIGITAL_MIXING_CONTROL 0x15 | ||
39 | #define AK4671_ALC_TIMER_SELECT 0x16 | ||
40 | #define AK4671_ALC_MODE_CONTROL 0x17 | ||
41 | #define AK4671_MODE_CONTROL1 0x18 | ||
42 | #define AK4671_MODE_CONTROL2 0x19 | ||
43 | #define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a | ||
44 | #define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b | ||
45 | #define AK4671_SIDETONE_A_CONTROL 0x1c | ||
46 | #define AK4671_DIGITAL_FILTER_SELECT 0x1d | ||
47 | #define AK4671_FIL3_COEFFICIENT0 0x1e | ||
48 | #define AK4671_FIL3_COEFFICIENT1 0x1f | ||
49 | #define AK4671_FIL3_COEFFICIENT2 0x20 | ||
50 | #define AK4671_FIL3_COEFFICIENT3 0x21 | ||
51 | #define AK4671_EQ_COEFFICIENT0 0x22 | ||
52 | #define AK4671_EQ_COEFFICIENT1 0x23 | ||
53 | #define AK4671_EQ_COEFFICIENT2 0x24 | ||
54 | #define AK4671_EQ_COEFFICIENT3 0x25 | ||
55 | #define AK4671_EQ_COEFFICIENT4 0x26 | ||
56 | #define AK4671_EQ_COEFFICIENT5 0x27 | ||
57 | #define AK4671_FIL1_COEFFICIENT0 0x28 | ||
58 | #define AK4671_FIL1_COEFFICIENT1 0x29 | ||
59 | #define AK4671_FIL1_COEFFICIENT2 0x2a | ||
60 | #define AK4671_FIL1_COEFFICIENT3 0x2b | ||
61 | #define AK4671_FIL2_COEFFICIENT0 0x2c | ||
62 | #define AK4671_FIL2_COEFFICIENT1 0x2d | ||
63 | #define AK4671_FIL2_COEFFICIENT2 0x2e | ||
64 | #define AK4671_FIL2_COEFFICIENT3 0x2f | ||
65 | #define AK4671_DIGITAL_FILTER_SELECT2 0x30 | ||
66 | #define AK4671_E1_COEFFICIENT0 0x32 | ||
67 | #define AK4671_E1_COEFFICIENT1 0x33 | ||
68 | #define AK4671_E1_COEFFICIENT2 0x34 | ||
69 | #define AK4671_E1_COEFFICIENT3 0x35 | ||
70 | #define AK4671_E1_COEFFICIENT4 0x36 | ||
71 | #define AK4671_E1_COEFFICIENT5 0x37 | ||
72 | #define AK4671_E2_COEFFICIENT0 0x38 | ||
73 | #define AK4671_E2_COEFFICIENT1 0x39 | ||
74 | #define AK4671_E2_COEFFICIENT2 0x3a | ||
75 | #define AK4671_E2_COEFFICIENT3 0x3b | ||
76 | #define AK4671_E2_COEFFICIENT4 0x3c | ||
77 | #define AK4671_E2_COEFFICIENT5 0x3d | ||
78 | #define AK4671_E3_COEFFICIENT0 0x3e | ||
79 | #define AK4671_E3_COEFFICIENT1 0x3f | ||
80 | #define AK4671_E3_COEFFICIENT2 0x40 | ||
81 | #define AK4671_E3_COEFFICIENT3 0x41 | ||
82 | #define AK4671_E3_COEFFICIENT4 0x42 | ||
83 | #define AK4671_E3_COEFFICIENT5 0x43 | ||
84 | #define AK4671_E4_COEFFICIENT0 0x44 | ||
85 | #define AK4671_E4_COEFFICIENT1 0x45 | ||
86 | #define AK4671_E4_COEFFICIENT2 0x46 | ||
87 | #define AK4671_E4_COEFFICIENT3 0x47 | ||
88 | #define AK4671_E4_COEFFICIENT4 0x48 | ||
89 | #define AK4671_E4_COEFFICIENT5 0x49 | ||
90 | #define AK4671_E5_COEFFICIENT0 0x4a | ||
91 | #define AK4671_E5_COEFFICIENT1 0x4b | ||
92 | #define AK4671_E5_COEFFICIENT2 0x4c | ||
93 | #define AK4671_E5_COEFFICIENT3 0x4d | ||
94 | #define AK4671_E5_COEFFICIENT4 0x4e | ||
95 | #define AK4671_E5_COEFFICIENT5 0x4f | ||
96 | #define AK4671_EQ_CONTROL_250HZ_100HZ 0x50 | ||
97 | #define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51 | ||
98 | #define AK4671_EQ_CONTRO_10KHZ 0x52 | ||
99 | #define AK4671_PCM_IF_CONTROL0 0x53 | ||
100 | #define AK4671_PCM_IF_CONTROL1 0x54 | ||
101 | #define AK4671_PCM_IF_CONTROL2 0x55 | ||
102 | #define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56 | ||
103 | #define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57 | ||
104 | #define AK4671_SIDETONE_VOLUME_CONTROL 0x58 | ||
105 | #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 | ||
106 | #define AK4671_SAR_ADC_CONTROL 0x5a | ||
107 | |||
108 | #define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) | ||
109 | |||
110 | /* Bitfield Definitions */ | ||
111 | |||
112 | /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ | ||
113 | #define AK4671_PMVCM 0x01 | ||
114 | |||
115 | /* AK4671_PLL_MODE_SELECT0 (0x01) Fields */ | ||
116 | #define AK4671_PLL 0x0f | ||
117 | #define AK4671_PLL_11_2896MHZ (4 << 0) | ||
118 | #define AK4671_PLL_12_288MHZ (5 << 0) | ||
119 | #define AK4671_PLL_12MHZ (6 << 0) | ||
120 | #define AK4671_PLL_24MHZ (7 << 0) | ||
121 | #define AK4671_PLL_19_2MHZ (8 << 0) | ||
122 | #define AK4671_PLL_13_5MHZ (12 << 0) | ||
123 | #define AK4671_PLL_27MHZ (13 << 0) | ||
124 | #define AK4671_PLL_13MHZ (14 << 0) | ||
125 | #define AK4671_PLL_26MHZ (15 << 0) | ||
126 | #define AK4671_FS 0xf0 | ||
127 | #define AK4671_FS_8KHZ (0 << 4) | ||
128 | #define AK4671_FS_12KHZ (1 << 4) | ||
129 | #define AK4671_FS_16KHZ (2 << 4) | ||
130 | #define AK4671_FS_24KHZ (3 << 4) | ||
131 | #define AK4671_FS_11_025KHZ (5 << 4) | ||
132 | #define AK4671_FS_22_05KHZ (7 << 4) | ||
133 | #define AK4671_FS_32KHZ (10 << 4) | ||
134 | #define AK4671_FS_48KHZ (11 << 4) | ||
135 | #define AK4671_FS_44_1KHZ (15 << 4) | ||
136 | |||
137 | /* AK4671_PLL_MODE_SELECT1 (0x02) Fields */ | ||
138 | #define AK4671_PMPLL 0x01 | ||
139 | #define AK4671_M_S 0x02 | ||
140 | |||
141 | /* AK4671_FORMAT_SELECT (0x03) Fields */ | ||
142 | #define AK4671_DIF 0x03 | ||
143 | #define AK4671_DIF_DSP_MODE (0 << 0) | ||
144 | #define AK4671_DIF_MSB_MODE (2 << 0) | ||
145 | #define AK4671_DIF_I2S_MODE (3 << 0) | ||
146 | #define AK4671_BCKP 0x04 | ||
147 | #define AK4671_MSBS 0x08 | ||
148 | #define AK4671_SDOD 0x10 | ||
149 | |||
150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ | ||
151 | #define AK4671_MUTEN 0x04 | ||
152 | |||
153 | extern struct snd_soc_dai ak4671_dai; | ||
154 | extern struct snd_soc_codec_device soc_codec_dev_ak4671; | ||
155 | |||
156 | #endif | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index ca1e24a8f12a..81a62d198b70 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -23,11 +23,13 @@ | |||
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/slab.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
28 | #include <sound/initval.h> | 29 | #include <sound/initval.h> |
29 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
30 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/regulator/consumer.h> | ||
31 | 33 | ||
32 | #include "cs4270.h" | 34 | #include "cs4270.h" |
33 | 35 | ||
@@ -106,6 +108,10 @@ | |||
106 | #define CS4270_MUTE_DAC_A 0x01 | 108 | #define CS4270_MUTE_DAC_A 0x01 |
107 | #define CS4270_MUTE_DAC_B 0x02 | 109 | #define CS4270_MUTE_DAC_B 0x02 |
108 | 110 | ||
111 | static const char *supply_names[] = { | ||
112 | "va", "vd", "vlc" | ||
113 | }; | ||
114 | |||
109 | /* Private data for the CS4270 */ | 115 | /* Private data for the CS4270 */ |
110 | struct cs4270_private { | 116 | struct cs4270_private { |
111 | struct snd_soc_codec codec; | 117 | struct snd_soc_codec codec; |
@@ -114,6 +120,9 @@ struct cs4270_private { | |||
114 | unsigned int mode; /* The mode (I2S or left-justified) */ | 120 | unsigned int mode; /* The mode (I2S or left-justified) */ |
115 | unsigned int slave_mode; | 121 | unsigned int slave_mode; |
116 | unsigned int manual_mute; | 122 | unsigned int manual_mute; |
123 | |||
124 | /* power domain regulators */ | ||
125 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
117 | }; | 126 | }; |
118 | 127 | ||
119 | /** | 128 | /** |
@@ -192,6 +201,11 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { | |||
192 | * This function must be called by the machine driver's 'startup' function, | 201 | * This function must be called by the machine driver's 'startup' function, |
193 | * otherwise the list of supported sample rates will not be available in | 202 | * otherwise the list of supported sample rates will not be available in |
194 | * time for ALSA. | 203 | * time for ALSA. |
204 | * | ||
205 | * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause | ||
206 | * theoretically possible sample rates to be enabled. Call it again with a | ||
207 | * proper value set one the external clock is set (most probably you would do | ||
208 | * that from a machine's driver 'hw_param' hook. | ||
195 | */ | 209 | */ |
196 | static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 210 | static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
197 | int clk_id, unsigned int freq, int dir) | 211 | int clk_id, unsigned int freq, int dir) |
@@ -205,20 +219,27 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
205 | 219 | ||
206 | cs4270->mclk = freq; | 220 | cs4270->mclk = freq; |
207 | 221 | ||
208 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | 222 | if (cs4270->mclk) { |
209 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; | 223 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { |
210 | rates |= snd_pcm_rate_to_rate_bit(rate); | 224 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; |
211 | if (rate < rate_min) | 225 | rates |= snd_pcm_rate_to_rate_bit(rate); |
212 | rate_min = rate; | 226 | if (rate < rate_min) |
213 | if (rate > rate_max) | 227 | rate_min = rate; |
214 | rate_max = rate; | 228 | if (rate > rate_max) |
215 | } | 229 | rate_max = rate; |
216 | /* FIXME: soc should support a rate list */ | 230 | } |
217 | rates &= ~SNDRV_PCM_RATE_KNOT; | 231 | /* FIXME: soc should support a rate list */ |
232 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
218 | 233 | ||
219 | if (!rates) { | 234 | if (!rates) { |
220 | dev_err(codec->dev, "could not find a valid sample rate\n"); | 235 | dev_err(codec->dev, "could not find a valid sample rate\n"); |
221 | return -EINVAL; | 236 | return -EINVAL; |
237 | } | ||
238 | } else { | ||
239 | /* enable all possible rates */ | ||
240 | rates = SNDRV_PCM_RATE_8000_192000; | ||
241 | rate_min = 8000; | ||
242 | rate_max = 192000; | ||
222 | } | 243 | } |
223 | 244 | ||
224 | codec_dai->playback.rates = rates; | 245 | codec_dai->playback.rates = rates; |
@@ -520,6 +541,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { | |||
520 | SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), | 541 | SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), |
521 | SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), | 542 | SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), |
522 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), | 543 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), |
544 | SOC_SINGLE("De-emphasis filter", CS4270_TRANS, 0, 1, 0), | ||
523 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), | 545 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), |
524 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), | 546 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), |
525 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), | 547 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), |
@@ -578,7 +600,8 @@ static int cs4270_probe(struct platform_device *pdev) | |||
578 | { | 600 | { |
579 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
580 | struct snd_soc_codec *codec = cs4270_codec; | 602 | struct snd_soc_codec *codec = cs4270_codec; |
581 | int ret; | 603 | struct cs4270_private *cs4270 = codec->private_data; |
604 | int i, ret; | ||
582 | 605 | ||
583 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | 606 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ |
584 | socdev->card->codec = codec; | 607 | socdev->card->codec = codec; |
@@ -598,15 +621,26 @@ static int cs4270_probe(struct platform_device *pdev) | |||
598 | goto error_free_pcms; | 621 | goto error_free_pcms; |
599 | } | 622 | } |
600 | 623 | ||
601 | /* And finally, register the socdev */ | 624 | /* get the power supply regulators */ |
602 | ret = snd_soc_init_card(socdev); | 625 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) |
603 | if (ret < 0) { | 626 | cs4270->supplies[i].supply = supply_names[i]; |
604 | dev_err(codec->dev, "failed to register card\n"); | 627 | |
628 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
629 | cs4270->supplies); | ||
630 | if (ret < 0) | ||
605 | goto error_free_pcms; | 631 | goto error_free_pcms; |
606 | } | 632 | |
633 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
634 | cs4270->supplies); | ||
635 | if (ret < 0) | ||
636 | goto error_free_regulators; | ||
607 | 637 | ||
608 | return 0; | 638 | return 0; |
609 | 639 | ||
640 | error_free_regulators: | ||
641 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
642 | cs4270->supplies); | ||
643 | |||
610 | error_free_pcms: | 644 | error_free_pcms: |
611 | snd_soc_free_pcms(socdev); | 645 | snd_soc_free_pcms(socdev); |
612 | 646 | ||
@@ -622,8 +656,12 @@ error_free_pcms: | |||
622 | static int cs4270_remove(struct platform_device *pdev) | 656 | static int cs4270_remove(struct platform_device *pdev) |
623 | { | 657 | { |
624 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 658 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
659 | struct snd_soc_codec *codec = cs4270_codec; | ||
660 | struct cs4270_private *cs4270 = codec->private_data; | ||
625 | 661 | ||
626 | snd_soc_free_pcms(socdev); | 662 | snd_soc_free_pcms(socdev); |
663 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
664 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
627 | 665 | ||
628 | return 0; | 666 | return 0; |
629 | }; | 667 | }; |
@@ -802,36 +840,36 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
802 | * and all registers are written back to the hardware when resuming. | 840 | * and all registers are written back to the hardware when resuming. |
803 | */ | 841 | */ |
804 | 842 | ||
805 | static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 843 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) |
806 | { | 844 | { |
807 | struct cs4270_private *cs4270 = i2c_get_clientdata(client); | 845 | struct snd_soc_codec *codec = cs4270_codec; |
808 | struct snd_soc_codec *codec = &cs4270->codec; | 846 | struct cs4270_private *cs4270 = codec->private_data; |
809 | 847 | int reg, ret; | |
810 | return snd_soc_suspend_device(codec->dev); | ||
811 | } | ||
812 | 848 | ||
813 | static int cs4270_i2c_resume(struct i2c_client *client) | 849 | reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; |
814 | { | 850 | if (reg < 0) |
815 | struct cs4270_private *cs4270 = i2c_get_clientdata(client); | 851 | return reg; |
816 | struct snd_soc_codec *codec = &cs4270->codec; | ||
817 | 852 | ||
818 | return snd_soc_resume_device(codec->dev); | 853 | ret = snd_soc_write(codec, CS4270_PWRCTL, reg); |
819 | } | 854 | if (ret < 0) |
855 | return ret; | ||
820 | 856 | ||
821 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | 857 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), |
822 | { | 858 | cs4270->supplies); |
823 | struct snd_soc_codec *codec = cs4270_codec; | ||
824 | int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; | ||
825 | 859 | ||
826 | return snd_soc_write(codec, CS4270_PWRCTL, reg); | 860 | return 0; |
827 | } | 861 | } |
828 | 862 | ||
829 | static int cs4270_soc_resume(struct platform_device *pdev) | 863 | static int cs4270_soc_resume(struct platform_device *pdev) |
830 | { | 864 | { |
831 | struct snd_soc_codec *codec = cs4270_codec; | 865 | struct snd_soc_codec *codec = cs4270_codec; |
866 | struct cs4270_private *cs4270 = codec->private_data; | ||
832 | struct i2c_client *i2c_client = codec->control_data; | 867 | struct i2c_client *i2c_client = codec->control_data; |
833 | int reg; | 868 | int reg; |
834 | 869 | ||
870 | regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
871 | cs4270->supplies); | ||
872 | |||
835 | /* In case the device was put to hard reset during sleep, we need to | 873 | /* In case the device was put to hard reset during sleep, we need to |
836 | * wait 500ns here before any I2C communication. */ | 874 | * wait 500ns here before any I2C communication. */ |
837 | ndelay(500); | 875 | ndelay(500); |
@@ -853,8 +891,6 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
853 | return snd_soc_write(codec, CS4270_PWRCTL, reg); | 891 | return snd_soc_write(codec, CS4270_PWRCTL, reg); |
854 | } | 892 | } |
855 | #else | 893 | #else |
856 | #define cs4270_i2c_suspend NULL | ||
857 | #define cs4270_i2c_resume NULL | ||
858 | #define cs4270_soc_suspend NULL | 894 | #define cs4270_soc_suspend NULL |
859 | #define cs4270_soc_resume NULL | 895 | #define cs4270_soc_resume NULL |
860 | #endif /* CONFIG_PM */ | 896 | #endif /* CONFIG_PM */ |
@@ -873,8 +909,6 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
873 | .id_table = cs4270_id, | 909 | .id_table = cs4270_id, |
874 | .probe = cs4270_i2c_probe, | 910 | .probe = cs4270_i2c_probe, |
875 | .remove = cs4270_i2c_remove, | 911 | .remove = cs4270_i2c_remove, |
876 | .suspend = cs4270_i2c_suspend, | ||
877 | .resume = cs4270_i2c_resume, | ||
878 | }; | 912 | }; |
879 | 913 | ||
880 | /* | 914 | /* |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 38eac9c866e1..9f169c477108 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/tty.h> | 16 | #include <linux/tty.h> |
17 | #include <linux/slab.h> | ||
17 | 18 | ||
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/initval.h> | 20 | #include <sound/initval.h> |
@@ -93,7 +94,6 @@ static int cx20442_add_widgets(struct snd_soc_codec *codec) | |||
93 | snd_soc_dapm_add_routes(codec, cx20442_audio_map, | 94 | snd_soc_dapm_add_routes(codec, cx20442_audio_map, |
94 | ARRAY_SIZE(cx20442_audio_map)); | 95 | ARRAY_SIZE(cx20442_audio_map)); |
95 | 96 | ||
96 | snd_soc_dapm_new_widgets(codec); | ||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
@@ -355,17 +355,6 @@ static int cx20442_codec_probe(struct platform_device *pdev) | |||
355 | 355 | ||
356 | cx20442_add_widgets(codec); | 356 | cx20442_add_widgets(codec); |
357 | 357 | ||
358 | ret = snd_soc_init_card(socdev); | ||
359 | if (ret < 0) { | ||
360 | dev_err(&pdev->dev, "failed to register card\n"); | ||
361 | goto card_err; | ||
362 | } | ||
363 | |||
364 | return ret; | ||
365 | |||
366 | card_err: | ||
367 | snd_soc_free_pcms(socdev); | ||
368 | snd_soc_dapm_free(socdev); | ||
369 | pcm_err: | 358 | pcm_err: |
370 | return ret; | 359 | return ret; |
371 | } | 360 | } |
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c new file mode 100644 index 000000000000..366daf1d044e --- /dev/null +++ b/sound/soc/codecs/da7210.c | |||
@@ -0,0 +1,590 @@ | |||
1 | /* | ||
2 | * DA7210 ALSA Soc codec driver | ||
3 | * | ||
4 | * Copyright (c) 2009 Dialog Semiconductor | ||
5 | * Written by David Chen <Dajun.chen@diasemi.com> | ||
6 | * | ||
7 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
8 | * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
9 | * | ||
10 | * Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S | ||
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/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/pm.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/soc.h> | ||
31 | #include <sound/soc-dapm.h> | ||
32 | #include <sound/tlv.h> | ||
33 | #include <sound/initval.h> | ||
34 | #include <asm/div64.h> | ||
35 | |||
36 | #include "da7210.h" | ||
37 | |||
38 | /* DA7210 register space */ | ||
39 | #define DA7210_STATUS 0x02 | ||
40 | #define DA7210_STARTUP1 0x03 | ||
41 | #define DA7210_MIC_L 0x07 | ||
42 | #define DA7210_MIC_R 0x08 | ||
43 | #define DA7210_INMIX_L 0x0D | ||
44 | #define DA7210_INMIX_R 0x0E | ||
45 | #define DA7210_ADC_HPF 0x0F | ||
46 | #define DA7210_ADC 0x10 | ||
47 | #define DA7210_DAC_HPF 0x14 | ||
48 | #define DA7210_DAC_L 0x15 | ||
49 | #define DA7210_DAC_R 0x16 | ||
50 | #define DA7210_DAC_SEL 0x17 | ||
51 | #define DA7210_OUTMIX_L 0x1C | ||
52 | #define DA7210_OUTMIX_R 0x1D | ||
53 | #define DA7210_HP_L_VOL 0x21 | ||
54 | #define DA7210_HP_R_VOL 0x22 | ||
55 | #define DA7210_HP_CFG 0x23 | ||
56 | #define DA7210_DAI_SRC_SEL 0x25 | ||
57 | #define DA7210_DAI_CFG1 0x26 | ||
58 | #define DA7210_DAI_CFG3 0x28 | ||
59 | #define DA7210_PLL_DIV3 0x2B | ||
60 | #define DA7210_PLL 0x2C | ||
61 | |||
62 | /* STARTUP1 bit fields */ | ||
63 | #define DA7210_SC_MST_EN (1 << 0) | ||
64 | |||
65 | /* MIC_L bit fields */ | ||
66 | #define DA7210_MICBIAS_EN (1 << 6) | ||
67 | #define DA7210_MIC_L_EN (1 << 7) | ||
68 | |||
69 | /* MIC_R bit fields */ | ||
70 | #define DA7210_MIC_R_EN (1 << 7) | ||
71 | |||
72 | /* INMIX_L bit fields */ | ||
73 | #define DA7210_IN_L_EN (1 << 7) | ||
74 | |||
75 | /* INMIX_R bit fields */ | ||
76 | #define DA7210_IN_R_EN (1 << 7) | ||
77 | |||
78 | /* ADC_HPF bit fields */ | ||
79 | #define DA7210_ADC_VOICE_EN (1 << 7) | ||
80 | |||
81 | /* ADC bit fields */ | ||
82 | #define DA7210_ADC_L_EN (1 << 3) | ||
83 | #define DA7210_ADC_R_EN (1 << 7) | ||
84 | |||
85 | /* DAC_HPF fields */ | ||
86 | #define DA7210_DAC_VOICE_EN (1 << 7) | ||
87 | |||
88 | /* DAC_SEL bit fields */ | ||
89 | #define DA7210_DAC_L_SRC_DAI_L (4 << 0) | ||
90 | #define DA7210_DAC_L_EN (1 << 3) | ||
91 | #define DA7210_DAC_R_SRC_DAI_R (5 << 4) | ||
92 | #define DA7210_DAC_R_EN (1 << 7) | ||
93 | |||
94 | /* OUTMIX_L bit fields */ | ||
95 | #define DA7210_OUT_L_EN (1 << 7) | ||
96 | |||
97 | /* OUTMIX_R bit fields */ | ||
98 | #define DA7210_OUT_R_EN (1 << 7) | ||
99 | |||
100 | /* HP_CFG bit fields */ | ||
101 | #define DA7210_HP_2CAP_MODE (1 << 1) | ||
102 | #define DA7210_HP_SENSE_EN (1 << 2) | ||
103 | #define DA7210_HP_L_EN (1 << 3) | ||
104 | #define DA7210_HP_MODE (1 << 6) | ||
105 | #define DA7210_HP_R_EN (1 << 7) | ||
106 | |||
107 | /* DAI_SRC_SEL bit fields */ | ||
108 | #define DA7210_DAI_OUT_L_SRC (6 << 0) | ||
109 | #define DA7210_DAI_OUT_R_SRC (7 << 4) | ||
110 | |||
111 | /* DAI_CFG1 bit fields */ | ||
112 | #define DA7210_DAI_WORD_S16_LE (0 << 0) | ||
113 | #define DA7210_DAI_WORD_S24_LE (2 << 0) | ||
114 | #define DA7210_DAI_FLEN_64BIT (1 << 2) | ||
115 | #define DA7210_DAI_MODE_MASTER (1 << 7) | ||
116 | |||
117 | /* DAI_CFG3 bit fields */ | ||
118 | #define DA7210_DAI_FORMAT_I2SMODE (0 << 0) | ||
119 | #define DA7210_DAI_OE (1 << 3) | ||
120 | #define DA7210_DAI_EN (1 << 7) | ||
121 | |||
122 | /*PLL_DIV3 bit fields */ | ||
123 | #define DA7210_MCLK_RANGE_10_20_MHZ (1 << 4) | ||
124 | #define DA7210_PLL_BYP (1 << 6) | ||
125 | |||
126 | /* PLL bit fields */ | ||
127 | #define DA7210_PLL_FS_48000 (11 << 0) | ||
128 | |||
129 | #define DA7210_VERSION "0.0.1" | ||
130 | |||
131 | /* Codec private data */ | ||
132 | struct da7210_priv { | ||
133 | struct snd_soc_codec codec; | ||
134 | }; | ||
135 | |||
136 | static struct snd_soc_codec *da7210_codec; | ||
137 | |||
138 | /* | ||
139 | * Register cache | ||
140 | */ | ||
141 | static const u8 da7210_reg[] = { | ||
142 | 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R0 - R7 */ | ||
143 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, /* R8 - RF */ | ||
144 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54, /* R10 - R17 */ | ||
145 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R18 - R1F */ | ||
146 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, /* R20 - R27 */ | ||
147 | 0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00, /* R28 - R2F */ | ||
148 | 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, /* R30 - R37 */ | ||
149 | 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* R38 - R3F */ | ||
150 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R40 - R4F */ | ||
151 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R48 - R4F */ | ||
152 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R50 - R57 */ | ||
153 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R58 - R5F */ | ||
154 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R60 - R67 */ | ||
155 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R68 - R6F */ | ||
156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R70 - R77 */ | ||
157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, /* R78 - R7F */ | ||
158 | 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, /* R80 - R87 */ | ||
159 | 0x00, /* R88 */ | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * Read da7210 register cache | ||
164 | */ | ||
165 | static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg) | ||
166 | { | ||
167 | u8 *cache = codec->reg_cache; | ||
168 | BUG_ON(reg > ARRAY_SIZE(da7210_reg)); | ||
169 | return cache[reg]; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Write to the da7210 register space | ||
174 | */ | ||
175 | static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value) | ||
176 | { | ||
177 | u8 *cache = codec->reg_cache; | ||
178 | u8 data[2]; | ||
179 | |||
180 | BUG_ON(codec->volatile_register); | ||
181 | |||
182 | data[0] = reg & 0xff; | ||
183 | data[1] = value & 0xff; | ||
184 | |||
185 | if (reg >= codec->reg_cache_size) | ||
186 | return -EIO; | ||
187 | |||
188 | if (2 != codec->hw_write(codec->control_data, data, 2)) | ||
189 | return -EIO; | ||
190 | |||
191 | cache[reg] = value; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Read from the da7210 register space. | ||
197 | */ | ||
198 | static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg) | ||
199 | { | ||
200 | if (DA7210_STATUS == reg) | ||
201 | return i2c_smbus_read_byte_data(codec->control_data, reg); | ||
202 | |||
203 | return da7210_read_reg_cache(codec, reg); | ||
204 | } | ||
205 | |||
206 | static int da7210_startup(struct snd_pcm_substream *substream, | ||
207 | struct snd_soc_dai *dai) | ||
208 | { | ||
209 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
210 | struct snd_soc_codec *codec = dai->codec; | ||
211 | |||
212 | if (is_play) { | ||
213 | /* PlayBack Volume 40 */ | ||
214 | snd_soc_update_bits(codec, DA7210_HP_L_VOL, 0x3F, 40); | ||
215 | snd_soc_update_bits(codec, DA7210_HP_R_VOL, 0x3F, 40); | ||
216 | |||
217 | /* Enable Out */ | ||
218 | snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10); | ||
219 | snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10); | ||
220 | |||
221 | } else { | ||
222 | /* Volume 7 */ | ||
223 | snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7); | ||
224 | snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7); | ||
225 | |||
226 | /* Enable Mic */ | ||
227 | snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1); | ||
228 | snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1); | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Set PCM DAI word length. | ||
236 | */ | ||
237 | static int da7210_hw_params(struct snd_pcm_substream *substream, | ||
238 | struct snd_pcm_hw_params *params, | ||
239 | struct snd_soc_dai *dai) | ||
240 | { | ||
241 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
242 | struct snd_soc_device *socdev = rtd->socdev; | ||
243 | struct snd_soc_codec *codec = socdev->card->codec; | ||
244 | u32 dai_cfg1; | ||
245 | u32 reg, mask; | ||
246 | |||
247 | /* set DAI source to Left and Right ADC */ | ||
248 | da7210_write(codec, DA7210_DAI_SRC_SEL, | ||
249 | DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC); | ||
250 | |||
251 | /* Enable DAI */ | ||
252 | da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); | ||
253 | |||
254 | dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1); | ||
255 | |||
256 | switch (params_format(params)) { | ||
257 | case SNDRV_PCM_FORMAT_S16_LE: | ||
258 | dai_cfg1 |= DA7210_DAI_WORD_S16_LE; | ||
259 | break; | ||
260 | case SNDRV_PCM_FORMAT_S24_LE: | ||
261 | dai_cfg1 |= DA7210_DAI_WORD_S24_LE; | ||
262 | break; | ||
263 | default: | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); | ||
268 | |||
269 | /* FIXME | ||
270 | * | ||
271 | * It support 48K only now | ||
272 | */ | ||
273 | switch (params_rate(params)) { | ||
274 | case 48000: | ||
275 | if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { | ||
276 | reg = DA7210_DAC_HPF; | ||
277 | mask = DA7210_DAC_VOICE_EN; | ||
278 | } else { | ||
279 | reg = DA7210_ADC_HPF; | ||
280 | mask = DA7210_ADC_VOICE_EN; | ||
281 | } | ||
282 | break; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | |||
287 | snd_soc_update_bits(codec, reg, mask, 0); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * Set DAI mode and Format | ||
294 | */ | ||
295 | static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) | ||
296 | { | ||
297 | struct snd_soc_codec *codec = codec_dai->codec; | ||
298 | u32 dai_cfg1; | ||
299 | u32 dai_cfg3; | ||
300 | |||
301 | dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1); | ||
302 | dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3); | ||
303 | |||
304 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
305 | case SND_SOC_DAIFMT_CBM_CFM: | ||
306 | dai_cfg1 |= DA7210_DAI_MODE_MASTER; | ||
307 | break; | ||
308 | default: | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | /* FIXME | ||
313 | * | ||
314 | * It support I2S only now | ||
315 | */ | ||
316 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
317 | case SND_SOC_DAIFMT_I2S: | ||
318 | dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE; | ||
319 | break; | ||
320 | default: | ||
321 | return -EINVAL; | ||
322 | } | ||
323 | |||
324 | /* FIXME | ||
325 | * | ||
326 | * It support 64bit data transmission only now | ||
327 | */ | ||
328 | dai_cfg1 |= DA7210_DAI_FLEN_64BIT; | ||
329 | |||
330 | da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); | ||
331 | da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | #define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
337 | |||
338 | /* DAI operations */ | ||
339 | static struct snd_soc_dai_ops da7210_dai_ops = { | ||
340 | .startup = da7210_startup, | ||
341 | .hw_params = da7210_hw_params, | ||
342 | .set_fmt = da7210_set_dai_fmt, | ||
343 | }; | ||
344 | |||
345 | struct snd_soc_dai da7210_dai = { | ||
346 | .name = "DA7210 IIS", | ||
347 | .id = 0, | ||
348 | /* playback capabilities */ | ||
349 | .playback = { | ||
350 | .stream_name = "Playback", | ||
351 | .channels_min = 1, | ||
352 | .channels_max = 2, | ||
353 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
354 | .formats = DA7210_FORMATS, | ||
355 | }, | ||
356 | /* capture capabilities */ | ||
357 | .capture = { | ||
358 | .stream_name = "Capture", | ||
359 | .channels_min = 1, | ||
360 | .channels_max = 2, | ||
361 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
362 | .formats = DA7210_FORMATS, | ||
363 | }, | ||
364 | .ops = &da7210_dai_ops, | ||
365 | }; | ||
366 | EXPORT_SYMBOL_GPL(da7210_dai); | ||
367 | |||
368 | /* | ||
369 | * Initialize the DA7210 driver | ||
370 | * register the mixer and dsp interfaces with the kernel | ||
371 | */ | ||
372 | static int da7210_init(struct da7210_priv *da7210) | ||
373 | { | ||
374 | struct snd_soc_codec *codec = &da7210->codec; | ||
375 | int ret = 0; | ||
376 | |||
377 | if (da7210_codec) { | ||
378 | dev_err(codec->dev, "Another da7210 is registered\n"); | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | |||
382 | mutex_init(&codec->mutex); | ||
383 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
384 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
385 | |||
386 | codec->private_data = da7210; | ||
387 | codec->name = "DA7210"; | ||
388 | codec->owner = THIS_MODULE; | ||
389 | codec->read = da7210_read; | ||
390 | codec->write = da7210_write; | ||
391 | codec->dai = &da7210_dai; | ||
392 | codec->num_dai = 1; | ||
393 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
394 | codec->reg_cache_size = ARRAY_SIZE(da7210_reg); | ||
395 | codec->reg_cache = kmemdup(da7210_reg, | ||
396 | sizeof(da7210_reg), GFP_KERNEL); | ||
397 | |||
398 | if (!codec->reg_cache) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | da7210_dai.dev = codec->dev; | ||
402 | da7210_codec = codec; | ||
403 | |||
404 | ret = snd_soc_register_codec(codec); | ||
405 | if (ret) { | ||
406 | dev_err(codec->dev, "Failed to register CODEC: %d\n", ret); | ||
407 | goto init_err; | ||
408 | } | ||
409 | |||
410 | ret = snd_soc_register_dai(&da7210_dai); | ||
411 | if (ret) { | ||
412 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
413 | goto init_err; | ||
414 | } | ||
415 | |||
416 | /* FIXME | ||
417 | * | ||
418 | * This driver use fixed value here | ||
419 | */ | ||
420 | |||
421 | /* | ||
422 | * ADC settings | ||
423 | */ | ||
424 | |||
425 | /* Enable Left & Right MIC PGA and Mic Bias */ | ||
426 | da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN); | ||
427 | da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN); | ||
428 | |||
429 | /* Enable Left and Right input PGA */ | ||
430 | da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN); | ||
431 | da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN); | ||
432 | |||
433 | /* Enable Left and Right ADC */ | ||
434 | da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN); | ||
435 | |||
436 | /* | ||
437 | * DAC settings | ||
438 | */ | ||
439 | |||
440 | /* Enable Left and Right DAC */ | ||
441 | da7210_write(codec, DA7210_DAC_SEL, | ||
442 | DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN | | ||
443 | DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN); | ||
444 | |||
445 | /* Enable Left and Right out PGA */ | ||
446 | da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN); | ||
447 | da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN); | ||
448 | |||
449 | /* Enable Left and Right HeadPhone PGA */ | ||
450 | da7210_write(codec, DA7210_HP_CFG, | ||
451 | DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN | | ||
452 | DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN); | ||
453 | |||
454 | /* Diable PLL and bypass it */ | ||
455 | da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); | ||
456 | |||
457 | /* Bypass PLL and set MCLK freq rang to 10-20MHz */ | ||
458 | da7210_write(codec, DA7210_PLL_DIV3, | ||
459 | DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); | ||
460 | |||
461 | /* Activate all enabled subsystem */ | ||
462 | da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); | ||
463 | |||
464 | return ret; | ||
465 | |||
466 | init_err: | ||
467 | kfree(codec->reg_cache); | ||
468 | codec->reg_cache = NULL; | ||
469 | |||
470 | return ret; | ||
471 | |||
472 | } | ||
473 | |||
474 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
475 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | ||
476 | const struct i2c_device_id *id) | ||
477 | { | ||
478 | struct da7210_priv *da7210; | ||
479 | struct snd_soc_codec *codec; | ||
480 | int ret; | ||
481 | |||
482 | da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); | ||
483 | if (!da7210) | ||
484 | return -ENOMEM; | ||
485 | |||
486 | codec = &da7210->codec; | ||
487 | codec->dev = &i2c->dev; | ||
488 | |||
489 | i2c_set_clientdata(i2c, da7210); | ||
490 | codec->control_data = i2c; | ||
491 | |||
492 | ret = da7210_init(da7210); | ||
493 | if (ret < 0) | ||
494 | pr_err("Failed to initialise da7210 audio codec\n"); | ||
495 | |||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static int __devexit da7210_i2c_remove(struct i2c_client *client) | ||
500 | { | ||
501 | struct da7210_priv *da7210 = i2c_get_clientdata(client); | ||
502 | |||
503 | snd_soc_unregister_dai(&da7210_dai); | ||
504 | kfree(da7210->codec.reg_cache); | ||
505 | kfree(da7210); | ||
506 | da7210_codec = NULL; | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static const struct i2c_device_id da7210_i2c_id[] = { | ||
512 | { "da7210", 0 }, | ||
513 | { } | ||
514 | }; | ||
515 | MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); | ||
516 | |||
517 | /* I2C codec control layer */ | ||
518 | static struct i2c_driver da7210_i2c_driver = { | ||
519 | .driver = { | ||
520 | .name = "DA7210 I2C Codec", | ||
521 | .owner = THIS_MODULE, | ||
522 | }, | ||
523 | .probe = da7210_i2c_probe, | ||
524 | .remove = __devexit_p(da7210_i2c_remove), | ||
525 | .id_table = da7210_i2c_id, | ||
526 | }; | ||
527 | #endif | ||
528 | |||
529 | static int da7210_probe(struct platform_device *pdev) | ||
530 | { | ||
531 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
532 | struct snd_soc_codec *codec; | ||
533 | int ret; | ||
534 | |||
535 | if (!da7210_codec) { | ||
536 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
537 | return -ENODEV; | ||
538 | } | ||
539 | |||
540 | socdev->card->codec = da7210_codec; | ||
541 | codec = da7210_codec; | ||
542 | |||
543 | /* Register pcms */ | ||
544 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
545 | if (ret < 0) | ||
546 | goto pcm_err; | ||
547 | |||
548 | dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); | ||
549 | |||
550 | pcm_err: | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | static int da7210_remove(struct platform_device *pdev) | ||
555 | { | ||
556 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
557 | |||
558 | snd_soc_free_pcms(socdev); | ||
559 | snd_soc_dapm_free(socdev); | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | struct snd_soc_codec_device soc_codec_dev_da7210 = { | ||
565 | .probe = da7210_probe, | ||
566 | .remove = da7210_remove, | ||
567 | }; | ||
568 | EXPORT_SYMBOL_GPL(soc_codec_dev_da7210); | ||
569 | |||
570 | static int __init da7210_modinit(void) | ||
571 | { | ||
572 | int ret = 0; | ||
573 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
574 | ret = i2c_add_driver(&da7210_i2c_driver); | ||
575 | #endif | ||
576 | return ret; | ||
577 | } | ||
578 | module_init(da7210_modinit); | ||
579 | |||
580 | static void __exit da7210_exit(void) | ||
581 | { | ||
582 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
583 | i2c_del_driver(&da7210_i2c_driver); | ||
584 | #endif | ||
585 | } | ||
586 | module_exit(da7210_exit); | ||
587 | |||
588 | MODULE_DESCRIPTION("ASoC DA7210 driver"); | ||
589 | MODULE_AUTHOR("David Chen, Kuninori Morimoto"); | ||
590 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h new file mode 100644 index 000000000000..390d621eb742 --- /dev/null +++ b/sound/soc/codecs/da7210.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * da7210.h -- audio driver for da7210 | ||
3 | * | ||
4 | * Copyright (c) 2009 Dialog Semiconductor | ||
5 | * Written by David Chen <Dajun.chen@diasemi.com> | ||
6 | * | ||
7 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
8 | * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _DA7210_H | ||
18 | #define _DA7210_H | ||
19 | |||
20 | extern struct snd_soc_dai da7210_dai; | ||
21 | extern struct snd_soc_codec_device soc_codec_dev_da7210; | ||
22 | |||
23 | #endif | ||
24 | |||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 5cda9e6b5a74..5a5f187a2657 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/initval.h> | 25 | #include <sound/initval.h> |
@@ -90,13 +91,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev) | |||
90 | goto pcm_err; | 91 | goto pcm_err; |
91 | } | 92 | } |
92 | 93 | ||
93 | /* Register Card. */ | ||
94 | ret = snd_soc_init_card(socdev); | ||
95 | if (ret < 0) { | ||
96 | printk(KERN_ERR "pcm3008: failed to register card\n"); | ||
97 | goto card_err; | ||
98 | } | ||
99 | |||
100 | /* DEM1 DEM0 DE-EMPHASIS_MODE | 94 | /* DEM1 DEM0 DE-EMPHASIS_MODE |
101 | * Low Low De-emphasis 44.1 kHz ON | 95 | * Low Low De-emphasis 44.1 kHz ON |
102 | * Low High De-emphasis OFF | 96 | * Low High De-emphasis OFF |
@@ -136,8 +130,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev) | |||
136 | 130 | ||
137 | gpio_err: | 131 | gpio_err: |
138 | pcm3008_gpio_free(setup); | 132 | pcm3008_gpio_free(setup); |
139 | card_err: | ||
140 | snd_soc_free_pcms(socdev); | ||
141 | pcm_err: | 133 | pcm_err: |
142 | kfree(socdev->card->codec); | 134 | kfree(socdev->card->codec); |
143 | 135 | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index c550750c79c0..29d0906a924a 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/pm.h> | 33 | #include <linux/pm.h> |
34 | #include <linux/i2c.h> | 34 | #include <linux/i2c.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/slab.h> | ||
36 | #include <sound/core.h> | 37 | #include <sound/core.h> |
37 | #include <sound/pcm.h> | 38 | #include <sound/pcm.h> |
38 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
@@ -210,7 +211,6 @@ static int ssm2602_add_widgets(struct snd_soc_codec *codec) | |||
210 | 211 | ||
211 | snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn)); | 212 | snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn)); |
212 | 213 | ||
213 | snd_soc_dapm_new_widgets(codec); | ||
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | 216 | ||
@@ -613,17 +613,9 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
613 | snd_soc_add_controls(codec, ssm2602_snd_controls, | 613 | snd_soc_add_controls(codec, ssm2602_snd_controls, |
614 | ARRAY_SIZE(ssm2602_snd_controls)); | 614 | ARRAY_SIZE(ssm2602_snd_controls)); |
615 | ssm2602_add_widgets(codec); | 615 | ssm2602_add_widgets(codec); |
616 | ret = snd_soc_init_card(socdev); | ||
617 | if (ret < 0) { | ||
618 | pr_err("ssm2602: failed to register card\n"); | ||
619 | goto card_err; | ||
620 | } | ||
621 | 616 | ||
622 | return ret; | 617 | return ret; |
623 | 618 | ||
624 | card_err: | ||
625 | snd_soc_free_pcms(socdev); | ||
626 | snd_soc_dapm_free(socdev); | ||
627 | pcm_err: | 619 | pcm_err: |
628 | kfree(codec->reg_cache); | 620 | kfree(codec->reg_cache); |
629 | return ret; | 621 | return ret; |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index befc6488c39a..3293629dcb3b 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
@@ -191,6 +192,7 @@ static int ac97_analog_prepare(struct snd_pcm_substream *substream, | |||
191 | vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); | 192 | vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); |
192 | 193 | ||
193 | vra |= 0x1; /* enable variable rate audio */ | 194 | vra |= 0x1; /* enable variable rate audio */ |
195 | vra &= ~0x4; /* disable SPDIF output */ | ||
194 | 196 | ||
195 | stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); | 197 | stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); |
196 | 198 | ||
@@ -221,22 +223,6 @@ static int ac97_digital_prepare(struct snd_pcm_substream *substream, | |||
221 | return stac9766_ac97_write(codec, reg, runtime->rate); | 223 | return stac9766_ac97_write(codec, reg, runtime->rate); |
222 | } | 224 | } |
223 | 225 | ||
224 | static int ac97_digital_trigger(struct snd_pcm_substream *substream, | ||
225 | int cmd, struct snd_soc_dai *dai) | ||
226 | { | ||
227 | struct snd_soc_codec *codec = dai->codec; | ||
228 | unsigned short vra; | ||
229 | |||
230 | switch (cmd) { | ||
231 | case SNDRV_PCM_TRIGGER_STOP: | ||
232 | vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); | ||
233 | vra &= !0x04; | ||
234 | stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); | ||
235 | break; | ||
236 | } | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int stac9766_set_bias_level(struct snd_soc_codec *codec, | 226 | static int stac9766_set_bias_level(struct snd_soc_codec *codec, |
241 | enum snd_soc_bias_level level) | 227 | enum snd_soc_bias_level level) |
242 | { | 228 | { |
@@ -315,7 +301,6 @@ static struct snd_soc_dai_ops stac9766_dai_ops_analog = { | |||
315 | 301 | ||
316 | static struct snd_soc_dai_ops stac9766_dai_ops_digital = { | 302 | static struct snd_soc_dai_ops stac9766_dai_ops_digital = { |
317 | .prepare = ac97_digital_prepare, | 303 | .prepare = ac97_digital_prepare, |
318 | .trigger = ac97_digital_trigger, | ||
319 | }; | 304 | }; |
320 | 305 | ||
321 | struct snd_soc_dai stac9766_dai[] = { | 306 | struct snd_soc_dai stac9766_dai[] = { |
@@ -418,9 +403,6 @@ static int stac9766_codec_probe(struct platform_device *pdev) | |||
418 | snd_soc_add_controls(codec, stac9766_snd_ac97_controls, | 403 | snd_soc_add_controls(codec, stac9766_snd_ac97_controls, |
419 | ARRAY_SIZE(stac9766_snd_ac97_controls)); | 404 | ARRAY_SIZE(stac9766_snd_ac97_controls)); |
420 | 405 | ||
421 | ret = snd_soc_init_card(socdev); | ||
422 | if (ret < 0) | ||
423 | goto reset_err; | ||
424 | return 0; | 406 | return 0; |
425 | 407 | ||
426 | reset_err: | 408 | reset_err: |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 90a0264f7538..776b79cde904 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/slab.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
30 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
@@ -85,7 +86,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg, | |||
85 | * of data into val | 86 | * of data into val |
86 | */ | 87 | */ |
87 | 88 | ||
88 | if ((reg < 0 || reg > 9) && (reg != 15)) { | 89 | if (reg > 9 && reg != 15) { |
89 | printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg); | 90 | printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg); |
90 | return -1; | 91 | return -1; |
91 | } | 92 | } |
@@ -395,7 +396,6 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) | |||
395 | /* set up audio path interconnects */ | 396 | /* set up audio path interconnects */ |
396 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 397 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
397 | 398 | ||
398 | snd_soc_dapm_new_widgets(codec); | ||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
@@ -628,7 +628,7 @@ static int tlv320aic23_resume(struct platform_device *pdev) | |||
628 | u16 reg; | 628 | u16 reg; |
629 | 629 | ||
630 | /* Sync reg_cache with the hardware */ | 630 | /* Sync reg_cache with the hardware */ |
631 | for (reg = 0; reg < TLV320AIC23_RESET; reg++) { | 631 | for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) { |
632 | u16 val = tlv320aic23_read_reg_cache(codec, reg); | 632 | u16 val = tlv320aic23_read_reg_cache(codec, reg); |
633 | tlv320aic23_write(codec, reg, val); | 633 | tlv320aic23_write(codec, reg, val); |
634 | } | 634 | } |
@@ -706,17 +706,9 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) | |||
706 | snd_soc_add_controls(codec, tlv320aic23_snd_controls, | 706 | snd_soc_add_controls(codec, tlv320aic23_snd_controls, |
707 | ARRAY_SIZE(tlv320aic23_snd_controls)); | 707 | ARRAY_SIZE(tlv320aic23_snd_controls)); |
708 | tlv320aic23_add_widgets(codec); | 708 | tlv320aic23_add_widgets(codec); |
709 | ret = snd_soc_init_card(socdev); | ||
710 | if (ret < 0) { | ||
711 | printk(KERN_ERR "tlv320aic23: failed to register card\n"); | ||
712 | goto card_err; | ||
713 | } | ||
714 | 709 | ||
715 | return ret; | 710 | return ret; |
716 | 711 | ||
717 | card_err: | ||
718 | snd_soc_free_pcms(socdev); | ||
719 | snd_soc_dapm_free(socdev); | ||
720 | pcm_err: | 712 | pcm_err: |
721 | kfree(codec->reg_cache); | 713 | kfree(codec->reg_cache); |
722 | return ret; | 714 | return ret; |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 3387d9e736ea..b5b7d6a03844 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/sysfs.h> | 14 | #include <linux/sysfs.h> |
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <linux/slab.h> | ||
16 | #include <sound/core.h> | 17 | #include <sound/core.h> |
17 | #include <sound/pcm.h> | 18 | #include <sound/pcm.h> |
18 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
@@ -356,18 +357,7 @@ static int aic26_probe(struct platform_device *pdev) | |||
356 | ARRAY_SIZE(aic26_snd_controls)); | 357 | ARRAY_SIZE(aic26_snd_controls)); |
357 | WARN_ON(err < 0); | 358 | WARN_ON(err < 0); |
358 | 359 | ||
359 | /* CODEC is setup, we can register the card now */ | ||
360 | dev_dbg(&pdev->dev, "Registering card\n"); | ||
361 | ret = snd_soc_init_card(socdev); | ||
362 | if (ret < 0) { | ||
363 | dev_err(&pdev->dev, "aic26: failed to register card\n"); | ||
364 | goto card_err; | ||
365 | } | ||
366 | return 0; | 360 | return 0; |
367 | |||
368 | card_err: | ||
369 | snd_soc_free_pcms(socdev); | ||
370 | return ret; | ||
371 | } | 361 | } |
372 | 362 | ||
373 | static int aic26_remove(struct platform_device *pdev) | 363 | static int aic26_remove(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 3395cf945d56..4a6d56c3fed9 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/slab.h> | ||
42 | #include <sound/core.h> | 43 | #include <sound/core.h> |
43 | #include <sound/pcm.h> | 44 | #include <sound/pcm.h> |
44 | #include <sound/pcm_params.h> | 45 | #include <sound/pcm_params.h> |
@@ -753,7 +754,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) | |||
753 | /* set up audio path interconnects */ | 754 | /* set up audio path interconnects */ |
754 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 755 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
755 | 756 | ||
756 | snd_soc_dapm_new_widgets(codec); | ||
757 | return 0; | 757 | return 0; |
758 | } | 758 | } |
759 | 759 | ||
@@ -766,9 +766,10 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
766 | struct snd_soc_codec *codec = socdev->card->codec; | 766 | struct snd_soc_codec *codec = socdev->card->codec; |
767 | struct aic3x_priv *aic3x = codec->private_data; | 767 | struct aic3x_priv *aic3x = codec->private_data; |
768 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; | 768 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; |
769 | u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; | 769 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; |
770 | u16 pll_d = 1; | 770 | u16 d, pll_d = 1; |
771 | u8 reg; | 771 | u8 reg; |
772 | int clk; | ||
772 | 773 | ||
773 | /* select data word length */ | 774 | /* select data word length */ |
774 | data = | 775 | data = |
@@ -834,48 +835,70 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
834 | if (bypass_pll) | 835 | if (bypass_pll) |
835 | return 0; | 836 | return 0; |
836 | 837 | ||
837 | /* Use PLL | 838 | /* Use PLL, compute apropriate setup for j, d, r and p, the closest |
838 | * find an apropriate setup for j, d, r and p by iterating over | 839 | * one wins the game. Try with d==0 first, next with d!=0. |
839 | * p and r - j and d are calculated for each fraction. | 840 | * Constraints for j are according to the datasheet. |
840 | * Up to 128 values are probed, the closest one wins the game. | ||
841 | * The sysclk is divided by 1000 to prevent integer overflows. | 841 | * The sysclk is divided by 1000 to prevent integer overflows. |
842 | */ | 842 | */ |
843 | |||
843 | codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000); | 844 | codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000); |
844 | 845 | ||
845 | for (r = 1; r <= 16; r++) | 846 | for (r = 1; r <= 16; r++) |
846 | for (p = 1; p <= 8; p++) { | 847 | for (p = 1; p <= 8; p++) { |
847 | int clk, tmp = (codec_clk * pll_r * 10) / pll_p; | 848 | for (j = 4; j <= 55; j++) { |
848 | u8 j = tmp / 10000; | 849 | /* This is actually 1000*((j+(d/10000))*r)/p |
849 | u16 d = tmp % 10000; | 850 | * The term had to be converted to get |
851 | * rid of the division by 10000; d = 0 here | ||
852 | */ | ||
853 | int tmp_clk = (1000 * j * r) / p; | ||
854 | |||
855 | /* Check whether this values get closer than | ||
856 | * the best ones we had before | ||
857 | */ | ||
858 | if (abs(codec_clk - tmp_clk) < | ||
859 | abs(codec_clk - last_clk)) { | ||
860 | pll_j = j; pll_d = 0; | ||
861 | pll_r = r; pll_p = p; | ||
862 | last_clk = tmp_clk; | ||
863 | } | ||
864 | |||
865 | /* Early exit for exact matches */ | ||
866 | if (tmp_clk == codec_clk) | ||
867 | goto found; | ||
868 | } | ||
869 | } | ||
850 | 870 | ||
851 | if (j > 63) | 871 | /* try with d != 0 */ |
852 | continue; | 872 | for (p = 1; p <= 8; p++) { |
873 | j = codec_clk * p / 1000; | ||
853 | 874 | ||
854 | if (d != 0 && aic3x->sysclk < 10000000) | 875 | if (j < 4 || j > 11) |
855 | continue; | 876 | continue; |
856 | 877 | ||
857 | /* This is actually 1000 * ((j + (d/10000)) * r) / p | 878 | /* do not use codec_clk here since we'd loose precision */ |
858 | * The term had to be converted to get rid of the | 879 | d = ((2048 * p * fsref) - j * aic3x->sysclk) |
859 | * division by 10000 */ | 880 | * 100 / (aic3x->sysclk/100); |
860 | clk = ((10000 * j * r) + (d * r)) / (10 * p); | ||
861 | 881 | ||
862 | /* check whether this values get closer than the best | 882 | clk = (10000 * j + d) / (10 * p); |
863 | * ones we had before */ | ||
864 | if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) { | ||
865 | pll_j = j; pll_d = d; pll_r = r; pll_p = p; | ||
866 | last_clk = clk; | ||
867 | } | ||
868 | 883 | ||
869 | /* Early exit for exact matches */ | 884 | /* check whether this values get closer than the best |
870 | if (clk == codec_clk) | 885 | * ones we had before */ |
871 | break; | 886 | if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) { |
887 | pll_j = j; pll_d = d; pll_r = 1; pll_p = p; | ||
888 | last_clk = clk; | ||
872 | } | 889 | } |
873 | 890 | ||
891 | /* Early exit for exact matches */ | ||
892 | if (clk == codec_clk) | ||
893 | goto found; | ||
894 | } | ||
895 | |||
874 | if (last_clk == 0) { | 896 | if (last_clk == 0) { |
875 | printk(KERN_ERR "%s(): unable to setup PLL\n", __func__); | 897 | printk(KERN_ERR "%s(): unable to setup PLL\n", __func__); |
876 | return -EINVAL; | 898 | return -EINVAL; |
877 | } | 899 | } |
878 | 900 | ||
901 | found: | ||
879 | data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); | 902 | data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); |
880 | aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT)); | 903 | aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT)); |
881 | aic3x_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT); | 904 | aic3x_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT); |
@@ -1405,18 +1428,8 @@ static int aic3x_probe(struct platform_device *pdev) | |||
1405 | 1428 | ||
1406 | aic3x_add_widgets(codec); | 1429 | aic3x_add_widgets(codec); |
1407 | 1430 | ||
1408 | ret = snd_soc_init_card(socdev); | ||
1409 | if (ret < 0) { | ||
1410 | printk(KERN_ERR "aic3x: failed to register card\n"); | ||
1411 | goto card_err; | ||
1412 | } | ||
1413 | |||
1414 | return ret; | 1431 | return ret; |
1415 | 1432 | ||
1416 | card_err: | ||
1417 | snd_soc_free_pcms(socdev); | ||
1418 | snd_soc_dapm_free(socdev); | ||
1419 | |||
1420 | pcm_err: | 1433 | pcm_err: |
1421 | kfree(codec->reg_cache); | 1434 | kfree(codec->reg_cache); |
1422 | return ret; | 1435 | return ret; |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c new file mode 100644 index 000000000000..d1e0e81ef30c --- /dev/null +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -0,0 +1,1423 @@ | |||
1 | /* | ||
2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver | ||
3 | * | ||
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | ||
5 | * | ||
6 | * Copyright: (C) 2009 Nokia Corporation | ||
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 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/pm.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/gpio.h> | ||
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/pcm_params.h> | ||
38 | #include <sound/soc.h> | ||
39 | #include <sound/soc-dapm.h> | ||
40 | #include <sound/initval.h> | ||
41 | #include <sound/tlv.h> | ||
42 | |||
43 | #include <sound/tlv320dac33-plat.h> | ||
44 | #include "tlv320dac33.h" | ||
45 | |||
46 | #define DAC33_BUFFER_SIZE_BYTES 24576 /* bytes, 12288 16 bit words, | ||
47 | * 6144 stereo */ | ||
48 | #define DAC33_BUFFER_SIZE_SAMPLES 6144 | ||
49 | |||
50 | #define NSAMPLE_MAX 5700 | ||
51 | |||
52 | #define LATENCY_TIME_MS 20 | ||
53 | |||
54 | static struct snd_soc_codec *tlv320dac33_codec; | ||
55 | |||
56 | enum dac33_state { | ||
57 | DAC33_IDLE = 0, | ||
58 | DAC33_PREFILL, | ||
59 | DAC33_PLAYBACK, | ||
60 | DAC33_FLUSH, | ||
61 | }; | ||
62 | |||
63 | enum dac33_fifo_modes { | ||
64 | DAC33_FIFO_BYPASS = 0, | ||
65 | DAC33_FIFO_MODE1, | ||
66 | DAC33_FIFO_MODE7, | ||
67 | DAC33_FIFO_LAST_MODE, | ||
68 | }; | ||
69 | |||
70 | #define DAC33_NUM_SUPPLIES 3 | ||
71 | static const char *dac33_supply_names[DAC33_NUM_SUPPLIES] = { | ||
72 | "AVDD", | ||
73 | "DVDD", | ||
74 | "IOVDD", | ||
75 | }; | ||
76 | |||
77 | struct tlv320dac33_priv { | ||
78 | struct mutex mutex; | ||
79 | struct workqueue_struct *dac33_wq; | ||
80 | struct work_struct work; | ||
81 | struct snd_soc_codec codec; | ||
82 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; | ||
83 | int power_gpio; | ||
84 | int chip_power; | ||
85 | int irq; | ||
86 | unsigned int refclk; | ||
87 | |||
88 | unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */ | ||
89 | unsigned int nsample_min; /* nsample should not be lower than | ||
90 | * this */ | ||
91 | unsigned int nsample_max; /* nsample should not be higher than | ||
92 | * this */ | ||
93 | enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ | ||
94 | unsigned int nsample; /* burst read amount from host */ | ||
95 | u8 burst_bclkdiv; /* BCLK divider value in burst mode */ | ||
96 | |||
97 | enum dac33_state state; | ||
98 | }; | ||
99 | |||
100 | static const u8 dac33_reg[DAC33_CACHEREGNUM] = { | ||
101 | 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x03 */ | ||
102 | 0x00, 0x00, 0x00, 0x00, /* 0x04 - 0x07 */ | ||
103 | 0x00, 0x00, 0x00, 0x00, /* 0x08 - 0x0b */ | ||
104 | 0x00, 0x00, 0x00, 0x00, /* 0x0c - 0x0f */ | ||
105 | 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x13 */ | ||
106 | 0x00, 0x00, 0x00, 0x00, /* 0x14 - 0x17 */ | ||
107 | 0x00, 0x00, 0x00, 0x00, /* 0x18 - 0x1b */ | ||
108 | 0x00, 0x00, 0x00, 0x00, /* 0x1c - 0x1f */ | ||
109 | 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x23 */ | ||
110 | 0x00, 0x00, 0x00, 0x00, /* 0x24 - 0x27 */ | ||
111 | 0x00, 0x00, 0x00, 0x00, /* 0x28 - 0x2b */ | ||
112 | 0x00, 0x00, 0x00, 0x80, /* 0x2c - 0x2f */ | ||
113 | 0x80, 0x00, 0x00, 0x00, /* 0x30 - 0x33 */ | ||
114 | 0x00, 0x00, 0x00, 0x00, /* 0x34 - 0x37 */ | ||
115 | 0x00, 0x00, /* 0x38 - 0x39 */ | ||
116 | /* Registers 0x3a - 0x3f are reserved */ | ||
117 | 0x00, 0x00, /* 0x3a - 0x3b */ | ||
118 | 0x00, 0x00, 0x00, 0x00, /* 0x3c - 0x3f */ | ||
119 | |||
120 | 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x43 */ | ||
121 | 0x00, 0x80, /* 0x44 - 0x45 */ | ||
122 | /* Registers 0x46 - 0x47 are reserved */ | ||
123 | 0x80, 0x80, /* 0x46 - 0x47 */ | ||
124 | |||
125 | 0x80, 0x00, 0x00, /* 0x48 - 0x4a */ | ||
126 | /* Registers 0x4b - 0x7c are reserved */ | ||
127 | 0x00, /* 0x4b */ | ||
128 | 0x00, 0x00, 0x00, 0x00, /* 0x4c - 0x4f */ | ||
129 | 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x53 */ | ||
130 | 0x00, 0x00, 0x00, 0x00, /* 0x54 - 0x57 */ | ||
131 | 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5b */ | ||
132 | 0x00, 0x00, 0x00, 0x00, /* 0x5c - 0x5f */ | ||
133 | 0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x63 */ | ||
134 | 0x00, 0x00, 0x00, 0x00, /* 0x64 - 0x67 */ | ||
135 | 0x00, 0x00, 0x00, 0x00, /* 0x68 - 0x6b */ | ||
136 | 0x00, 0x00, 0x00, 0x00, /* 0x6c - 0x6f */ | ||
137 | 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x73 */ | ||
138 | 0x00, 0x00, 0x00, 0x00, /* 0x74 - 0x77 */ | ||
139 | 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7b */ | ||
140 | 0x00, /* 0x7c */ | ||
141 | |||
142 | 0xda, 0x33, 0x03, /* 0x7d - 0x7f */ | ||
143 | }; | ||
144 | |||
145 | /* Register read and write */ | ||
146 | static inline unsigned int dac33_read_reg_cache(struct snd_soc_codec *codec, | ||
147 | unsigned reg) | ||
148 | { | ||
149 | u8 *cache = codec->reg_cache; | ||
150 | if (reg >= DAC33_CACHEREGNUM) | ||
151 | return 0; | ||
152 | |||
153 | return cache[reg]; | ||
154 | } | ||
155 | |||
156 | static inline void dac33_write_reg_cache(struct snd_soc_codec *codec, | ||
157 | u8 reg, u8 value) | ||
158 | { | ||
159 | u8 *cache = codec->reg_cache; | ||
160 | if (reg >= DAC33_CACHEREGNUM) | ||
161 | return; | ||
162 | |||
163 | cache[reg] = value; | ||
164 | } | ||
165 | |||
166 | static int dac33_read(struct snd_soc_codec *codec, unsigned int reg, | ||
167 | u8 *value) | ||
168 | { | ||
169 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
170 | int val; | ||
171 | |||
172 | *value = reg & 0xff; | ||
173 | |||
174 | /* If powered off, return the cached value */ | ||
175 | if (dac33->chip_power) { | ||
176 | val = i2c_smbus_read_byte_data(codec->control_data, value[0]); | ||
177 | if (val < 0) { | ||
178 | dev_err(codec->dev, "Read failed (%d)\n", val); | ||
179 | value[0] = dac33_read_reg_cache(codec, reg); | ||
180 | } else { | ||
181 | value[0] = val; | ||
182 | dac33_write_reg_cache(codec, reg, val); | ||
183 | } | ||
184 | } else { | ||
185 | value[0] = dac33_read_reg_cache(codec, reg); | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int dac33_write(struct snd_soc_codec *codec, unsigned int reg, | ||
192 | unsigned int value) | ||
193 | { | ||
194 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
195 | u8 data[2]; | ||
196 | int ret = 0; | ||
197 | |||
198 | /* | ||
199 | * data is | ||
200 | * D15..D8 dac33 register offset | ||
201 | * D7...D0 register data | ||
202 | */ | ||
203 | data[0] = reg & 0xff; | ||
204 | data[1] = value & 0xff; | ||
205 | |||
206 | dac33_write_reg_cache(codec, data[0], data[1]); | ||
207 | if (dac33->chip_power) { | ||
208 | ret = codec->hw_write(codec->control_data, data, 2); | ||
209 | if (ret != 2) | ||
210 | dev_err(codec->dev, "Write failed (%d)\n", ret); | ||
211 | else | ||
212 | ret = 0; | ||
213 | } | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int dac33_write_locked(struct snd_soc_codec *codec, unsigned int reg, | ||
219 | unsigned int value) | ||
220 | { | ||
221 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
222 | int ret; | ||
223 | |||
224 | mutex_lock(&dac33->mutex); | ||
225 | ret = dac33_write(codec, reg, value); | ||
226 | mutex_unlock(&dac33->mutex); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | #define DAC33_I2C_ADDR_AUTOINC 0x80 | ||
232 | static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg, | ||
233 | unsigned int value) | ||
234 | { | ||
235 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
236 | u8 data[3]; | ||
237 | int ret = 0; | ||
238 | |||
239 | /* | ||
240 | * data is | ||
241 | * D23..D16 dac33 register offset | ||
242 | * D15..D8 register data MSB | ||
243 | * D7...D0 register data LSB | ||
244 | */ | ||
245 | data[0] = reg & 0xff; | ||
246 | data[1] = (value >> 8) & 0xff; | ||
247 | data[2] = value & 0xff; | ||
248 | |||
249 | dac33_write_reg_cache(codec, data[0], data[1]); | ||
250 | dac33_write_reg_cache(codec, data[0] + 1, data[2]); | ||
251 | |||
252 | if (dac33->chip_power) { | ||
253 | /* We need to set autoincrement mode for 16 bit writes */ | ||
254 | data[0] |= DAC33_I2C_ADDR_AUTOINC; | ||
255 | ret = codec->hw_write(codec->control_data, data, 3); | ||
256 | if (ret != 3) | ||
257 | dev_err(codec->dev, "Write failed (%d)\n", ret); | ||
258 | else | ||
259 | ret = 0; | ||
260 | } | ||
261 | |||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static void dac33_restore_regs(struct snd_soc_codec *codec) | ||
266 | { | ||
267 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
268 | u8 *cache = codec->reg_cache; | ||
269 | u8 data[2]; | ||
270 | int i, ret; | ||
271 | |||
272 | if (!dac33->chip_power) | ||
273 | return; | ||
274 | |||
275 | for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) { | ||
276 | data[0] = i; | ||
277 | data[1] = cache[i]; | ||
278 | /* Skip the read only registers */ | ||
279 | if ((i >= DAC33_INT_OSC_STATUS && | ||
280 | i <= DAC33_INT_OSC_FREQ_RAT_READ_B) || | ||
281 | (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) || | ||
282 | i == DAC33_DAC_STATUS_FLAGS || | ||
283 | i == DAC33_SRC_EST_REF_CLK_RATIO_A || | ||
284 | i == DAC33_SRC_EST_REF_CLK_RATIO_B) | ||
285 | continue; | ||
286 | ret = codec->hw_write(codec->control_data, data, 2); | ||
287 | if (ret != 2) | ||
288 | dev_err(codec->dev, "Write failed (%d)\n", ret); | ||
289 | } | ||
290 | for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) { | ||
291 | data[0] = i; | ||
292 | data[1] = cache[i]; | ||
293 | ret = codec->hw_write(codec->control_data, data, 2); | ||
294 | if (ret != 2) | ||
295 | dev_err(codec->dev, "Write failed (%d)\n", ret); | ||
296 | } | ||
297 | for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) { | ||
298 | data[0] = i; | ||
299 | data[1] = cache[i]; | ||
300 | ret = codec->hw_write(codec->control_data, data, 2); | ||
301 | if (ret != 2) | ||
302 | dev_err(codec->dev, "Write failed (%d)\n", ret); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) | ||
307 | { | ||
308 | u8 reg; | ||
309 | |||
310 | reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); | ||
311 | if (power) | ||
312 | reg |= DAC33_PDNALLB; | ||
313 | else | ||
314 | reg &= ~DAC33_PDNALLB; | ||
315 | dac33_write(codec, DAC33_PWR_CTRL, reg); | ||
316 | } | ||
317 | |||
318 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) | ||
319 | { | ||
320 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
321 | int ret; | ||
322 | |||
323 | mutex_lock(&dac33->mutex); | ||
324 | if (power) { | ||
325 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), | ||
326 | dac33->supplies); | ||
327 | if (ret != 0) { | ||
328 | dev_err(codec->dev, | ||
329 | "Failed to enable supplies: %d\n", ret); | ||
330 | goto exit; | ||
331 | } | ||
332 | |||
333 | if (dac33->power_gpio >= 0) | ||
334 | gpio_set_value(dac33->power_gpio, 1); | ||
335 | |||
336 | dac33->chip_power = 1; | ||
337 | |||
338 | /* Restore registers */ | ||
339 | dac33_restore_regs(codec); | ||
340 | |||
341 | dac33_soft_power(codec, 1); | ||
342 | } else { | ||
343 | dac33_soft_power(codec, 0); | ||
344 | if (dac33->power_gpio >= 0) | ||
345 | gpio_set_value(dac33->power_gpio, 0); | ||
346 | |||
347 | ret = regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), | ||
348 | dac33->supplies); | ||
349 | if (ret != 0) { | ||
350 | dev_err(codec->dev, | ||
351 | "Failed to disable supplies: %d\n", ret); | ||
352 | goto exit; | ||
353 | } | ||
354 | |||
355 | dac33->chip_power = 0; | ||
356 | } | ||
357 | |||
358 | exit: | ||
359 | mutex_unlock(&dac33->mutex); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | static int dac33_get_nsample(struct snd_kcontrol *kcontrol, | ||
364 | struct snd_ctl_elem_value *ucontrol) | ||
365 | { | ||
366 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
367 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
368 | |||
369 | ucontrol->value.integer.value[0] = dac33->nsample; | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int dac33_set_nsample(struct snd_kcontrol *kcontrol, | ||
375 | struct snd_ctl_elem_value *ucontrol) | ||
376 | { | ||
377 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
378 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
379 | int ret = 0; | ||
380 | |||
381 | if (dac33->nsample == ucontrol->value.integer.value[0]) | ||
382 | return 0; | ||
383 | |||
384 | if (ucontrol->value.integer.value[0] < dac33->nsample_min || | ||
385 | ucontrol->value.integer.value[0] > dac33->nsample_max) | ||
386 | ret = -EINVAL; | ||
387 | else | ||
388 | dac33->nsample = ucontrol->value.integer.value[0]; | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol, | ||
394 | struct snd_ctl_elem_value *ucontrol) | ||
395 | { | ||
396 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
397 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
398 | |||
399 | ucontrol->value.integer.value[0] = dac33->fifo_mode; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, | ||
405 | struct snd_ctl_elem_value *ucontrol) | ||
406 | { | ||
407 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
408 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
409 | int ret = 0; | ||
410 | |||
411 | if (dac33->fifo_mode == ucontrol->value.integer.value[0]) | ||
412 | return 0; | ||
413 | /* Do not allow changes while stream is running*/ | ||
414 | if (codec->active) | ||
415 | return -EPERM; | ||
416 | |||
417 | if (ucontrol->value.integer.value[0] < 0 || | ||
418 | ucontrol->value.integer.value[0] >= DAC33_FIFO_LAST_MODE) | ||
419 | ret = -EINVAL; | ||
420 | else | ||
421 | dac33->fifo_mode = ucontrol->value.integer.value[0]; | ||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | /* Codec operation modes */ | ||
427 | static const char *dac33_fifo_mode_texts[] = { | ||
428 | "Bypass", "Mode 1", "Mode 7" | ||
429 | }; | ||
430 | |||
431 | static const struct soc_enum dac33_fifo_mode_enum = | ||
432 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), | ||
433 | dac33_fifo_mode_texts); | ||
434 | |||
435 | /* | ||
436 | * DACL/R digital volume control: | ||
437 | * from 0 dB to -63.5 in 0.5 dB steps | ||
438 | * Need to be inverted later on: | ||
439 | * 0x00 == 0 dB | ||
440 | * 0x7f == -63.5 dB | ||
441 | */ | ||
442 | static DECLARE_TLV_DB_SCALE(dac_digivol_tlv, -6350, 50, 0); | ||
443 | |||
444 | static const struct snd_kcontrol_new dac33_snd_controls[] = { | ||
445 | SOC_DOUBLE_R_TLV("DAC Digital Playback Volume", | ||
446 | DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, | ||
447 | 0, 0x7f, 1, dac_digivol_tlv), | ||
448 | SOC_DOUBLE_R("DAC Digital Playback Switch", | ||
449 | DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1), | ||
450 | SOC_DOUBLE_R("Line to Line Out Volume", | ||
451 | DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), | ||
452 | }; | ||
453 | |||
454 | static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { | ||
455 | SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, | ||
456 | dac33_get_nsample, dac33_set_nsample), | ||
457 | SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, | ||
458 | dac33_get_fifo_mode, dac33_set_fifo_mode), | ||
459 | }; | ||
460 | |||
461 | /* Analog bypass */ | ||
462 | static const struct snd_kcontrol_new dac33_dapm_abypassl_control = | ||
463 | SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1); | ||
464 | |||
465 | static const struct snd_kcontrol_new dac33_dapm_abypassr_control = | ||
466 | SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1); | ||
467 | |||
468 | static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { | ||
469 | SND_SOC_DAPM_OUTPUT("LEFT_LO"), | ||
470 | SND_SOC_DAPM_OUTPUT("RIGHT_LO"), | ||
471 | |||
472 | SND_SOC_DAPM_INPUT("LINEL"), | ||
473 | SND_SOC_DAPM_INPUT("LINER"), | ||
474 | |||
475 | SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0), | ||
476 | SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0), | ||
477 | |||
478 | /* Analog bypass */ | ||
479 | SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0, | ||
480 | &dac33_dapm_abypassl_control), | ||
481 | SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, | ||
482 | &dac33_dapm_abypassr_control), | ||
483 | |||
484 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power", | ||
485 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), | ||
486 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", | ||
487 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), | ||
488 | }; | ||
489 | |||
490 | static const struct snd_soc_dapm_route audio_map[] = { | ||
491 | /* Analog bypass */ | ||
492 | {"Analog Left Bypass", "Switch", "LINEL"}, | ||
493 | {"Analog Right Bypass", "Switch", "LINER"}, | ||
494 | |||
495 | {"Output Left Amp Power", NULL, "DACL"}, | ||
496 | {"Output Right Amp Power", NULL, "DACR"}, | ||
497 | |||
498 | {"Output Left Amp Power", NULL, "Analog Left Bypass"}, | ||
499 | {"Output Right Amp Power", NULL, "Analog Right Bypass"}, | ||
500 | |||
501 | /* output */ | ||
502 | {"LEFT_LO", NULL, "Output Left Amp Power"}, | ||
503 | {"RIGHT_LO", NULL, "Output Right Amp Power"}, | ||
504 | }; | ||
505 | |||
506 | static int dac33_add_widgets(struct snd_soc_codec *codec) | ||
507 | { | ||
508 | snd_soc_dapm_new_controls(codec, dac33_dapm_widgets, | ||
509 | ARRAY_SIZE(dac33_dapm_widgets)); | ||
510 | |||
511 | /* set up audio path interconnects */ | ||
512 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int dac33_set_bias_level(struct snd_soc_codec *codec, | ||
518 | enum snd_soc_bias_level level) | ||
519 | { | ||
520 | int ret; | ||
521 | |||
522 | switch (level) { | ||
523 | case SND_SOC_BIAS_ON: | ||
524 | dac33_soft_power(codec, 1); | ||
525 | break; | ||
526 | case SND_SOC_BIAS_PREPARE: | ||
527 | break; | ||
528 | case SND_SOC_BIAS_STANDBY: | ||
529 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
530 | ret = dac33_hard_power(codec, 1); | ||
531 | if (ret != 0) | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | dac33_soft_power(codec, 0); | ||
536 | break; | ||
537 | case SND_SOC_BIAS_OFF: | ||
538 | ret = dac33_hard_power(codec, 0); | ||
539 | if (ret != 0) | ||
540 | return ret; | ||
541 | |||
542 | break; | ||
543 | } | ||
544 | codec->bias_level = level; | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | ||
550 | { | ||
551 | struct snd_soc_codec *codec; | ||
552 | |||
553 | codec = &dac33->codec; | ||
554 | |||
555 | switch (dac33->fifo_mode) { | ||
556 | case DAC33_FIFO_MODE1: | ||
557 | dac33_write16(codec, DAC33_NSAMPLE_MSB, | ||
558 | DAC33_THRREG(dac33->nsample)); | ||
559 | dac33_write16(codec, DAC33_PREFILL_MSB, | ||
560 | DAC33_THRREG(dac33->alarm_threshold)); | ||
561 | break; | ||
562 | case DAC33_FIFO_MODE7: | ||
563 | dac33_write16(codec, DAC33_PREFILL_MSB, | ||
564 | DAC33_THRREG(10)); | ||
565 | break; | ||
566 | default: | ||
567 | dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", | ||
568 | dac33->fifo_mode); | ||
569 | break; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) | ||
574 | { | ||
575 | struct snd_soc_codec *codec; | ||
576 | |||
577 | codec = &dac33->codec; | ||
578 | |||
579 | switch (dac33->fifo_mode) { | ||
580 | case DAC33_FIFO_MODE1: | ||
581 | dac33_write16(codec, DAC33_NSAMPLE_MSB, | ||
582 | DAC33_THRREG(dac33->nsample)); | ||
583 | break; | ||
584 | case DAC33_FIFO_MODE7: | ||
585 | /* At the moment we are not using interrupts in mode7 */ | ||
586 | break; | ||
587 | default: | ||
588 | dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", | ||
589 | dac33->fifo_mode); | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | static void dac33_work(struct work_struct *work) | ||
595 | { | ||
596 | struct snd_soc_codec *codec; | ||
597 | struct tlv320dac33_priv *dac33; | ||
598 | u8 reg; | ||
599 | |||
600 | dac33 = container_of(work, struct tlv320dac33_priv, work); | ||
601 | codec = &dac33->codec; | ||
602 | |||
603 | mutex_lock(&dac33->mutex); | ||
604 | switch (dac33->state) { | ||
605 | case DAC33_PREFILL: | ||
606 | dac33->state = DAC33_PLAYBACK; | ||
607 | dac33_prefill_handler(dac33); | ||
608 | break; | ||
609 | case DAC33_PLAYBACK: | ||
610 | dac33_playback_handler(dac33); | ||
611 | break; | ||
612 | case DAC33_IDLE: | ||
613 | break; | ||
614 | case DAC33_FLUSH: | ||
615 | dac33->state = DAC33_IDLE; | ||
616 | /* Mask all interrupts from dac33 */ | ||
617 | dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0); | ||
618 | |||
619 | /* flush fifo */ | ||
620 | reg = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A); | ||
621 | reg |= DAC33_FIFOFLUSH; | ||
622 | dac33_write(codec, DAC33_FIFO_CTRL_A, reg); | ||
623 | break; | ||
624 | } | ||
625 | mutex_unlock(&dac33->mutex); | ||
626 | } | ||
627 | |||
628 | static irqreturn_t dac33_interrupt_handler(int irq, void *dev) | ||
629 | { | ||
630 | struct snd_soc_codec *codec = dev; | ||
631 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
632 | |||
633 | queue_work(dac33->dac33_wq, &dac33->work); | ||
634 | |||
635 | return IRQ_HANDLED; | ||
636 | } | ||
637 | |||
638 | static void dac33_shutdown(struct snd_pcm_substream *substream, | ||
639 | struct snd_soc_dai *dai) | ||
640 | { | ||
641 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
642 | struct snd_soc_device *socdev = rtd->socdev; | ||
643 | struct snd_soc_codec *codec = socdev->card->codec; | ||
644 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
645 | unsigned int pwr_ctrl; | ||
646 | |||
647 | /* Stop pending workqueue */ | ||
648 | if (dac33->fifo_mode) | ||
649 | cancel_work_sync(&dac33->work); | ||
650 | |||
651 | mutex_lock(&dac33->mutex); | ||
652 | pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); | ||
653 | pwr_ctrl &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB); | ||
654 | dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl); | ||
655 | mutex_unlock(&dac33->mutex); | ||
656 | } | ||
657 | |||
658 | static void dac33_oscwait(struct snd_soc_codec *codec) | ||
659 | { | ||
660 | int timeout = 20; | ||
661 | u8 reg; | ||
662 | |||
663 | do { | ||
664 | msleep(1); | ||
665 | dac33_read(codec, DAC33_INT_OSC_STATUS, ®); | ||
666 | } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--); | ||
667 | if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) | ||
668 | dev_err(codec->dev, | ||
669 | "internal oscillator calibration failed\n"); | ||
670 | } | ||
671 | |||
672 | static int dac33_hw_params(struct snd_pcm_substream *substream, | ||
673 | struct snd_pcm_hw_params *params, | ||
674 | struct snd_soc_dai *dai) | ||
675 | { | ||
676 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
677 | struct snd_soc_device *socdev = rtd->socdev; | ||
678 | struct snd_soc_codec *codec = socdev->card->codec; | ||
679 | |||
680 | /* Check parameters for validity */ | ||
681 | switch (params_rate(params)) { | ||
682 | case 44100: | ||
683 | case 48000: | ||
684 | break; | ||
685 | default: | ||
686 | dev_err(codec->dev, "unsupported rate %d\n", | ||
687 | params_rate(params)); | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | switch (params_format(params)) { | ||
692 | case SNDRV_PCM_FORMAT_S16_LE: | ||
693 | break; | ||
694 | default: | ||
695 | dev_err(codec->dev, "unsupported format %d\n", | ||
696 | params_format(params)); | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | #define CALC_OSCSET(rate, refclk) ( \ | ||
704 | ((((rate * 10000) / refclk) * 4096) + 7000) / 10000) | ||
705 | #define CALC_RATIOSET(rate, refclk) ( \ | ||
706 | ((((refclk * 100000) / rate) * 16384) + 50000) / 100000) | ||
707 | |||
708 | /* | ||
709 | * tlv320dac33 is strict on the sequence of the register writes, if the register | ||
710 | * writes happens in different order, than dac33 might end up in unknown state. | ||
711 | * Use the known, working sequence of register writes to initialize the dac33. | ||
712 | */ | ||
713 | static int dac33_prepare_chip(struct snd_pcm_substream *substream) | ||
714 | { | ||
715 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
716 | struct snd_soc_device *socdev = rtd->socdev; | ||
717 | struct snd_soc_codec *codec = socdev->card->codec; | ||
718 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
719 | unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; | ||
720 | u8 aictrl_a, aictrl_b, fifoctrl_a; | ||
721 | |||
722 | switch (substream->runtime->rate) { | ||
723 | case 44100: | ||
724 | case 48000: | ||
725 | oscset = CALC_OSCSET(substream->runtime->rate, dac33->refclk); | ||
726 | ratioset = CALC_RATIOSET(substream->runtime->rate, | ||
727 | dac33->refclk); | ||
728 | break; | ||
729 | default: | ||
730 | dev_err(codec->dev, "unsupported rate %d\n", | ||
731 | substream->runtime->rate); | ||
732 | return -EINVAL; | ||
733 | } | ||
734 | |||
735 | |||
736 | aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A); | ||
737 | aictrl_a &= ~(DAC33_NCYCL_MASK | DAC33_WLEN_MASK); | ||
738 | /* Read FIFO control A, and clear FIFO flush bit */ | ||
739 | fifoctrl_a = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A); | ||
740 | fifoctrl_a &= ~DAC33_FIFOFLUSH; | ||
741 | |||
742 | fifoctrl_a &= ~DAC33_WIDTH; | ||
743 | switch (substream->runtime->format) { | ||
744 | case SNDRV_PCM_FORMAT_S16_LE: | ||
745 | aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16); | ||
746 | fifoctrl_a |= DAC33_WIDTH; | ||
747 | break; | ||
748 | default: | ||
749 | dev_err(codec->dev, "unsupported format %d\n", | ||
750 | substream->runtime->format); | ||
751 | return -EINVAL; | ||
752 | } | ||
753 | |||
754 | mutex_lock(&dac33->mutex); | ||
755 | dac33_soft_power(codec, 1); | ||
756 | |||
757 | reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); | ||
758 | dac33_write(codec, DAC33_INT_OSC_CTRL, reg_tmp); | ||
759 | |||
760 | /* Write registers 0x08 and 0x09 (MSB, LSB) */ | ||
761 | dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset); | ||
762 | |||
763 | /* calib time: 128 is a nice number ;) */ | ||
764 | dac33_write(codec, DAC33_CALIB_TIME, 128); | ||
765 | |||
766 | /* adjustment treshold & step */ | ||
767 | dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) | | ||
768 | DAC33_ADJSTEP(1)); | ||
769 | |||
770 | /* div=4 / gain=1 / div */ | ||
771 | dac33_write(codec, DAC33_INT_OSC_CTRL_C, DAC33_REFDIV(4)); | ||
772 | |||
773 | pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); | ||
774 | pwr_ctrl |= DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB; | ||
775 | dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl); | ||
776 | |||
777 | dac33_oscwait(codec); | ||
778 | |||
779 | if (dac33->fifo_mode) { | ||
780 | /* Generic for all FIFO modes */ | ||
781 | /* 50-51 : ASRC Control registers */ | ||
782 | dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCLKDIV(1)); | ||
783 | dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */ | ||
784 | |||
785 | /* Write registers 0x34 and 0x35 (MSB, LSB) */ | ||
786 | dac33_write16(codec, DAC33_SRC_REF_CLK_RATIO_A, ratioset); | ||
787 | |||
788 | /* Set interrupts to high active */ | ||
789 | dac33_write(codec, DAC33_INTP_CTRL_A, DAC33_INTPM_AHIGH); | ||
790 | } else { | ||
791 | /* FIFO bypass mode */ | ||
792 | /* 50-51 : ASRC Control registers */ | ||
793 | dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCBYP); | ||
794 | dac33_write(codec, DAC33_ASRC_CTRL_B, 0); /* ??? */ | ||
795 | } | ||
796 | |||
797 | /* Interrupt behaviour configuration */ | ||
798 | switch (dac33->fifo_mode) { | ||
799 | case DAC33_FIFO_MODE1: | ||
800 | dac33_write(codec, DAC33_FIFO_IRQ_MODE_B, | ||
801 | DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL)); | ||
802 | dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); | ||
803 | break; | ||
804 | case DAC33_FIFO_MODE7: | ||
805 | /* Disable all interrupts */ | ||
806 | dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0); | ||
807 | break; | ||
808 | default: | ||
809 | /* in FIFO bypass mode, the interrupts are not used */ | ||
810 | break; | ||
811 | } | ||
812 | |||
813 | aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); | ||
814 | |||
815 | switch (dac33->fifo_mode) { | ||
816 | case DAC33_FIFO_MODE1: | ||
817 | /* | ||
818 | * For mode1: | ||
819 | * Disable the FIFO bypass (Enable the use of FIFO) | ||
820 | * Select nSample mode | ||
821 | * BCLK is only running when data is needed by DAC33 | ||
822 | */ | ||
823 | fifoctrl_a &= ~DAC33_FBYPAS; | ||
824 | fifoctrl_a &= ~DAC33_FAUTO; | ||
825 | aictrl_b &= ~DAC33_BCLKON; | ||
826 | break; | ||
827 | case DAC33_FIFO_MODE7: | ||
828 | /* | ||
829 | * For mode1: | ||
830 | * Disable the FIFO bypass (Enable the use of FIFO) | ||
831 | * Select Threshold mode | ||
832 | * BCLK is only running when data is needed by DAC33 | ||
833 | */ | ||
834 | fifoctrl_a &= ~DAC33_FBYPAS; | ||
835 | fifoctrl_a |= DAC33_FAUTO; | ||
836 | aictrl_b &= ~DAC33_BCLKON; | ||
837 | break; | ||
838 | default: | ||
839 | /* | ||
840 | * For FIFO bypass mode: | ||
841 | * Enable the FIFO bypass (Disable the FIFO use) | ||
842 | * Set the BCLK as continous | ||
843 | */ | ||
844 | fifoctrl_a |= DAC33_FBYPAS; | ||
845 | aictrl_b |= DAC33_BCLKON; | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | dac33_write(codec, DAC33_FIFO_CTRL_A, fifoctrl_a); | ||
850 | dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a); | ||
851 | dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b); | ||
852 | |||
853 | /* | ||
854 | * BCLK divide ratio | ||
855 | * 0: 1.5 | ||
856 | * 1: 1 | ||
857 | * 2: 2 | ||
858 | * ... | ||
859 | * 254: 254 | ||
860 | * 255: 255 | ||
861 | */ | ||
862 | if (dac33->fifo_mode) | ||
863 | dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, | ||
864 | dac33->burst_bclkdiv); | ||
865 | else | ||
866 | dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32); | ||
867 | |||
868 | switch (dac33->fifo_mode) { | ||
869 | case DAC33_FIFO_MODE1: | ||
870 | dac33_write16(codec, DAC33_ATHR_MSB, | ||
871 | DAC33_THRREG(dac33->alarm_threshold)); | ||
872 | break; | ||
873 | case DAC33_FIFO_MODE7: | ||
874 | /* | ||
875 | * Configure the threshold levels, and leave 10 sample space | ||
876 | * at the bottom, and also at the top of the FIFO | ||
877 | */ | ||
878 | dac33_write16(codec, DAC33_UTHR_MSB, | ||
879 | DAC33_THRREG(DAC33_BUFFER_SIZE_SAMPLES - 10)); | ||
880 | dac33_write16(codec, DAC33_LTHR_MSB, | ||
881 | DAC33_THRREG(10)); | ||
882 | break; | ||
883 | default: | ||
884 | break; | ||
885 | } | ||
886 | |||
887 | mutex_unlock(&dac33->mutex); | ||
888 | |||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | static void dac33_calculate_times(struct snd_pcm_substream *substream) | ||
893 | { | ||
894 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
895 | struct snd_soc_device *socdev = rtd->socdev; | ||
896 | struct snd_soc_codec *codec = socdev->card->codec; | ||
897 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
898 | unsigned int nsample_limit; | ||
899 | |||
900 | /* Number of samples (16bit, stereo) in one period */ | ||
901 | dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4; | ||
902 | |||
903 | /* Number of samples (16bit, stereo) in ALSA buffer */ | ||
904 | dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4; | ||
905 | /* Subtract one period from the total */ | ||
906 | dac33->nsample_max -= dac33->nsample_min; | ||
907 | |||
908 | /* Number of samples for LATENCY_TIME_MS / 2 */ | ||
909 | dac33->alarm_threshold = substream->runtime->rate / | ||
910 | (1000 / (LATENCY_TIME_MS / 2)); | ||
911 | |||
912 | /* Find and fix up the lowest nsmaple limit */ | ||
913 | nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS); | ||
914 | |||
915 | if (dac33->nsample_min < nsample_limit) | ||
916 | dac33->nsample_min = nsample_limit; | ||
917 | |||
918 | if (dac33->nsample < dac33->nsample_min) | ||
919 | dac33->nsample = dac33->nsample_min; | ||
920 | |||
921 | /* | ||
922 | * Find and fix up the highest nsmaple limit | ||
923 | * In order to not overflow the DAC33 buffer substract the | ||
924 | * alarm_threshold value from the size of the DAC33 buffer | ||
925 | */ | ||
926 | nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; | ||
927 | |||
928 | if (dac33->nsample_max > nsample_limit) | ||
929 | dac33->nsample_max = nsample_limit; | ||
930 | |||
931 | if (dac33->nsample > dac33->nsample_max) | ||
932 | dac33->nsample = dac33->nsample_max; | ||
933 | } | ||
934 | |||
935 | static int dac33_pcm_prepare(struct snd_pcm_substream *substream, | ||
936 | struct snd_soc_dai *dai) | ||
937 | { | ||
938 | dac33_calculate_times(substream); | ||
939 | dac33_prepare_chip(substream); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | ||
945 | struct snd_soc_dai *dai) | ||
946 | { | ||
947 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
948 | struct snd_soc_device *socdev = rtd->socdev; | ||
949 | struct snd_soc_codec *codec = socdev->card->codec; | ||
950 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
951 | int ret = 0; | ||
952 | |||
953 | switch (cmd) { | ||
954 | case SNDRV_PCM_TRIGGER_START: | ||
955 | case SNDRV_PCM_TRIGGER_RESUME: | ||
956 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
957 | if (dac33->fifo_mode) { | ||
958 | dac33->state = DAC33_PREFILL; | ||
959 | queue_work(dac33->dac33_wq, &dac33->work); | ||
960 | } | ||
961 | break; | ||
962 | case SNDRV_PCM_TRIGGER_STOP: | ||
963 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
964 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
965 | if (dac33->fifo_mode) { | ||
966 | dac33->state = DAC33_FLUSH; | ||
967 | queue_work(dac33->dac33_wq, &dac33->work); | ||
968 | } | ||
969 | break; | ||
970 | default: | ||
971 | ret = -EINVAL; | ||
972 | } | ||
973 | |||
974 | return ret; | ||
975 | } | ||
976 | |||
977 | static int dac33_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
978 | int clk_id, unsigned int freq, int dir) | ||
979 | { | ||
980 | struct snd_soc_codec *codec = codec_dai->codec; | ||
981 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
982 | u8 ioc_reg, asrcb_reg; | ||
983 | |||
984 | ioc_reg = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); | ||
985 | asrcb_reg = dac33_read_reg_cache(codec, DAC33_ASRC_CTRL_B); | ||
986 | switch (clk_id) { | ||
987 | case TLV320DAC33_MCLK: | ||
988 | ioc_reg |= DAC33_REFSEL; | ||
989 | asrcb_reg |= DAC33_SRCREFSEL; | ||
990 | break; | ||
991 | case TLV320DAC33_SLEEPCLK: | ||
992 | ioc_reg &= ~DAC33_REFSEL; | ||
993 | asrcb_reg &= ~DAC33_SRCREFSEL; | ||
994 | break; | ||
995 | default: | ||
996 | dev_err(codec->dev, "Invalid clock ID (%d)\n", clk_id); | ||
997 | break; | ||
998 | } | ||
999 | dac33->refclk = freq; | ||
1000 | |||
1001 | dac33_write_reg_cache(codec, DAC33_INT_OSC_CTRL, ioc_reg); | ||
1002 | dac33_write_reg_cache(codec, DAC33_ASRC_CTRL_B, asrcb_reg); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1008 | unsigned int fmt) | ||
1009 | { | ||
1010 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1011 | struct tlv320dac33_priv *dac33 = codec->private_data; | ||
1012 | u8 aictrl_a, aictrl_b; | ||
1013 | |||
1014 | aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A); | ||
1015 | aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); | ||
1016 | /* set master/slave audio interface */ | ||
1017 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1018 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1019 | /* Codec Master */ | ||
1020 | aictrl_a |= (DAC33_MSBCLK | DAC33_MSWCLK); | ||
1021 | break; | ||
1022 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1023 | /* Codec Slave */ | ||
1024 | if (dac33->fifo_mode) { | ||
1025 | dev_err(codec->dev, "FIFO mode requires master mode\n"); | ||
1026 | return -EINVAL; | ||
1027 | } else | ||
1028 | aictrl_a &= ~(DAC33_MSBCLK | DAC33_MSWCLK); | ||
1029 | break; | ||
1030 | default: | ||
1031 | return -EINVAL; | ||
1032 | } | ||
1033 | |||
1034 | aictrl_a &= ~DAC33_AFMT_MASK; | ||
1035 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1036 | case SND_SOC_DAIFMT_I2S: | ||
1037 | aictrl_a |= DAC33_AFMT_I2S; | ||
1038 | break; | ||
1039 | case SND_SOC_DAIFMT_DSP_A: | ||
1040 | aictrl_a |= DAC33_AFMT_DSP; | ||
1041 | aictrl_b &= ~DAC33_DATA_DELAY_MASK; | ||
1042 | aictrl_b |= DAC33_DATA_DELAY(0); | ||
1043 | break; | ||
1044 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1045 | aictrl_a |= DAC33_AFMT_RIGHT_J; | ||
1046 | break; | ||
1047 | case SND_SOC_DAIFMT_LEFT_J: | ||
1048 | aictrl_a |= DAC33_AFMT_LEFT_J; | ||
1049 | break; | ||
1050 | default: | ||
1051 | dev_err(codec->dev, "Unsupported format (%u)\n", | ||
1052 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
1053 | return -EINVAL; | ||
1054 | } | ||
1055 | |||
1056 | dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a); | ||
1057 | dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b); | ||
1058 | |||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static void dac33_init_chip(struct snd_soc_codec *codec) | ||
1063 | { | ||
1064 | /* 44-46: DAC Control Registers */ | ||
1065 | /* A : DAC sample rate Fsref/1.5 */ | ||
1066 | dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); | ||
1067 | /* B : DAC src=normal, not muted */ | ||
1068 | dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | | ||
1069 | DAC33_DACSRCL_LEFT); | ||
1070 | /* C : (defaults) */ | ||
1071 | dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); | ||
1072 | |||
1073 | /* 64-65 : L&R DAC power control | ||
1074 | Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/ | ||
1075 | dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); | ||
1076 | dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); | ||
1077 | |||
1078 | /* 73 : volume soft stepping control, | ||
1079 | clock source = internal osc (?) */ | ||
1080 | dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); | ||
1081 | |||
1082 | /* 66 : LOP/LOM Modes */ | ||
1083 | dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff); | ||
1084 | |||
1085 | /* 68 : LOM inverted from LOP */ | ||
1086 | dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2)); | ||
1087 | |||
1088 | dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); | ||
1089 | } | ||
1090 | |||
1091 | static int dac33_soc_probe(struct platform_device *pdev) | ||
1092 | { | ||
1093 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1094 | struct snd_soc_codec *codec; | ||
1095 | struct tlv320dac33_priv *dac33; | ||
1096 | int ret = 0; | ||
1097 | |||
1098 | BUG_ON(!tlv320dac33_codec); | ||
1099 | |||
1100 | codec = tlv320dac33_codec; | ||
1101 | socdev->card->codec = codec; | ||
1102 | dac33 = codec->private_data; | ||
1103 | |||
1104 | /* Power up the codec */ | ||
1105 | dac33_hard_power(codec, 1); | ||
1106 | /* Set default configuration */ | ||
1107 | dac33_init_chip(codec); | ||
1108 | |||
1109 | /* register pcms */ | ||
1110 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1111 | if (ret < 0) { | ||
1112 | dev_err(codec->dev, "failed to create pcms\n"); | ||
1113 | goto pcm_err; | ||
1114 | } | ||
1115 | |||
1116 | snd_soc_add_controls(codec, dac33_snd_controls, | ||
1117 | ARRAY_SIZE(dac33_snd_controls)); | ||
1118 | /* Only add the nSample controls, if we have valid IRQ number */ | ||
1119 | if (dac33->irq >= 0) | ||
1120 | snd_soc_add_controls(codec, dac33_nsample_snd_controls, | ||
1121 | ARRAY_SIZE(dac33_nsample_snd_controls)); | ||
1122 | |||
1123 | dac33_add_widgets(codec); | ||
1124 | |||
1125 | /* power on device */ | ||
1126 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1127 | |||
1128 | /* Bias level configuration has enabled regulator an extra time */ | ||
1129 | regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1130 | |||
1131 | return 0; | ||
1132 | |||
1133 | pcm_err: | ||
1134 | dac33_hard_power(codec, 0); | ||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | static int dac33_soc_remove(struct platform_device *pdev) | ||
1139 | { | ||
1140 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1141 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1142 | |||
1143 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1144 | |||
1145 | snd_soc_free_pcms(socdev); | ||
1146 | snd_soc_dapm_free(socdev); | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) | ||
1152 | { | ||
1153 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1154 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1155 | |||
1156 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1157 | |||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | static int dac33_soc_resume(struct platform_device *pdev) | ||
1162 | { | ||
1163 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1164 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1165 | |||
1166 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1167 | dac33_set_bias_level(codec, codec->suspend_bias_level); | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { | ||
1173 | .probe = dac33_soc_probe, | ||
1174 | .remove = dac33_soc_remove, | ||
1175 | .suspend = dac33_soc_suspend, | ||
1176 | .resume = dac33_soc_resume, | ||
1177 | }; | ||
1178 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); | ||
1179 | |||
1180 | #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ | ||
1181 | SNDRV_PCM_RATE_48000) | ||
1182 | #define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
1183 | |||
1184 | static struct snd_soc_dai_ops dac33_dai_ops = { | ||
1185 | .shutdown = dac33_shutdown, | ||
1186 | .hw_params = dac33_hw_params, | ||
1187 | .prepare = dac33_pcm_prepare, | ||
1188 | .trigger = dac33_pcm_trigger, | ||
1189 | .set_sysclk = dac33_set_dai_sysclk, | ||
1190 | .set_fmt = dac33_set_dai_fmt, | ||
1191 | }; | ||
1192 | |||
1193 | struct snd_soc_dai dac33_dai = { | ||
1194 | .name = "tlv320dac33", | ||
1195 | .playback = { | ||
1196 | .stream_name = "Playback", | ||
1197 | .channels_min = 2, | ||
1198 | .channels_max = 2, | ||
1199 | .rates = DAC33_RATES, | ||
1200 | .formats = DAC33_FORMATS,}, | ||
1201 | .ops = &dac33_dai_ops, | ||
1202 | }; | ||
1203 | EXPORT_SYMBOL_GPL(dac33_dai); | ||
1204 | |||
1205 | static int __devinit dac33_i2c_probe(struct i2c_client *client, | ||
1206 | const struct i2c_device_id *id) | ||
1207 | { | ||
1208 | struct tlv320dac33_platform_data *pdata; | ||
1209 | struct tlv320dac33_priv *dac33; | ||
1210 | struct snd_soc_codec *codec; | ||
1211 | int ret, i; | ||
1212 | |||
1213 | if (client->dev.platform_data == NULL) { | ||
1214 | dev_err(&client->dev, "Platform data not set\n"); | ||
1215 | return -ENODEV; | ||
1216 | } | ||
1217 | pdata = client->dev.platform_data; | ||
1218 | |||
1219 | dac33 = kzalloc(sizeof(struct tlv320dac33_priv), GFP_KERNEL); | ||
1220 | if (dac33 == NULL) | ||
1221 | return -ENOMEM; | ||
1222 | |||
1223 | codec = &dac33->codec; | ||
1224 | codec->private_data = dac33; | ||
1225 | codec->control_data = client; | ||
1226 | |||
1227 | mutex_init(&codec->mutex); | ||
1228 | mutex_init(&dac33->mutex); | ||
1229 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1230 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1231 | |||
1232 | codec->name = "tlv320dac33"; | ||
1233 | codec->owner = THIS_MODULE; | ||
1234 | codec->read = dac33_read_reg_cache; | ||
1235 | codec->write = dac33_write_locked; | ||
1236 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1237 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1238 | codec->set_bias_level = dac33_set_bias_level; | ||
1239 | codec->dai = &dac33_dai; | ||
1240 | codec->num_dai = 1; | ||
1241 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); | ||
1242 | codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), | ||
1243 | GFP_KERNEL); | ||
1244 | if (codec->reg_cache == NULL) { | ||
1245 | ret = -ENOMEM; | ||
1246 | goto error_reg; | ||
1247 | } | ||
1248 | |||
1249 | i2c_set_clientdata(client, dac33); | ||
1250 | |||
1251 | dac33->power_gpio = pdata->power_gpio; | ||
1252 | dac33->burst_bclkdiv = pdata->burst_bclkdiv; | ||
1253 | dac33->irq = client->irq; | ||
1254 | dac33->nsample = NSAMPLE_MAX; | ||
1255 | /* Disable FIFO use by default */ | ||
1256 | dac33->fifo_mode = DAC33_FIFO_BYPASS; | ||
1257 | |||
1258 | tlv320dac33_codec = codec; | ||
1259 | |||
1260 | codec->dev = &client->dev; | ||
1261 | dac33_dai.dev = codec->dev; | ||
1262 | |||
1263 | /* Check if the reset GPIO number is valid and request it */ | ||
1264 | if (dac33->power_gpio >= 0) { | ||
1265 | ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); | ||
1266 | if (ret < 0) { | ||
1267 | dev_err(codec->dev, | ||
1268 | "Failed to request reset GPIO (%d)\n", | ||
1269 | dac33->power_gpio); | ||
1270 | snd_soc_unregister_dai(&dac33_dai); | ||
1271 | snd_soc_unregister_codec(codec); | ||
1272 | goto error_gpio; | ||
1273 | } | ||
1274 | gpio_direction_output(dac33->power_gpio, 0); | ||
1275 | } else { | ||
1276 | dac33->chip_power = 1; | ||
1277 | } | ||
1278 | |||
1279 | /* Check if the IRQ number is valid and request it */ | ||
1280 | if (dac33->irq >= 0) { | ||
1281 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | ||
1282 | IRQF_TRIGGER_RISING | IRQF_DISABLED, | ||
1283 | codec->name, codec); | ||
1284 | if (ret < 0) { | ||
1285 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | ||
1286 | dac33->irq, ret); | ||
1287 | dac33->irq = -1; | ||
1288 | } | ||
1289 | if (dac33->irq != -1) { | ||
1290 | /* Setup work queue */ | ||
1291 | dac33->dac33_wq = | ||
1292 | create_singlethread_workqueue("tlv320dac33"); | ||
1293 | if (dac33->dac33_wq == NULL) { | ||
1294 | free_irq(dac33->irq, &dac33->codec); | ||
1295 | ret = -ENOMEM; | ||
1296 | goto error_wq; | ||
1297 | } | ||
1298 | |||
1299 | INIT_WORK(&dac33->work, dac33_work); | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) | ||
1304 | dac33->supplies[i].supply = dac33_supply_names[i]; | ||
1305 | |||
1306 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), | ||
1307 | dac33->supplies); | ||
1308 | |||
1309 | if (ret != 0) { | ||
1310 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1311 | goto err_get; | ||
1312 | } | ||
1313 | |||
1314 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), | ||
1315 | dac33->supplies); | ||
1316 | if (ret != 0) { | ||
1317 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1318 | goto err_enable; | ||
1319 | } | ||
1320 | |||
1321 | ret = snd_soc_register_codec(codec); | ||
1322 | if (ret != 0) { | ||
1323 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1324 | goto error_codec; | ||
1325 | } | ||
1326 | |||
1327 | ret = snd_soc_register_dai(&dac33_dai); | ||
1328 | if (ret != 0) { | ||
1329 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1330 | snd_soc_unregister_codec(codec); | ||
1331 | goto error_codec; | ||
1332 | } | ||
1333 | |||
1334 | /* Shut down the codec for now */ | ||
1335 | dac33_hard_power(codec, 0); | ||
1336 | |||
1337 | return ret; | ||
1338 | |||
1339 | error_codec: | ||
1340 | regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1341 | err_enable: | ||
1342 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1343 | err_get: | ||
1344 | if (dac33->irq >= 0) { | ||
1345 | free_irq(dac33->irq, &dac33->codec); | ||
1346 | destroy_workqueue(dac33->dac33_wq); | ||
1347 | } | ||
1348 | error_wq: | ||
1349 | if (dac33->power_gpio >= 0) | ||
1350 | gpio_free(dac33->power_gpio); | ||
1351 | error_gpio: | ||
1352 | kfree(codec->reg_cache); | ||
1353 | error_reg: | ||
1354 | tlv320dac33_codec = NULL; | ||
1355 | kfree(dac33); | ||
1356 | |||
1357 | return ret; | ||
1358 | } | ||
1359 | |||
1360 | static int __devexit dac33_i2c_remove(struct i2c_client *client) | ||
1361 | { | ||
1362 | struct tlv320dac33_priv *dac33; | ||
1363 | |||
1364 | dac33 = i2c_get_clientdata(client); | ||
1365 | dac33_hard_power(&dac33->codec, 0); | ||
1366 | |||
1367 | if (dac33->power_gpio >= 0) | ||
1368 | gpio_free(dac33->power_gpio); | ||
1369 | if (dac33->irq >= 0) | ||
1370 | free_irq(dac33->irq, &dac33->codec); | ||
1371 | |||
1372 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1373 | |||
1374 | destroy_workqueue(dac33->dac33_wq); | ||
1375 | snd_soc_unregister_dai(&dac33_dai); | ||
1376 | snd_soc_unregister_codec(&dac33->codec); | ||
1377 | kfree(dac33->codec.reg_cache); | ||
1378 | kfree(dac33); | ||
1379 | tlv320dac33_codec = NULL; | ||
1380 | |||
1381 | return 0; | ||
1382 | } | ||
1383 | |||
1384 | static const struct i2c_device_id tlv320dac33_i2c_id[] = { | ||
1385 | { | ||
1386 | .name = "tlv320dac33", | ||
1387 | .driver_data = 0, | ||
1388 | }, | ||
1389 | { }, | ||
1390 | }; | ||
1391 | |||
1392 | static struct i2c_driver tlv320dac33_i2c_driver = { | ||
1393 | .driver = { | ||
1394 | .name = "tlv320dac33", | ||
1395 | .owner = THIS_MODULE, | ||
1396 | }, | ||
1397 | .probe = dac33_i2c_probe, | ||
1398 | .remove = __devexit_p(dac33_i2c_remove), | ||
1399 | .id_table = tlv320dac33_i2c_id, | ||
1400 | }; | ||
1401 | |||
1402 | static int __init dac33_module_init(void) | ||
1403 | { | ||
1404 | int r; | ||
1405 | r = i2c_add_driver(&tlv320dac33_i2c_driver); | ||
1406 | if (r < 0) { | ||
1407 | printk(KERN_ERR "DAC33: driver registration failed\n"); | ||
1408 | return r; | ||
1409 | } | ||
1410 | return 0; | ||
1411 | } | ||
1412 | module_init(dac33_module_init); | ||
1413 | |||
1414 | static void __exit dac33_module_exit(void) | ||
1415 | { | ||
1416 | i2c_del_driver(&tlv320dac33_i2c_driver); | ||
1417 | } | ||
1418 | module_exit(dac33_module_exit); | ||
1419 | |||
1420 | |||
1421 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); | ||
1422 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>"); | ||
1423 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h new file mode 100644 index 000000000000..eb8ae07f0bd2 --- /dev/null +++ b/sound/soc/codecs/tlv320dac33.h | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * ALSA SoC Texas Instruments TLV320DAC33 codec driver | ||
3 | * | ||
4 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | ||
5 | * | ||
6 | * Copyright: (C) 2009 Nokia Corporation | ||
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 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __TLV320DAC33_H | ||
25 | #define __TLV320DAC33_H | ||
26 | |||
27 | #define DAC33_PAGE_SELECT 0x00 | ||
28 | #define DAC33_PWR_CTRL 0x01 | ||
29 | #define DAC33_PLL_CTRL_A 0x02 | ||
30 | #define DAC33_PLL_CTRL_B 0x03 | ||
31 | #define DAC33_PLL_CTRL_C 0x04 | ||
32 | #define DAC33_PLL_CTRL_D 0x05 | ||
33 | #define DAC33_PLL_CTRL_E 0x06 | ||
34 | #define DAC33_INT_OSC_CTRL 0x07 | ||
35 | #define DAC33_INT_OSC_FREQ_RAT_A 0x08 | ||
36 | #define DAC33_INT_OSC_FREQ_RAT_B 0x09 | ||
37 | #define DAC33_INT_OSC_DAC_RATIO_SET 0x0A | ||
38 | #define DAC33_CALIB_TIME 0x0B | ||
39 | #define DAC33_INT_OSC_CTRL_B 0x0C | ||
40 | #define DAC33_INT_OSC_CTRL_C 0x0D | ||
41 | #define DAC33_INT_OSC_STATUS 0x0E | ||
42 | #define DAC33_INT_OSC_DAC_RATIO_READ 0x0F | ||
43 | #define DAC33_INT_OSC_FREQ_RAT_READ_A 0x10 | ||
44 | #define DAC33_INT_OSC_FREQ_RAT_READ_B 0x11 | ||
45 | #define DAC33_SER_AUDIOIF_CTRL_A 0x12 | ||
46 | #define DAC33_SER_AUDIOIF_CTRL_B 0x13 | ||
47 | #define DAC33_SER_AUDIOIF_CTRL_C 0x14 | ||
48 | #define DAC33_FIFO_CTRL_A 0x15 | ||
49 | #define DAC33_UTHR_MSB 0x16 | ||
50 | #define DAC33_UTHR_LSB 0x17 | ||
51 | #define DAC33_ATHR_MSB 0x18 | ||
52 | #define DAC33_ATHR_LSB 0x19 | ||
53 | #define DAC33_LTHR_MSB 0x1A | ||
54 | #define DAC33_LTHR_LSB 0x1B | ||
55 | #define DAC33_PREFILL_MSB 0x1C | ||
56 | #define DAC33_PREFILL_LSB 0x1D | ||
57 | #define DAC33_NSAMPLE_MSB 0x1E | ||
58 | #define DAC33_NSAMPLE_LSB 0x1F | ||
59 | #define DAC33_FIFO_WPTR_MSB 0x20 | ||
60 | #define DAC33_FIFO_WPTR_LSB 0x21 | ||
61 | #define DAC33_FIFO_RPTR_MSB 0x22 | ||
62 | #define DAC33_FIFO_RPTR_LSB 0x23 | ||
63 | #define DAC33_FIFO_DEPTH_MSB 0x24 | ||
64 | #define DAC33_FIFO_DEPTH_LSB 0x25 | ||
65 | #define DAC33_SAMPLES_REMAINING_MSB 0x26 | ||
66 | #define DAC33_SAMPLES_REMAINING_LSB 0x27 | ||
67 | #define DAC33_FIFO_IRQ_FLAG 0x28 | ||
68 | #define DAC33_FIFO_IRQ_MASK 0x29 | ||
69 | #define DAC33_FIFO_IRQ_MODE_A 0x2A | ||
70 | #define DAC33_FIFO_IRQ_MODE_B 0x2B | ||
71 | #define DAC33_DAC_CTRL_A 0x2C | ||
72 | #define DAC33_DAC_CTRL_B 0x2D | ||
73 | #define DAC33_DAC_CTRL_C 0x2E | ||
74 | #define DAC33_LDAC_DIG_VOL_CTRL 0x2F | ||
75 | #define DAC33_RDAC_DIG_VOL_CTRL 0x30 | ||
76 | #define DAC33_DAC_STATUS_FLAGS 0x31 | ||
77 | #define DAC33_ASRC_CTRL_A 0x32 | ||
78 | #define DAC33_ASRC_CTRL_B 0x33 | ||
79 | #define DAC33_SRC_REF_CLK_RATIO_A 0x34 | ||
80 | #define DAC33_SRC_REF_CLK_RATIO_B 0x35 | ||
81 | #define DAC33_SRC_EST_REF_CLK_RATIO_A 0x36 | ||
82 | #define DAC33_SRC_EST_REF_CLK_RATIO_B 0x37 | ||
83 | #define DAC33_INTP_CTRL_A 0x38 | ||
84 | #define DAC33_INTP_CTRL_B 0x39 | ||
85 | /* Registers 0x3A - 0x3F Reserved */ | ||
86 | #define DAC33_LDAC_PWR_CTRL 0x40 | ||
87 | #define DAC33_RDAC_PWR_CTRL 0x41 | ||
88 | #define DAC33_OUT_AMP_CM_CTRL 0x42 | ||
89 | #define DAC33_OUT_AMP_PWR_CTRL 0x43 | ||
90 | #define DAC33_OUT_AMP_CTRL 0x44 | ||
91 | #define DAC33_LINEL_TO_LLO_VOL 0x45 | ||
92 | /* Registers 0x45 - 0x47 Reserved */ | ||
93 | #define DAC33_LINER_TO_RLO_VOL 0x48 | ||
94 | #define DAC33_ANA_VOL_SOFT_STEP_CTRL 0x49 | ||
95 | #define DAC33_OSC_TRIM 0x4A | ||
96 | /* Registers 0x4B - 0x7C Reserved */ | ||
97 | #define DAC33_DEVICE_ID_MSB 0x7D | ||
98 | #define DAC33_DEVICE_ID_LSB 0x7E | ||
99 | #define DAC33_DEVICE_REV_ID 0x7F | ||
100 | |||
101 | #define DAC33_CACHEREGNUM 128 | ||
102 | |||
103 | /* Bit definitions */ | ||
104 | |||
105 | /* DAC33_PWR_CTRL (0x01) */ | ||
106 | #define DAC33_DACRPDNB (0x01 << 0) | ||
107 | #define DAC33_DACLPDNB (0x01 << 1) | ||
108 | #define DAC33_OSCPDNB (0x01 << 2) | ||
109 | #define DAC33_PLLPDNB (0x01 << 3) | ||
110 | #define DAC33_PDNALLB (0x01 << 4) | ||
111 | #define DAC33_SOFT_RESET (0x01 << 7) | ||
112 | |||
113 | /* DAC33_INT_OSC_CTRL (0x07) */ | ||
114 | #define DAC33_REFSEL (0x01 << 1) | ||
115 | |||
116 | /* DAC33_INT_OSC_CTRL_B (0x0C) */ | ||
117 | #define DAC33_ADJSTEP(x) (x << 0) | ||
118 | #define DAC33_ADJTHRSHLD(x) (x << 4) | ||
119 | |||
120 | /* DAC33_INT_OSC_CTRL_C (0x0D) */ | ||
121 | #define DAC33_REFDIV(x) (x << 4) | ||
122 | |||
123 | /* DAC33_INT_OSC_STATUS (0x0E) */ | ||
124 | #define DAC33_OSCSTATUS_IDLE_CALIB (0x00) | ||
125 | #define DAC33_OSCSTATUS_NORMAL (0x01) | ||
126 | #define DAC33_OSCSTATUS_ADJUSTMENT (0x03) | ||
127 | #define DAC33_OSCSTATUS_NOT_USED (0x02) | ||
128 | |||
129 | /* DAC33_SER_AUDIOIF_CTRL_A (0x12) */ | ||
130 | #define DAC33_MSWCLK (0x01 << 0) | ||
131 | #define DAC33_MSBCLK (0x01 << 1) | ||
132 | #define DAC33_AFMT_MASK (0x03 << 2) | ||
133 | #define DAC33_AFMT_I2S (0x00 << 2) | ||
134 | #define DAC33_AFMT_DSP (0x01 << 2) | ||
135 | #define DAC33_AFMT_RIGHT_J (0x02 << 2) | ||
136 | #define DAC33_AFMT_LEFT_J (0x03 << 2) | ||
137 | #define DAC33_WLEN_MASK (0x03 << 4) | ||
138 | #define DAC33_WLEN_16 (0x00 << 4) | ||
139 | #define DAC33_WLEN_20 (0x01 << 4) | ||
140 | #define DAC33_WLEN_24 (0x02 << 4) | ||
141 | #define DAC33_WLEN_32 (0x03 << 4) | ||
142 | #define DAC33_NCYCL_MASK (0x03 << 6) | ||
143 | #define DAC33_NCYCL_16 (0x00 << 6) | ||
144 | #define DAC33_NCYCL_20 (0x01 << 6) | ||
145 | #define DAC33_NCYCL_24 (0x02 << 6) | ||
146 | #define DAC33_NCYCL_32 (0x03 << 6) | ||
147 | |||
148 | /* DAC33_SER_AUDIOIF_CTRL_B (0x13) */ | ||
149 | #define DAC33_DATA_DELAY_MASK (0x03 << 2) | ||
150 | #define DAC33_DATA_DELAY(x) (x << 2) | ||
151 | #define DAC33_BCLKON (0x01 << 5) | ||
152 | |||
153 | /* DAC33_FIFO_CTRL_A (0x15) */ | ||
154 | #define DAC33_WIDTH (0x01 << 0) | ||
155 | #define DAC33_FBYPAS (0x01 << 1) | ||
156 | #define DAC33_FAUTO (0x01 << 2) | ||
157 | #define DAC33_FIFOFLUSH (0x01 << 3) | ||
158 | |||
159 | /* | ||
160 | * UTHR, ATHR, LTHR, PREFILL, NSAMPLE (0x16 - 0x1F) | ||
161 | * 13-bit values | ||
162 | */ | ||
163 | #define DAC33_THRREG(x) (((x) & 0x1FFF) << 3) | ||
164 | |||
165 | /* DAC33_FIFO_IRQ_MASK (0x29) */ | ||
166 | #define DAC33_MNS (0x01 << 0) | ||
167 | #define DAC33_MPS (0x01 << 1) | ||
168 | #define DAC33_MAT (0x01 << 2) | ||
169 | #define DAC33_MLT (0x01 << 3) | ||
170 | #define DAC33_MUT (0x01 << 4) | ||
171 | #define DAC33_MUF (0x01 << 5) | ||
172 | #define DAC33_MOF (0x01 << 6) | ||
173 | |||
174 | #define DAC33_FIFO_IRQ_MODE_MASK (0x03) | ||
175 | #define DAC33_FIFO_IRQ_MODE_RISING (0x00) | ||
176 | #define DAC33_FIFO_IRQ_MODE_FALLING (0x01) | ||
177 | #define DAC33_FIFO_IRQ_MODE_LEVEL (0x02) | ||
178 | #define DAC33_FIFO_IRQ_MODE_EDGE (0x03) | ||
179 | |||
180 | /* DAC33_FIFO_IRQ_MODE_A (0x2A) */ | ||
181 | #define DAC33_UTM(x) (x << 0) | ||
182 | #define DAC33_UFM(x) (x << 2) | ||
183 | #define DAC33_OFM(x) (x << 4) | ||
184 | |||
185 | /* DAC33_FIFO_IRQ_MODE_B (0x2B) */ | ||
186 | #define DAC33_NSM(x) (x << 0) | ||
187 | #define DAC33_PSM(x) (x << 2) | ||
188 | #define DAC33_ATM(x) (x << 4) | ||
189 | #define DAC33_LTM(x) (x << 6) | ||
190 | |||
191 | /* DAC33_DAC_CTRL_A (0x2C) */ | ||
192 | #define DAC33_DACRATE(x) (x << 0) | ||
193 | #define DAC33_DACDUAL (0x01 << 4) | ||
194 | #define DAC33_DACLKSEL_MASK (0x03 << 5) | ||
195 | #define DAC33_DACLKSEL_INTSOC (0x00 << 5) | ||
196 | #define DAC33_DACLKSEL_PLL (0x01 << 5) | ||
197 | #define DAC33_DACLKSEL_MCLK (0x02 << 5) | ||
198 | #define DAC33_DACLKSEL_BCLK (0x03 << 5) | ||
199 | |||
200 | /* DAC33_DAC_CTRL_B (0x2D) */ | ||
201 | #define DAC33_DACSRCR_MASK (0x03 << 0) | ||
202 | #define DAC33_DACSRCR_MUTE (0x00 << 0) | ||
203 | #define DAC33_DACSRCR_RIGHT (0x01 << 0) | ||
204 | #define DAC33_DACSRCR_LEFT (0x02 << 0) | ||
205 | #define DAC33_DACSRCR_MONOMIX (0x03 << 0) | ||
206 | #define DAC33_DACSRCL_MASK (0x03 << 2) | ||
207 | #define DAC33_DACSRCL_MUTE (0x00 << 2) | ||
208 | #define DAC33_DACSRCL_LEFT (0x01 << 2) | ||
209 | #define DAC33_DACSRCL_RIGHT (0x02 << 2) | ||
210 | #define DAC33_DACSRCL_MONOMIX (0x03 << 2) | ||
211 | #define DAC33_DVOLSTEP_MASK (0x03 << 4) | ||
212 | #define DAC33_DVOLSTEP_SS_PERFS (0x00 << 4) | ||
213 | #define DAC33_DVOLSTEP_SS_PER2FS (0x01 << 4) | ||
214 | #define DAC33_DVOLSTEP_SS_DISABLED (0x02 << 4) | ||
215 | #define DAC33_DVOLCTRL_MASK (0x03 << 6) | ||
216 | #define DAC33_DVOLCTRL_LR_INDEPENDENT1 (0x00 << 6) | ||
217 | #define DAC33_DVOLCTRL_LR_RIGHT_CONTROL (0x01 << 6) | ||
218 | #define DAC33_DVOLCTRL_LR_LEFT_CONTROL (0x02 << 6) | ||
219 | #define DAC33_DVOLCTRL_LR_INDEPENDENT2 (0x03 << 6) | ||
220 | |||
221 | /* DAC33_DAC_CTRL_C (0x2E) */ | ||
222 | #define DAC33_DEEMENR (0x01 << 0) | ||
223 | #define DAC33_EFFENR (0x01 << 1) | ||
224 | #define DAC33_DEEMENL (0x01 << 2) | ||
225 | #define DAC33_EFFENL (0x01 << 3) | ||
226 | #define DAC33_EN3D (0x01 << 4) | ||
227 | #define DAC33_RESYNMUTE (0x01 << 5) | ||
228 | #define DAC33_RESYNEN (0x01 << 6) | ||
229 | |||
230 | /* DAC33_ASRC_CTRL_A (0x32) */ | ||
231 | #define DAC33_SRCBYP (0x01 << 0) | ||
232 | #define DAC33_SRCLKSEL_MASK (0x03 << 1) | ||
233 | #define DAC33_SRCLKSEL_INTSOC (0x00 << 1) | ||
234 | #define DAC33_SRCLKSEL_PLL (0x01 << 1) | ||
235 | #define DAC33_SRCLKSEL_MCLK (0x02 << 1) | ||
236 | #define DAC33_SRCLKSEL_BCLK (0x03 << 1) | ||
237 | #define DAC33_SRCLKDIV(x) (x << 3) | ||
238 | |||
239 | /* DAC33_ASRC_CTRL_B (0x33) */ | ||
240 | #define DAC33_SRCSETUP(x) (x << 0) | ||
241 | #define DAC33_SRCREFSEL (0x01 << 4) | ||
242 | #define DAC33_SRCREFDIV(x) (x << 5) | ||
243 | |||
244 | /* DAC33_INTP_CTRL_A (0x38) */ | ||
245 | #define DAC33_INTPSEL (0x01 << 0) | ||
246 | #define DAC33_INTPM_MASK (0x03 << 1) | ||
247 | #define DAC33_INTPM_ALOW_OPENDRAIN (0x00 << 1) | ||
248 | #define DAC33_INTPM_ALOW (0x01 << 1) | ||
249 | #define DAC33_INTPM_AHIGH (0x02 << 1) | ||
250 | |||
251 | /* DAC33_LDAC_PWR_CTRL (0x40) */ | ||
252 | /* DAC33_RDAC_PWR_CTRL (0x41) */ | ||
253 | #define DAC33_DACLRNUM (0x01 << 2) | ||
254 | #define DAC33_LROUT_GAIN(x) (x << 0) | ||
255 | |||
256 | /* DAC33_ANA_VOL_SOFT_STEP_CTRL (0x49) */ | ||
257 | #define DAC33_VOLCLKSEL (0x01 << 0) | ||
258 | #define DAC33_VOLCLKEN (0x01 << 1) | ||
259 | #define DAC33_VOLBYPASS (0x01 << 2) | ||
260 | |||
261 | #define TLV320DAC33_MCLK 0 | ||
262 | #define TLV320DAC33_SLEEPCLK 1 | ||
263 | |||
264 | extern struct snd_soc_dai dac33_dai; | ||
265 | extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33; | ||
266 | |||
267 | #endif /* __TLV320DAC33_H */ | ||
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c new file mode 100644 index 000000000000..569ad8758a84 --- /dev/null +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -0,0 +1,531 @@ | |||
1 | /* | ||
2 | * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver | ||
3 | * | ||
4 | * Copyright (C) Nokia Corporation | ||
5 | * | ||
6 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/regulator/consumer.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/tpa6130a2-plat.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include <sound/soc-dapm.h> | ||
33 | #include <sound/tlv.h> | ||
34 | |||
35 | #include "tpa6130a2.h" | ||
36 | |||
37 | static struct i2c_client *tpa6130a2_client; | ||
38 | |||
39 | #define TPA6130A2_NUM_SUPPLIES 2 | ||
40 | static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { | ||
41 | "CPVSS", | ||
42 | "Vdd", | ||
43 | }; | ||
44 | |||
45 | static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { | ||
46 | "HPVdd", | ||
47 | "AVdd", | ||
48 | }; | ||
49 | |||
50 | /* This struct is used to save the context */ | ||
51 | struct tpa6130a2_data { | ||
52 | struct mutex mutex; | ||
53 | unsigned char regs[TPA6130A2_CACHEREGNUM]; | ||
54 | struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; | ||
55 | int power_gpio; | ||
56 | unsigned char power_state; | ||
57 | }; | ||
58 | |||
59 | static int tpa6130a2_i2c_read(int reg) | ||
60 | { | ||
61 | struct tpa6130a2_data *data; | ||
62 | int val; | ||
63 | |||
64 | BUG_ON(tpa6130a2_client == NULL); | ||
65 | data = i2c_get_clientdata(tpa6130a2_client); | ||
66 | |||
67 | /* If powered off, return the cached value */ | ||
68 | if (data->power_state) { | ||
69 | val = i2c_smbus_read_byte_data(tpa6130a2_client, reg); | ||
70 | if (val < 0) | ||
71 | dev_err(&tpa6130a2_client->dev, "Read failed\n"); | ||
72 | else | ||
73 | data->regs[reg] = val; | ||
74 | } else { | ||
75 | val = data->regs[reg]; | ||
76 | } | ||
77 | |||
78 | return val; | ||
79 | } | ||
80 | |||
81 | static int tpa6130a2_i2c_write(int reg, u8 value) | ||
82 | { | ||
83 | struct tpa6130a2_data *data; | ||
84 | int val = 0; | ||
85 | |||
86 | BUG_ON(tpa6130a2_client == NULL); | ||
87 | data = i2c_get_clientdata(tpa6130a2_client); | ||
88 | |||
89 | if (data->power_state) { | ||
90 | val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); | ||
91 | if (val < 0) | ||
92 | dev_err(&tpa6130a2_client->dev, "Write failed\n"); | ||
93 | } | ||
94 | |||
95 | /* Either powered on or off, we save the context */ | ||
96 | data->regs[reg] = value; | ||
97 | |||
98 | return val; | ||
99 | } | ||
100 | |||
101 | static u8 tpa6130a2_read(int reg) | ||
102 | { | ||
103 | struct tpa6130a2_data *data; | ||
104 | |||
105 | BUG_ON(tpa6130a2_client == NULL); | ||
106 | data = i2c_get_clientdata(tpa6130a2_client); | ||
107 | |||
108 | return data->regs[reg]; | ||
109 | } | ||
110 | |||
111 | static void tpa6130a2_initialize(void) | ||
112 | { | ||
113 | struct tpa6130a2_data *data; | ||
114 | int i; | ||
115 | |||
116 | BUG_ON(tpa6130a2_client == NULL); | ||
117 | data = i2c_get_clientdata(tpa6130a2_client); | ||
118 | |||
119 | for (i = 1; i < TPA6130A2_REG_VERSION; i++) | ||
120 | tpa6130a2_i2c_write(i, data->regs[i]); | ||
121 | } | ||
122 | |||
123 | static int tpa6130a2_power(int power) | ||
124 | { | ||
125 | struct tpa6130a2_data *data; | ||
126 | u8 val; | ||
127 | int ret; | ||
128 | |||
129 | BUG_ON(tpa6130a2_client == NULL); | ||
130 | data = i2c_get_clientdata(tpa6130a2_client); | ||
131 | |||
132 | mutex_lock(&data->mutex); | ||
133 | if (power) { | ||
134 | /* Power on */ | ||
135 | if (data->power_gpio >= 0) | ||
136 | gpio_set_value(data->power_gpio, 1); | ||
137 | |||
138 | ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), | ||
139 | data->supplies); | ||
140 | if (ret != 0) { | ||
141 | dev_err(&tpa6130a2_client->dev, | ||
142 | "Failed to enable supplies: %d\n", ret); | ||
143 | goto exit; | ||
144 | } | ||
145 | |||
146 | data->power_state = 1; | ||
147 | tpa6130a2_initialize(); | ||
148 | |||
149 | /* Clear SWS */ | ||
150 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | ||
151 | val &= ~TPA6130A2_SWS; | ||
152 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | ||
153 | } else { | ||
154 | /* set SWS */ | ||
155 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | ||
156 | val |= TPA6130A2_SWS; | ||
157 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | ||
158 | |||
159 | /* Power off */ | ||
160 | if (data->power_gpio >= 0) | ||
161 | gpio_set_value(data->power_gpio, 0); | ||
162 | |||
163 | ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies), | ||
164 | data->supplies); | ||
165 | if (ret != 0) { | ||
166 | dev_err(&tpa6130a2_client->dev, | ||
167 | "Failed to disable supplies: %d\n", ret); | ||
168 | goto exit; | ||
169 | } | ||
170 | |||
171 | data->power_state = 0; | ||
172 | } | ||
173 | |||
174 | exit: | ||
175 | mutex_unlock(&data->mutex); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, | ||
180 | struct snd_ctl_elem_value *ucontrol) | ||
181 | { | ||
182 | struct soc_mixer_control *mc = | ||
183 | (struct soc_mixer_control *)kcontrol->private_value; | ||
184 | struct tpa6130a2_data *data; | ||
185 | unsigned int reg = mc->reg; | ||
186 | unsigned int shift = mc->shift; | ||
187 | unsigned int mask = mc->max; | ||
188 | unsigned int invert = mc->invert; | ||
189 | |||
190 | BUG_ON(tpa6130a2_client == NULL); | ||
191 | data = i2c_get_clientdata(tpa6130a2_client); | ||
192 | |||
193 | mutex_lock(&data->mutex); | ||
194 | |||
195 | ucontrol->value.integer.value[0] = | ||
196 | (tpa6130a2_read(reg) >> shift) & mask; | ||
197 | |||
198 | if (invert) | ||
199 | ucontrol->value.integer.value[0] = | ||
200 | mask - ucontrol->value.integer.value[0]; | ||
201 | |||
202 | mutex_unlock(&data->mutex); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, | ||
207 | struct snd_ctl_elem_value *ucontrol) | ||
208 | { | ||
209 | struct soc_mixer_control *mc = | ||
210 | (struct soc_mixer_control *)kcontrol->private_value; | ||
211 | struct tpa6130a2_data *data; | ||
212 | unsigned int reg = mc->reg; | ||
213 | unsigned int shift = mc->shift; | ||
214 | unsigned int mask = mc->max; | ||
215 | unsigned int invert = mc->invert; | ||
216 | unsigned int val = (ucontrol->value.integer.value[0] & mask); | ||
217 | unsigned int val_reg; | ||
218 | |||
219 | BUG_ON(tpa6130a2_client == NULL); | ||
220 | data = i2c_get_clientdata(tpa6130a2_client); | ||
221 | |||
222 | if (invert) | ||
223 | val = mask - val; | ||
224 | |||
225 | mutex_lock(&data->mutex); | ||
226 | |||
227 | val_reg = tpa6130a2_read(reg); | ||
228 | if (((val_reg >> shift) & mask) == val) { | ||
229 | mutex_unlock(&data->mutex); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | val_reg &= ~(mask << shift); | ||
234 | val_reg |= val << shift; | ||
235 | tpa6130a2_i2c_write(reg, val_reg); | ||
236 | |||
237 | mutex_unlock(&data->mutex); | ||
238 | |||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going | ||
244 | * down in gain. | ||
245 | */ | ||
246 | static const unsigned int tpa6130_tlv[] = { | ||
247 | TLV_DB_RANGE_HEAD(10), | ||
248 | 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0), | ||
249 | 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0), | ||
250 | 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0), | ||
251 | 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0), | ||
252 | 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0), | ||
253 | 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0), | ||
254 | 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0), | ||
255 | 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0), | ||
256 | 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0), | ||
257 | 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0), | ||
258 | }; | ||
259 | |||
260 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { | ||
261 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", | ||
262 | TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, | ||
263 | tpa6130a2_get_reg, tpa6130a2_set_reg, | ||
264 | tpa6130_tlv), | ||
265 | }; | ||
266 | |||
267 | /* | ||
268 | * Enable or disable channel (left or right) | ||
269 | * The bit number for mute and amplifier are the same per channel: | ||
270 | * bit 6: Right channel | ||
271 | * bit 7: Left channel | ||
272 | * in both registers. | ||
273 | */ | ||
274 | static void tpa6130a2_channel_enable(u8 channel, int enable) | ||
275 | { | ||
276 | u8 val; | ||
277 | |||
278 | if (enable) { | ||
279 | /* Enable channel */ | ||
280 | /* Enable amplifier */ | ||
281 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | ||
282 | val |= channel; | ||
283 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | ||
284 | |||
285 | /* Unmute channel */ | ||
286 | val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); | ||
287 | val &= ~channel; | ||
288 | tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); | ||
289 | } else { | ||
290 | /* Disable channel */ | ||
291 | /* Mute channel */ | ||
292 | val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); | ||
293 | val |= channel; | ||
294 | tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); | ||
295 | |||
296 | /* Disable amplifier */ | ||
297 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | ||
298 | val &= ~channel; | ||
299 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w, | ||
304 | struct snd_kcontrol *kcontrol, int event) | ||
305 | { | ||
306 | switch (event) { | ||
307 | case SND_SOC_DAPM_POST_PMU: | ||
308 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1); | ||
309 | break; | ||
310 | case SND_SOC_DAPM_POST_PMD: | ||
311 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0); | ||
312 | break; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w, | ||
318 | struct snd_kcontrol *kcontrol, int event) | ||
319 | { | ||
320 | switch (event) { | ||
321 | case SND_SOC_DAPM_POST_PMU: | ||
322 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1); | ||
323 | break; | ||
324 | case SND_SOC_DAPM_POST_PMD: | ||
325 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0); | ||
326 | break; | ||
327 | } | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w, | ||
332 | struct snd_kcontrol *kcontrol, int event) | ||
333 | { | ||
334 | int ret = 0; | ||
335 | |||
336 | switch (event) { | ||
337 | case SND_SOC_DAPM_POST_PMU: | ||
338 | ret = tpa6130a2_power(1); | ||
339 | break; | ||
340 | case SND_SOC_DAPM_POST_PMD: | ||
341 | ret = tpa6130a2_power(0); | ||
342 | break; | ||
343 | } | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { | ||
348 | SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM, | ||
349 | 0, 0, NULL, 0, tpa6130a2_left_event, | ||
350 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
351 | SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM, | ||
352 | 0, 0, NULL, 0, tpa6130a2_right_event, | ||
353 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
354 | SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM, | ||
355 | 0, 0, tpa6130a2_supply_event, | ||
356 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
357 | /* Outputs */ | ||
358 | SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL), | ||
359 | SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL), | ||
360 | }; | ||
361 | |||
362 | static const struct snd_soc_dapm_route audio_map[] = { | ||
363 | {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"}, | ||
364 | {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"}, | ||
365 | |||
366 | {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"}, | ||
367 | {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"}, | ||
368 | }; | ||
369 | |||
370 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) | ||
371 | { | ||
372 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, | ||
373 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); | ||
374 | |||
375 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
376 | |||
377 | return snd_soc_add_controls(codec, tpa6130a2_controls, | ||
378 | ARRAY_SIZE(tpa6130a2_controls)); | ||
379 | |||
380 | } | ||
381 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); | ||
382 | |||
383 | static int __devinit tpa6130a2_probe(struct i2c_client *client, | ||
384 | const struct i2c_device_id *id) | ||
385 | { | ||
386 | struct device *dev; | ||
387 | struct tpa6130a2_data *data; | ||
388 | struct tpa6130a2_platform_data *pdata; | ||
389 | int i, ret; | ||
390 | |||
391 | dev = &client->dev; | ||
392 | |||
393 | if (client->dev.platform_data == NULL) { | ||
394 | dev_err(dev, "Platform data not set\n"); | ||
395 | dump_stack(); | ||
396 | return -ENODEV; | ||
397 | } | ||
398 | |||
399 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
400 | if (data == NULL) { | ||
401 | dev_err(dev, "Can not allocate memory\n"); | ||
402 | return -ENOMEM; | ||
403 | } | ||
404 | |||
405 | tpa6130a2_client = client; | ||
406 | |||
407 | i2c_set_clientdata(tpa6130a2_client, data); | ||
408 | |||
409 | pdata = client->dev.platform_data; | ||
410 | data->power_gpio = pdata->power_gpio; | ||
411 | |||
412 | mutex_init(&data->mutex); | ||
413 | |||
414 | /* Set default register values */ | ||
415 | data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS; | ||
416 | data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R | | ||
417 | TPA6130A2_MUTE_L; | ||
418 | |||
419 | if (data->power_gpio >= 0) { | ||
420 | ret = gpio_request(data->power_gpio, "tpa6130a2 enable"); | ||
421 | if (ret < 0) { | ||
422 | dev_err(dev, "Failed to request power GPIO (%d)\n", | ||
423 | data->power_gpio); | ||
424 | goto err_gpio; | ||
425 | } | ||
426 | gpio_direction_output(data->power_gpio, 0); | ||
427 | } | ||
428 | |||
429 | switch (pdata->id) { | ||
430 | case TPA6130A2: | ||
431 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | ||
432 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | ||
433 | break; | ||
434 | case TPA6140A2: | ||
435 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | ||
436 | data->supplies[i].supply = tpa6140a2_supply_names[i];; | ||
437 | break; | ||
438 | default: | ||
439 | dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", | ||
440 | pdata->id); | ||
441 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | ||
442 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | ||
443 | } | ||
444 | |||
445 | ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), | ||
446 | data->supplies); | ||
447 | if (ret != 0) { | ||
448 | dev_err(dev, "Failed to request supplies: %d\n", ret); | ||
449 | goto err_regulator; | ||
450 | } | ||
451 | |||
452 | ret = tpa6130a2_power(1); | ||
453 | if (ret != 0) | ||
454 | goto err_power; | ||
455 | |||
456 | |||
457 | /* Read version */ | ||
458 | ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & | ||
459 | TPA6130A2_VERSION_MASK; | ||
460 | if ((ret != 1) && (ret != 2)) | ||
461 | dev_warn(dev, "UNTESTED version detected (%d)\n", ret); | ||
462 | |||
463 | /* Disable the chip */ | ||
464 | ret = tpa6130a2_power(0); | ||
465 | if (ret != 0) | ||
466 | goto err_power; | ||
467 | |||
468 | return 0; | ||
469 | |||
470 | err_power: | ||
471 | regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); | ||
472 | err_regulator: | ||
473 | if (data->power_gpio >= 0) | ||
474 | gpio_free(data->power_gpio); | ||
475 | err_gpio: | ||
476 | kfree(data); | ||
477 | i2c_set_clientdata(tpa6130a2_client, NULL); | ||
478 | tpa6130a2_client = NULL; | ||
479 | |||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | static int __devexit tpa6130a2_remove(struct i2c_client *client) | ||
484 | { | ||
485 | struct tpa6130a2_data *data = i2c_get_clientdata(client); | ||
486 | |||
487 | tpa6130a2_power(0); | ||
488 | |||
489 | if (data->power_gpio >= 0) | ||
490 | gpio_free(data->power_gpio); | ||
491 | |||
492 | regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); | ||
493 | |||
494 | kfree(data); | ||
495 | tpa6130a2_client = NULL; | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static const struct i2c_device_id tpa6130a2_id[] = { | ||
501 | { "tpa6130a2", 0 }, | ||
502 | { } | ||
503 | }; | ||
504 | MODULE_DEVICE_TABLE(i2c, tpa6130a2_id); | ||
505 | |||
506 | static struct i2c_driver tpa6130a2_i2c_driver = { | ||
507 | .driver = { | ||
508 | .name = "tpa6130a2", | ||
509 | .owner = THIS_MODULE, | ||
510 | }, | ||
511 | .probe = tpa6130a2_probe, | ||
512 | .remove = __devexit_p(tpa6130a2_remove), | ||
513 | .id_table = tpa6130a2_id, | ||
514 | }; | ||
515 | |||
516 | static int __init tpa6130a2_init(void) | ||
517 | { | ||
518 | return i2c_add_driver(&tpa6130a2_i2c_driver); | ||
519 | } | ||
520 | |||
521 | static void __exit tpa6130a2_exit(void) | ||
522 | { | ||
523 | i2c_del_driver(&tpa6130a2_i2c_driver); | ||
524 | } | ||
525 | |||
526 | MODULE_AUTHOR("Peter Ujfalusi"); | ||
527 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); | ||
528 | MODULE_LICENSE("GPL"); | ||
529 | |||
530 | module_init(tpa6130a2_init); | ||
531 | module_exit(tpa6130a2_exit); | ||
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h new file mode 100644 index 000000000000..57e867fd86d1 --- /dev/null +++ b/sound/soc/codecs/tpa6130a2.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * ALSA SoC TPA6130A2 amplifier driver | ||
3 | * | ||
4 | * Copyright (C) Nokia Corporation | ||
5 | * | ||
6 | * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __TPA6130A2_H__ | ||
25 | #define __TPA6130A2_H__ | ||
26 | |||
27 | /* Register addresses */ | ||
28 | #define TPA6130A2_REG_CONTROL 0x01 | ||
29 | #define TPA6130A2_REG_VOL_MUTE 0x02 | ||
30 | #define TPA6130A2_REG_OUT_IMPEDANCE 0x03 | ||
31 | #define TPA6130A2_REG_VERSION 0x04 | ||
32 | |||
33 | #define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1) | ||
34 | |||
35 | /* Register bits */ | ||
36 | /* TPA6130A2_REG_CONTROL (0x01) */ | ||
37 | #define TPA6130A2_SWS (0x01 << 0) | ||
38 | #define TPA6130A2_TERMAL (0x01 << 1) | ||
39 | #define TPA6130A2_MODE(x) (x << 4) | ||
40 | #define TPA6130A2_MODE_STEREO (0x00) | ||
41 | #define TPA6130A2_MODE_DUAL_MONO (0x01) | ||
42 | #define TPA6130A2_MODE_BRIDGE (0x02) | ||
43 | #define TPA6130A2_MODE_MASK (0x03) | ||
44 | #define TPA6130A2_HP_EN_R (0x01 << 6) | ||
45 | #define TPA6130A2_HP_EN_L (0x01 << 7) | ||
46 | |||
47 | /* TPA6130A2_REG_VOL_MUTE (0x02) */ | ||
48 | #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) | ||
49 | #define TPA6130A2_MUTE_R (0x01 << 6) | ||
50 | #define TPA6130A2_MUTE_L (0x01 << 7) | ||
51 | |||
52 | /* TPA6130A2_REG_OUT_IMPEDANCE (0x03) */ | ||
53 | #define TPA6130A2_HIZ_R (0x01 << 0) | ||
54 | #define TPA6130A2_HIZ_L (0x01 << 1) | ||
55 | |||
56 | /* TPA6130A2_REG_VERSION (0x04) */ | ||
57 | #define TPA6130A2_VERSION_MASK (0x0f) | ||
58 | |||
59 | extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); | ||
60 | |||
61 | #endif /* __TPA6130A2_H__ */ | ||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 4df7c6c61c76..520ffd6536c3 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/i2c/twl4030.h> | 29 | #include <linux/i2c/twl.h> |
30 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -55,7 +56,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | |||
55 | 0x0c, /* REG_ATXR1PGA (0xB) */ | 56 | 0x0c, /* REG_ATXR1PGA (0xB) */ |
56 | 0x00, /* REG_AVTXL2PGA (0xC) */ | 57 | 0x00, /* REG_AVTXL2PGA (0xC) */ |
57 | 0x00, /* REG_AVTXR2PGA (0xD) */ | 58 | 0x00, /* REG_AVTXR2PGA (0xD) */ |
58 | 0x01, /* REG_AUDIO_IF (0xE) */ | 59 | 0x00, /* REG_AUDIO_IF (0xE) */ |
59 | 0x00, /* REG_VOICE_IF (0xF) */ | 60 | 0x00, /* REG_VOICE_IF (0xF) */ |
60 | 0x00, /* REG_ARXR1PGA (0x10) */ | 61 | 0x00, /* REG_ARXR1PGA (0x10) */ |
61 | 0x00, /* REG_ARXL1PGA (0x11) */ | 62 | 0x00, /* REG_ARXL1PGA (0x11) */ |
@@ -64,19 +65,19 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | |||
64 | 0x00, /* REG_VRXPGA (0x14) */ | 65 | 0x00, /* REG_VRXPGA (0x14) */ |
65 | 0x00, /* REG_VSTPGA (0x15) */ | 66 | 0x00, /* REG_VSTPGA (0x15) */ |
66 | 0x00, /* REG_VRX2ARXPGA (0x16) */ | 67 | 0x00, /* REG_VRX2ARXPGA (0x16) */ |
67 | 0x0c, /* REG_AVDAC_CTL (0x17) */ | 68 | 0x00, /* REG_AVDAC_CTL (0x17) */ |
68 | 0x00, /* REG_ARX2VTXPGA (0x18) */ | 69 | 0x00, /* REG_ARX2VTXPGA (0x18) */ |
69 | 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ | 70 | 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ |
70 | 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ | 71 | 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ |
71 | 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */ | 72 | 0x4a, /* REG_ARXL2_APGA_CTL (0x1B) */ |
72 | 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */ | 73 | 0x4a, /* REG_ARXR2_APGA_CTL (0x1C) */ |
73 | 0x00, /* REG_ATX2ARXPGA (0x1D) */ | 74 | 0x00, /* REG_ATX2ARXPGA (0x1D) */ |
74 | 0x00, /* REG_BT_IF (0x1E) */ | 75 | 0x00, /* REG_BT_IF (0x1E) */ |
75 | 0x00, /* REG_BTPGA (0x1F) */ | 76 | 0x00, /* REG_BTPGA (0x1F) */ |
76 | 0x00, /* REG_BTSTPGA (0x20) */ | 77 | 0x00, /* REG_BTSTPGA (0x20) */ |
77 | 0x00, /* REG_EAR_CTL (0x21) */ | 78 | 0x00, /* REG_EAR_CTL (0x21) */ |
78 | 0x24, /* REG_HS_SEL (0x22) */ | 79 | 0x00, /* REG_HS_SEL (0x22) */ |
79 | 0x0a, /* REG_HS_GAIN_SET (0x23) */ | 80 | 0x00, /* REG_HS_GAIN_SET (0x23) */ |
80 | 0x00, /* REG_HS_POPN_SET (0x24) */ | 81 | 0x00, /* REG_HS_POPN_SET (0x24) */ |
81 | 0x00, /* REG_PREDL_CTL (0x25) */ | 82 | 0x00, /* REG_PREDL_CTL (0x25) */ |
82 | 0x00, /* REG_PREDR_CTL (0x26) */ | 83 | 0x00, /* REG_PREDR_CTL (0x26) */ |
@@ -99,7 +100,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | |||
99 | 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ | 100 | 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ |
100 | 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ | 101 | 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ |
101 | 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ | 102 | 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ |
102 | 0x16, /* REG_APLL_CTL (0x3A) */ | 103 | 0x06, /* REG_APLL_CTL (0x3A) */ |
103 | 0x00, /* REG_DTMF_CTL (0x3B) */ | 104 | 0x00, /* REG_DTMF_CTL (0x3B) */ |
104 | 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */ | 105 | 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */ |
105 | 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */ | 106 | 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */ |
@@ -120,9 +121,10 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | |||
120 | 121 | ||
121 | /* codec private data */ | 122 | /* codec private data */ |
122 | struct twl4030_priv { | 123 | struct twl4030_priv { |
123 | unsigned int bypass_state; | 124 | struct snd_soc_codec codec; |
125 | |||
124 | unsigned int codec_powered; | 126 | unsigned int codec_powered; |
125 | unsigned int codec_muted; | 127 | unsigned int apll_enabled; |
126 | 128 | ||
127 | struct snd_pcm_substream *master_substream; | 129 | struct snd_pcm_substream *master_substream; |
128 | struct snd_pcm_substream *slave_substream; | 130 | struct snd_pcm_substream *slave_substream; |
@@ -174,7 +176,7 @@ static int twl4030_write(struct snd_soc_codec *codec, | |||
174 | { | 176 | { |
175 | twl4030_write_reg_cache(codec, reg, value); | 177 | twl4030_write_reg_cache(codec, reg, value); |
176 | if (likely(reg < TWL4030_REG_SW_SHADOW)) | 178 | if (likely(reg < TWL4030_REG_SW_SHADOW)) |
177 | return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, | 179 | return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, |
178 | reg); | 180 | reg); |
179 | else | 181 | else |
180 | return 0; | 182 | return 0; |
@@ -183,19 +185,20 @@ static int twl4030_write(struct snd_soc_codec *codec, | |||
183 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) | 185 | static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) |
184 | { | 186 | { |
185 | struct twl4030_priv *twl4030 = codec->private_data; | 187 | struct twl4030_priv *twl4030 = codec->private_data; |
186 | u8 mode; | 188 | int mode; |
187 | 189 | ||
188 | if (enable == twl4030->codec_powered) | 190 | if (enable == twl4030->codec_powered) |
189 | return; | 191 | return; |
190 | 192 | ||
191 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | ||
192 | if (enable) | 193 | if (enable) |
193 | mode |= TWL4030_CODECPDZ; | 194 | mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); |
194 | else | 195 | else |
195 | mode &= ~TWL4030_CODECPDZ; | 196 | mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); |
196 | 197 | ||
197 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); | 198 | if (mode >= 0) { |
198 | twl4030->codec_powered = enable; | 199 | twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode); |
200 | twl4030->codec_powered = enable; | ||
201 | } | ||
199 | 202 | ||
200 | /* REVISIT: this delay is present in TI sample drivers */ | 203 | /* REVISIT: this delay is present in TI sample drivers */ |
201 | /* but there seems to be no TRM requirement for it */ | 204 | /* but there seems to be no TRM requirement for it */ |
@@ -212,31 +215,30 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
212 | 215 | ||
213 | /* set all audio section registers to reasonable defaults */ | 216 | /* set all audio section registers to reasonable defaults */ |
214 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) | 217 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) |
215 | twl4030_write(codec, i, cache[i]); | 218 | if (i != TWL4030_REG_APLL_CTL) |
219 | twl4030_write(codec, i, cache[i]); | ||
216 | 220 | ||
217 | } | 221 | } |
218 | 222 | ||
219 | static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) | 223 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) |
220 | { | 224 | { |
221 | struct twl4030_priv *twl4030 = codec->private_data; | 225 | struct twl4030_priv *twl4030 = codec->private_data; |
222 | u8 reg_val; | 226 | int status; |
223 | 227 | ||
224 | if (mute == twl4030->codec_muted) | 228 | if (enable == twl4030->apll_enabled) |
225 | return; | 229 | return; |
226 | 230 | ||
227 | if (mute) { | 231 | if (enable) |
228 | /* Disable PLL */ | ||
229 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); | ||
230 | reg_val &= ~TWL4030_APLL_EN; | ||
231 | twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); | ||
232 | } else { | ||
233 | /* Enable PLL */ | 232 | /* Enable PLL */ |
234 | reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); | 233 | status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); |
235 | reg_val |= TWL4030_APLL_EN; | 234 | else |
236 | twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); | 235 | /* Disable PLL */ |
237 | } | 236 | status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); |
237 | |||
238 | if (status >= 0) | ||
239 | twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); | ||
238 | 240 | ||
239 | twl4030->codec_muted = mute; | 241 | twl4030->apll_enabled = enable; |
240 | } | 242 | } |
241 | 243 | ||
242 | static void twl4030_power_up(struct snd_soc_codec *codec) | 244 | static void twl4030_power_up(struct snd_soc_codec *codec) |
@@ -260,7 +262,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec) | |||
260 | do { | 262 | do { |
261 | /* this takes a little while, so don't slam i2c */ | 263 | /* this takes a little while, so don't slam i2c */ |
262 | udelay(2000); | 264 | udelay(2000); |
263 | twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | 265 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, |
264 | TWL4030_REG_ANAMICL); | 266 | TWL4030_REG_ANAMICL); |
265 | } while ((i++ < 100) && | 267 | } while ((i++ < 100) && |
266 | ((byte & TWL4030_CNCL_OFFSET_START) == | 268 | ((byte & TWL4030_CNCL_OFFSET_START) == |
@@ -541,7 +543,7 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ | |||
541 | break; \ | 543 | break; \ |
542 | case SND_SOC_DAPM_POST_PMD: \ | 544 | case SND_SOC_DAPM_POST_PMD: \ |
543 | reg_val = twl4030_read_reg_cache(w->codec, reg); \ | 545 | reg_val = twl4030_read_reg_cache(w->codec, reg); \ |
544 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ | 546 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ |
545 | reg_val & (~mask), \ | 547 | reg_val & (~mask), \ |
546 | reg); \ | 548 | reg); \ |
547 | break; \ | 549 | break; \ |
@@ -613,6 +615,27 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | |||
613 | return 0; | 615 | return 0; |
614 | } | 616 | } |
615 | 617 | ||
618 | static int vibramux_event(struct snd_soc_dapm_widget *w, | ||
619 | struct snd_kcontrol *kcontrol, int event) | ||
620 | { | ||
621 | twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int apll_event(struct snd_soc_dapm_widget *w, | ||
626 | struct snd_kcontrol *kcontrol, int event) | ||
627 | { | ||
628 | switch (event) { | ||
629 | case SND_SOC_DAPM_PRE_PMU: | ||
630 | twl4030_apll_enable(w->codec, 1); | ||
631 | break; | ||
632 | case SND_SOC_DAPM_POST_PMD: | ||
633 | twl4030_apll_enable(w->codec, 0); | ||
634 | break; | ||
635 | } | ||
636 | return 0; | ||
637 | } | ||
638 | |||
616 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 639 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
617 | { | 640 | { |
618 | struct snd_soc_device *socdev = codec->socdev; | 641 | struct snd_soc_device *socdev = codec->socdev; |
@@ -657,7 +680,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
657 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / | 680 | mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / |
658 | twl4030->sysclk) + 1); | 681 | twl4030->sysclk) + 1); |
659 | /* Bypass the reg_cache to mute the headset */ | 682 | /* Bypass the reg_cache to mute the headset */ |
660 | twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 683 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
661 | hs_gain & (~0x0f), | 684 | hs_gain & (~0x0f), |
662 | TWL4030_REG_HS_GAIN_SET); | 685 | TWL4030_REG_HS_GAIN_SET); |
663 | 686 | ||
@@ -724,67 +747,6 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w, | |||
724 | return 0; | 747 | return 0; |
725 | } | 748 | } |
726 | 749 | ||
727 | static int bypass_event(struct snd_soc_dapm_widget *w, | ||
728 | struct snd_kcontrol *kcontrol, int event) | ||
729 | { | ||
730 | struct soc_mixer_control *m = | ||
731 | (struct soc_mixer_control *)w->kcontrols->private_value; | ||
732 | struct twl4030_priv *twl4030 = w->codec->private_data; | ||
733 | unsigned char reg, misc; | ||
734 | |||
735 | reg = twl4030_read_reg_cache(w->codec, m->reg); | ||
736 | |||
737 | /* | ||
738 | * bypass_state[0:3] - analog HiFi bypass | ||
739 | * bypass_state[4] - analog voice bypass | ||
740 | * bypass_state[5] - digital voice bypass | ||
741 | * bypass_state[6:7] - digital HiFi bypass | ||
742 | */ | ||
743 | if (m->reg == TWL4030_REG_VSTPGA) { | ||
744 | /* Voice digital bypass */ | ||
745 | if (reg) | ||
746 | twl4030->bypass_state |= (1 << 5); | ||
747 | else | ||
748 | twl4030->bypass_state &= ~(1 << 5); | ||
749 | } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { | ||
750 | /* Analog bypass */ | ||
751 | if (reg & (1 << m->shift)) | ||
752 | twl4030->bypass_state |= | ||
753 | (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); | ||
754 | else | ||
755 | twl4030->bypass_state &= | ||
756 | ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); | ||
757 | } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) { | ||
758 | /* Analog voice bypass */ | ||
759 | if (reg & (1 << m->shift)) | ||
760 | twl4030->bypass_state |= (1 << 4); | ||
761 | else | ||
762 | twl4030->bypass_state &= ~(1 << 4); | ||
763 | } else { | ||
764 | /* Digital bypass */ | ||
765 | if (reg & (0x7 << m->shift)) | ||
766 | twl4030->bypass_state |= (1 << (m->shift ? 7 : 6)); | ||
767 | else | ||
768 | twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6)); | ||
769 | } | ||
770 | |||
771 | /* Enable master analog loopback mode if any analog switch is enabled*/ | ||
772 | misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1); | ||
773 | if (twl4030->bypass_state & 0x1F) | ||
774 | misc |= TWL4030_FMLOOP_EN; | ||
775 | else | ||
776 | misc &= ~TWL4030_FMLOOP_EN; | ||
777 | twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc); | ||
778 | |||
779 | if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { | ||
780 | if (twl4030->bypass_state) | ||
781 | twl4030_codec_mute(w->codec, 0); | ||
782 | else | ||
783 | twl4030_codec_mute(w->codec, 1); | ||
784 | } | ||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | /* | 750 | /* |
789 | * Some of the gain controls in TWL (mostly those which are associated with | 751 | * Some of the gain controls in TWL (mostly those which are associated with |
790 | * the outputs) are implemented in an interesting way: | 752 | * the outputs) are implemented in an interesting way: |
@@ -1192,32 +1154,28 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1192 | SND_SOC_NOPM, 0, 0), | 1154 | SND_SOC_NOPM, 0, 0), |
1193 | 1155 | ||
1194 | /* Analog bypasses */ | 1156 | /* Analog bypasses */ |
1195 | SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1157 | SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, |
1196 | &twl4030_dapm_abypassr1_control, bypass_event, | 1158 | &twl4030_dapm_abypassr1_control), |
1197 | SND_SOC_DAPM_POST_REG), | 1159 | SND_SOC_DAPM_SWITCH("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, |
1198 | SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1160 | &twl4030_dapm_abypassl1_control), |
1199 | &twl4030_dapm_abypassl1_control, | 1161 | SND_SOC_DAPM_SWITCH("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, |
1200 | bypass_event, SND_SOC_DAPM_POST_REG), | 1162 | &twl4030_dapm_abypassr2_control), |
1201 | SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1163 | SND_SOC_DAPM_SWITCH("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, |
1202 | &twl4030_dapm_abypassr2_control, | 1164 | &twl4030_dapm_abypassl2_control), |
1203 | bypass_event, SND_SOC_DAPM_POST_REG), | 1165 | SND_SOC_DAPM_SWITCH("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, |
1204 | SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1166 | &twl4030_dapm_abypassv_control), |
1205 | &twl4030_dapm_abypassl2_control, | 1167 | |
1206 | bypass_event, SND_SOC_DAPM_POST_REG), | 1168 | /* Master analog loopback switch */ |
1207 | SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, | 1169 | SND_SOC_DAPM_SUPPLY("FM Loop Enable", TWL4030_REG_MISC_SET_1, 5, 0, |
1208 | &twl4030_dapm_abypassv_control, | 1170 | NULL, 0), |
1209 | bypass_event, SND_SOC_DAPM_POST_REG), | ||
1210 | 1171 | ||
1211 | /* Digital bypasses */ | 1172 | /* Digital bypasses */ |
1212 | SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, | 1173 | SND_SOC_DAPM_SWITCH("Left Digital Loopback", SND_SOC_NOPM, 0, 0, |
1213 | &twl4030_dapm_dbypassl_control, bypass_event, | 1174 | &twl4030_dapm_dbypassl_control), |
1214 | SND_SOC_DAPM_POST_REG), | 1175 | SND_SOC_DAPM_SWITCH("Right Digital Loopback", SND_SOC_NOPM, 0, 0, |
1215 | SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, | 1176 | &twl4030_dapm_dbypassr_control), |
1216 | &twl4030_dapm_dbypassr_control, bypass_event, | 1177 | SND_SOC_DAPM_SWITCH("Voice Digital Loopback", SND_SOC_NOPM, 0, 0, |
1217 | SND_SOC_DAPM_POST_REG), | 1178 | &twl4030_dapm_dbypassv_control), |
1218 | SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0, | ||
1219 | &twl4030_dapm_dbypassv_control, bypass_event, | ||
1220 | SND_SOC_DAPM_POST_REG), | ||
1221 | 1179 | ||
1222 | /* Digital mixers, power control for the physical DACs */ | 1180 | /* Digital mixers, power control for the physical DACs */ |
1223 | SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", | 1181 | SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", |
@@ -1243,6 +1201,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1243 | SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", | 1201 | SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", |
1244 | TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), | 1202 | TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), |
1245 | 1203 | ||
1204 | SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event, | ||
1205 | SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), | ||
1206 | |||
1207 | SND_SOC_DAPM_SUPPLY("AIF Enable", TWL4030_REG_AUDIO_IF, 0, 0, NULL, 0), | ||
1208 | |||
1246 | /* Output MIXER controls */ | 1209 | /* Output MIXER controls */ |
1247 | /* Earpiece */ | 1210 | /* Earpiece */ |
1248 | SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, | 1211 | SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, |
@@ -1308,8 +1271,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1308 | 0, 0, NULL, 0, handsfreerpga_event, | 1271 | 0, 0, NULL, 0, handsfreerpga_event, |
1309 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | 1272 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), |
1310 | /* Vibra */ | 1273 | /* Vibra */ |
1311 | SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, | 1274 | SND_SOC_DAPM_MUX_E("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, |
1312 | &twl4030_dapm_vibra_control), | 1275 | &twl4030_dapm_vibra_control, vibramux_event, |
1276 | SND_SOC_DAPM_PRE_PMU), | ||
1313 | SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, | 1277 | SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, |
1314 | &twl4030_dapm_vibrapath_control), | 1278 | &twl4030_dapm_vibrapath_control), |
1315 | 1279 | ||
@@ -1369,6 +1333,18 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1369 | {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, | 1333 | {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, |
1370 | {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, | 1334 | {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, |
1371 | 1335 | ||
1336 | /* Supply for the digital part (APLL) */ | ||
1337 | {"Digital R1 Playback Mixer", NULL, "APLL Enable"}, | ||
1338 | {"Digital L1 Playback Mixer", NULL, "APLL Enable"}, | ||
1339 | {"Digital R2 Playback Mixer", NULL, "APLL Enable"}, | ||
1340 | {"Digital L2 Playback Mixer", NULL, "APLL Enable"}, | ||
1341 | {"Digital Voice Playback Mixer", NULL, "APLL Enable"}, | ||
1342 | |||
1343 | {"Digital R1 Playback Mixer", NULL, "AIF Enable"}, | ||
1344 | {"Digital L1 Playback Mixer", NULL, "AIF Enable"}, | ||
1345 | {"Digital R2 Playback Mixer", NULL, "AIF Enable"}, | ||
1346 | {"Digital L2 Playback Mixer", NULL, "AIF Enable"}, | ||
1347 | |||
1372 | {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, | 1348 | {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, |
1373 | {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, | 1349 | {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, |
1374 | {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, | 1350 | {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, |
@@ -1482,6 +1458,16 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1482 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, | 1458 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, |
1483 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, | 1459 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, |
1484 | 1460 | ||
1461 | {"ADC Virtual Left1", NULL, "APLL Enable"}, | ||
1462 | {"ADC Virtual Right1", NULL, "APLL Enable"}, | ||
1463 | {"ADC Virtual Left2", NULL, "APLL Enable"}, | ||
1464 | {"ADC Virtual Right2", NULL, "APLL Enable"}, | ||
1465 | |||
1466 | {"ADC Virtual Left1", NULL, "AIF Enable"}, | ||
1467 | {"ADC Virtual Right1", NULL, "AIF Enable"}, | ||
1468 | {"ADC Virtual Left2", NULL, "AIF Enable"}, | ||
1469 | {"ADC Virtual Right2", NULL, "AIF Enable"}, | ||
1470 | |||
1485 | /* Analog bypass routes */ | 1471 | /* Analog bypass routes */ |
1486 | {"Right1 Analog Loopback", "Switch", "Analog Right"}, | 1472 | {"Right1 Analog Loopback", "Switch", "Analog Right"}, |
1487 | {"Left1 Analog Loopback", "Switch", "Analog Left"}, | 1473 | {"Left1 Analog Loopback", "Switch", "Analog Left"}, |
@@ -1489,6 +1475,13 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1489 | {"Left2 Analog Loopback", "Switch", "Analog Left"}, | 1475 | {"Left2 Analog Loopback", "Switch", "Analog Left"}, |
1490 | {"Voice Analog Loopback", "Switch", "Analog Left"}, | 1476 | {"Voice Analog Loopback", "Switch", "Analog Left"}, |
1491 | 1477 | ||
1478 | /* Supply for the Analog loopbacks */ | ||
1479 | {"Right1 Analog Loopback", NULL, "FM Loop Enable"}, | ||
1480 | {"Left1 Analog Loopback", NULL, "FM Loop Enable"}, | ||
1481 | {"Right2 Analog Loopback", NULL, "FM Loop Enable"}, | ||
1482 | {"Left2 Analog Loopback", NULL, "FM Loop Enable"}, | ||
1483 | {"Voice Analog Loopback", NULL, "FM Loop Enable"}, | ||
1484 | |||
1492 | {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, | 1485 | {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, |
1493 | {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, | 1486 | {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, |
1494 | {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, | 1487 | {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, |
@@ -1513,32 +1506,20 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec) | |||
1513 | 1506 | ||
1514 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 1507 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
1515 | 1508 | ||
1516 | snd_soc_dapm_new_widgets(codec); | ||
1517 | return 0; | 1509 | return 0; |
1518 | } | 1510 | } |
1519 | 1511 | ||
1520 | static int twl4030_set_bias_level(struct snd_soc_codec *codec, | 1512 | static int twl4030_set_bias_level(struct snd_soc_codec *codec, |
1521 | enum snd_soc_bias_level level) | 1513 | enum snd_soc_bias_level level) |
1522 | { | 1514 | { |
1523 | struct twl4030_priv *twl4030 = codec->private_data; | ||
1524 | |||
1525 | switch (level) { | 1515 | switch (level) { |
1526 | case SND_SOC_BIAS_ON: | 1516 | case SND_SOC_BIAS_ON: |
1527 | twl4030_codec_mute(codec, 0); | ||
1528 | break; | 1517 | break; |
1529 | case SND_SOC_BIAS_PREPARE: | 1518 | case SND_SOC_BIAS_PREPARE: |
1530 | twl4030_power_up(codec); | ||
1531 | if (twl4030->bypass_state) | ||
1532 | twl4030_codec_mute(codec, 0); | ||
1533 | else | ||
1534 | twl4030_codec_mute(codec, 1); | ||
1535 | break; | 1519 | break; |
1536 | case SND_SOC_BIAS_STANDBY: | 1520 | case SND_SOC_BIAS_STANDBY: |
1537 | twl4030_power_up(codec); | 1521 | if (codec->bias_level == SND_SOC_BIAS_OFF) |
1538 | if (twl4030->bypass_state) | 1522 | twl4030_power_up(codec); |
1539 | twl4030_codec_mute(codec, 0); | ||
1540 | else | ||
1541 | twl4030_codec_mute(codec, 1); | ||
1542 | break; | 1523 | break; |
1543 | case SND_SOC_BIAS_OFF: | 1524 | case SND_SOC_BIAS_OFF: |
1544 | twl4030_power_down(codec); | 1525 | twl4030_power_down(codec); |
@@ -1785,29 +1766,23 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1785 | { | 1766 | { |
1786 | struct snd_soc_codec *codec = codec_dai->codec; | 1767 | struct snd_soc_codec *codec = codec_dai->codec; |
1787 | struct twl4030_priv *twl4030 = codec->private_data; | 1768 | struct twl4030_priv *twl4030 = codec->private_data; |
1788 | u8 infreq; | ||
1789 | 1769 | ||
1790 | switch (freq) { | 1770 | switch (freq) { |
1791 | case 19200000: | 1771 | case 19200000: |
1792 | infreq = TWL4030_APLL_INFREQ_19200KHZ; | ||
1793 | twl4030->sysclk = 19200; | ||
1794 | break; | ||
1795 | case 26000000: | 1772 | case 26000000: |
1796 | infreq = TWL4030_APLL_INFREQ_26000KHZ; | ||
1797 | twl4030->sysclk = 26000; | ||
1798 | break; | ||
1799 | case 38400000: | 1773 | case 38400000: |
1800 | infreq = TWL4030_APLL_INFREQ_38400KHZ; | ||
1801 | twl4030->sysclk = 38400; | ||
1802 | break; | 1774 | break; |
1803 | default: | 1775 | default: |
1804 | printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", | 1776 | dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq); |
1805 | freq); | ||
1806 | return -EINVAL; | 1777 | return -EINVAL; |
1807 | } | 1778 | } |
1808 | 1779 | ||
1809 | infreq |= TWL4030_APLL_EN; | 1780 | if ((freq / 1000) != twl4030->sysclk) { |
1810 | twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq); | 1781 | dev_err(codec->dev, |
1782 | "Mismatch in APLL mclk: %u (configured: %u)\n", | ||
1783 | freq, twl4030->sysclk * 1000); | ||
1784 | return -EINVAL; | ||
1785 | } | ||
1811 | 1786 | ||
1812 | return 0; | 1787 | return 0; |
1813 | } | 1788 | } |
@@ -1905,18 +1880,16 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, | |||
1905 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1880 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1906 | struct snd_soc_device *socdev = rtd->socdev; | 1881 | struct snd_soc_device *socdev = rtd->socdev; |
1907 | struct snd_soc_codec *codec = socdev->card->codec; | 1882 | struct snd_soc_codec *codec = socdev->card->codec; |
1908 | u8 infreq; | 1883 | struct twl4030_priv *twl4030 = codec->private_data; |
1909 | u8 mode; | 1884 | u8 mode; |
1910 | 1885 | ||
1911 | /* If the system master clock is not 26MHz, the voice PCM interface is | 1886 | /* If the system master clock is not 26MHz, the voice PCM interface is |
1912 | * not avilable. | 1887 | * not avilable. |
1913 | */ | 1888 | */ |
1914 | infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL) | 1889 | if (twl4030->sysclk != 26000) { |
1915 | & TWL4030_APLL_INFREQ; | 1890 | dev_err(codec->dev, "The board is configured for %u Hz, while" |
1916 | 1891 | "the Voice interface needs 26MHz APLL mclk\n", | |
1917 | if (infreq != TWL4030_APLL_INFREQ_26000KHZ) { | 1892 | twl4030->sysclk * 1000); |
1918 | printk(KERN_ERR "TWL4030 voice startup: " | ||
1919 | "MCLK is not 26MHz, call set_sysclk() on init\n"); | ||
1920 | return -EINVAL; | 1893 | return -EINVAL; |
1921 | } | 1894 | } |
1922 | 1895 | ||
@@ -1989,21 +1962,19 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1989 | int clk_id, unsigned int freq, int dir) | 1962 | int clk_id, unsigned int freq, int dir) |
1990 | { | 1963 | { |
1991 | struct snd_soc_codec *codec = codec_dai->codec; | 1964 | struct snd_soc_codec *codec = codec_dai->codec; |
1992 | u8 infreq; | 1965 | struct twl4030_priv *twl4030 = codec->private_data; |
1993 | 1966 | ||
1994 | switch (freq) { | 1967 | if (freq != 26000000) { |
1995 | case 26000000: | 1968 | dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice" |
1996 | infreq = TWL4030_APLL_INFREQ_26000KHZ; | 1969 | "interface needs 26MHz APLL mclk\n", freq); |
1997 | break; | 1970 | return -EINVAL; |
1998 | default: | 1971 | } |
1999 | printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n", | 1972 | if ((freq / 1000) != twl4030->sysclk) { |
2000 | freq); | 1973 | dev_err(codec->dev, |
1974 | "Mismatch in APLL mclk: %u (configured: %u)\n", | ||
1975 | freq, twl4030->sysclk * 1000); | ||
2001 | return -EINVAL; | 1976 | return -EINVAL; |
2002 | } | 1977 | } |
2003 | |||
2004 | infreq |= TWL4030_APLL_EN; | ||
2005 | twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq); | ||
2006 | |||
2007 | return 0; | 1978 | return 0; |
2008 | } | 1979 | } |
2009 | 1980 | ||
@@ -2121,7 +2092,7 @@ struct snd_soc_dai twl4030_dai[] = { | |||
2121 | }; | 2092 | }; |
2122 | EXPORT_SYMBOL_GPL(twl4030_dai); | 2093 | EXPORT_SYMBOL_GPL(twl4030_dai); |
2123 | 2094 | ||
2124 | static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) | 2095 | static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) |
2125 | { | 2096 | { |
2126 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2097 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
2127 | struct snd_soc_codec *codec = socdev->card->codec; | 2098 | struct snd_soc_codec *codec = socdev->card->codec; |
@@ -2131,7 +2102,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) | |||
2131 | return 0; | 2102 | return 0; |
2132 | } | 2103 | } |
2133 | 2104 | ||
2134 | static int twl4030_resume(struct platform_device *pdev) | 2105 | static int twl4030_soc_resume(struct platform_device *pdev) |
2135 | { | 2106 | { |
2136 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2107 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
2137 | struct snd_soc_codec *codec = socdev->card->codec; | 2108 | struct snd_soc_codec *codec = socdev->card->codec; |
@@ -2141,147 +2112,182 @@ static int twl4030_resume(struct platform_device *pdev) | |||
2141 | return 0; | 2112 | return 0; |
2142 | } | 2113 | } |
2143 | 2114 | ||
2144 | /* | 2115 | static struct snd_soc_codec *twl4030_codec; |
2145 | * initialize the driver | ||
2146 | * register the mixer and dsp interfaces with the kernel | ||
2147 | */ | ||
2148 | 2116 | ||
2149 | static int twl4030_init(struct snd_soc_device *socdev) | 2117 | static int twl4030_soc_probe(struct platform_device *pdev) |
2150 | { | 2118 | { |
2151 | struct snd_soc_codec *codec = socdev->card->codec; | 2119 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
2152 | struct twl4030_setup_data *setup = socdev->codec_data; | 2120 | struct twl4030_setup_data *setup = socdev->codec_data; |
2153 | struct twl4030_priv *twl4030 = codec->private_data; | 2121 | struct snd_soc_codec *codec; |
2154 | int ret = 0; | 2122 | struct twl4030_priv *twl4030; |
2123 | int ret; | ||
2155 | 2124 | ||
2156 | printk(KERN_INFO "TWL4030 Audio Codec init \n"); | 2125 | BUG_ON(!twl4030_codec); |
2157 | 2126 | ||
2158 | codec->name = "twl4030"; | 2127 | codec = twl4030_codec; |
2159 | codec->owner = THIS_MODULE; | 2128 | twl4030 = codec->private_data; |
2160 | codec->read = twl4030_read_reg_cache; | 2129 | socdev->card->codec = codec; |
2161 | codec->write = twl4030_write; | ||
2162 | codec->set_bias_level = twl4030_set_bias_level; | ||
2163 | codec->dai = twl4030_dai; | ||
2164 | codec->num_dai = ARRAY_SIZE(twl4030_dai), | ||
2165 | codec->reg_cache_size = sizeof(twl4030_reg); | ||
2166 | codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), | ||
2167 | GFP_KERNEL); | ||
2168 | if (codec->reg_cache == NULL) | ||
2169 | return -ENOMEM; | ||
2170 | 2130 | ||
2171 | /* Configuration for headset ramp delay from setup data */ | 2131 | /* Configuration for headset ramp delay from setup data */ |
2172 | if (setup) { | 2132 | if (setup) { |
2173 | unsigned char hs_pop; | 2133 | unsigned char hs_pop; |
2174 | 2134 | ||
2175 | if (setup->sysclk) | 2135 | if (setup->sysclk != twl4030->sysclk) |
2176 | twl4030->sysclk = setup->sysclk; | 2136 | dev_warn(&pdev->dev, |
2177 | else | 2137 | "Mismatch in APLL mclk: %u (configured: %u)\n", |
2178 | twl4030->sysclk = 26000; | 2138 | setup->sysclk, twl4030->sysclk); |
2179 | 2139 | ||
2180 | hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 2140 | hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
2181 | hs_pop &= ~TWL4030_RAMP_DELAY; | 2141 | hs_pop &= ~TWL4030_RAMP_DELAY; |
2182 | hs_pop |= (setup->ramp_delay_value << 2); | 2142 | hs_pop |= (setup->ramp_delay_value << 2); |
2183 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 2143 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
2184 | } else { | ||
2185 | twl4030->sysclk = 26000; | ||
2186 | } | 2144 | } |
2187 | 2145 | ||
2188 | /* register pcms */ | 2146 | /* register pcms */ |
2189 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 2147 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
2190 | if (ret < 0) { | 2148 | if (ret < 0) { |
2191 | printk(KERN_ERR "twl4030: failed to create pcms\n"); | 2149 | dev_err(&pdev->dev, "failed to create pcms\n"); |
2192 | goto pcm_err; | 2150 | return ret; |
2193 | } | 2151 | } |
2194 | 2152 | ||
2195 | twl4030_init_chip(codec); | ||
2196 | |||
2197 | /* power on device */ | ||
2198 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2199 | |||
2200 | snd_soc_add_controls(codec, twl4030_snd_controls, | 2153 | snd_soc_add_controls(codec, twl4030_snd_controls, |
2201 | ARRAY_SIZE(twl4030_snd_controls)); | 2154 | ARRAY_SIZE(twl4030_snd_controls)); |
2202 | twl4030_add_widgets(codec); | 2155 | twl4030_add_widgets(codec); |
2203 | 2156 | ||
2204 | ret = snd_soc_init_card(socdev); | 2157 | return 0; |
2205 | if (ret < 0) { | 2158 | } |
2206 | printk(KERN_ERR "twl4030: failed to register card\n"); | ||
2207 | goto card_err; | ||
2208 | } | ||
2209 | 2159 | ||
2210 | return ret; | 2160 | static int twl4030_soc_remove(struct platform_device *pdev) |
2161 | { | ||
2162 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2163 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2211 | 2164 | ||
2212 | card_err: | 2165 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2213 | snd_soc_free_pcms(socdev); | 2166 | snd_soc_free_pcms(socdev); |
2214 | snd_soc_dapm_free(socdev); | 2167 | snd_soc_dapm_free(socdev); |
2215 | pcm_err: | ||
2216 | kfree(codec->reg_cache); | ||
2217 | return ret; | ||
2218 | } | ||
2219 | 2168 | ||
2220 | static struct snd_soc_device *twl4030_socdev; | 2169 | return 0; |
2170 | } | ||
2221 | 2171 | ||
2222 | static int twl4030_probe(struct platform_device *pdev) | 2172 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2223 | { | 2173 | { |
2224 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2174 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; |
2225 | struct snd_soc_codec *codec; | 2175 | struct snd_soc_codec *codec; |
2226 | struct twl4030_priv *twl4030; | 2176 | struct twl4030_priv *twl4030; |
2177 | int ret; | ||
2227 | 2178 | ||
2228 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 2179 | if (!pdata) { |
2229 | if (codec == NULL) | 2180 | dev_err(&pdev->dev, "platform_data is missing\n"); |
2230 | return -ENOMEM; | 2181 | return -EINVAL; |
2182 | } | ||
2231 | 2183 | ||
2232 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); | 2184 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); |
2233 | if (twl4030 == NULL) { | 2185 | if (twl4030 == NULL) { |
2234 | kfree(codec); | 2186 | dev_err(&pdev->dev, "Can not allocate memroy\n"); |
2235 | return -ENOMEM; | 2187 | return -ENOMEM; |
2236 | } | 2188 | } |
2237 | 2189 | ||
2190 | codec = &twl4030->codec; | ||
2238 | codec->private_data = twl4030; | 2191 | codec->private_data = twl4030; |
2239 | socdev->card->codec = codec; | 2192 | codec->dev = &pdev->dev; |
2193 | twl4030_dai[0].dev = &pdev->dev; | ||
2194 | twl4030_dai[1].dev = &pdev->dev; | ||
2195 | |||
2240 | mutex_init(&codec->mutex); | 2196 | mutex_init(&codec->mutex); |
2241 | INIT_LIST_HEAD(&codec->dapm_widgets); | 2197 | INIT_LIST_HEAD(&codec->dapm_widgets); |
2242 | INIT_LIST_HEAD(&codec->dapm_paths); | 2198 | INIT_LIST_HEAD(&codec->dapm_paths); |
2243 | 2199 | ||
2244 | twl4030_socdev = socdev; | 2200 | codec->name = "twl4030"; |
2245 | twl4030_init(socdev); | 2201 | codec->owner = THIS_MODULE; |
2202 | codec->read = twl4030_read_reg_cache; | ||
2203 | codec->write = twl4030_write; | ||
2204 | codec->set_bias_level = twl4030_set_bias_level; | ||
2205 | codec->dai = twl4030_dai; | ||
2206 | codec->num_dai = ARRAY_SIZE(twl4030_dai); | ||
2207 | codec->reg_cache_size = sizeof(twl4030_reg); | ||
2208 | codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), | ||
2209 | GFP_KERNEL); | ||
2210 | if (codec->reg_cache == NULL) { | ||
2211 | ret = -ENOMEM; | ||
2212 | goto error_cache; | ||
2213 | } | ||
2214 | |||
2215 | platform_set_drvdata(pdev, twl4030); | ||
2216 | twl4030_codec = codec; | ||
2217 | |||
2218 | /* Set the defaults, and power up the codec */ | ||
2219 | twl4030->sysclk = twl4030_codec_get_mclk() / 1000; | ||
2220 | twl4030_init_chip(codec); | ||
2221 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2222 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2223 | |||
2224 | ret = snd_soc_register_codec(codec); | ||
2225 | if (ret != 0) { | ||
2226 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2227 | goto error_codec; | ||
2228 | } | ||
2229 | |||
2230 | ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | ||
2231 | if (ret != 0) { | ||
2232 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
2233 | snd_soc_unregister_codec(codec); | ||
2234 | goto error_codec; | ||
2235 | } | ||
2246 | 2236 | ||
2247 | return 0; | 2237 | return 0; |
2238 | |||
2239 | error_codec: | ||
2240 | twl4030_power_down(codec); | ||
2241 | kfree(codec->reg_cache); | ||
2242 | error_cache: | ||
2243 | kfree(twl4030); | ||
2244 | return ret; | ||
2248 | } | 2245 | } |
2249 | 2246 | ||
2250 | static int twl4030_remove(struct platform_device *pdev) | 2247 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) |
2251 | { | 2248 | { |
2252 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2249 | struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); |
2253 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2254 | 2250 | ||
2255 | printk(KERN_INFO "TWL4030 Audio Codec remove\n"); | 2251 | snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); |
2256 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2252 | snd_soc_unregister_codec(&twl4030->codec); |
2257 | snd_soc_free_pcms(socdev); | 2253 | kfree(twl4030->codec.reg_cache); |
2258 | snd_soc_dapm_free(socdev); | 2254 | kfree(twl4030); |
2259 | kfree(codec->private_data); | ||
2260 | kfree(codec); | ||
2261 | 2255 | ||
2256 | twl4030_codec = NULL; | ||
2262 | return 0; | 2257 | return 0; |
2263 | } | 2258 | } |
2264 | 2259 | ||
2265 | struct snd_soc_codec_device soc_codec_dev_twl4030 = { | 2260 | MODULE_ALIAS("platform:twl4030_codec_audio"); |
2266 | .probe = twl4030_probe, | 2261 | |
2267 | .remove = twl4030_remove, | 2262 | static struct platform_driver twl4030_codec_driver = { |
2268 | .suspend = twl4030_suspend, | 2263 | .probe = twl4030_codec_probe, |
2269 | .resume = twl4030_resume, | 2264 | .remove = __devexit_p(twl4030_codec_remove), |
2265 | .driver = { | ||
2266 | .name = "twl4030_codec_audio", | ||
2267 | .owner = THIS_MODULE, | ||
2268 | }, | ||
2270 | }; | 2269 | }; |
2271 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); | ||
2272 | 2270 | ||
2273 | static int __init twl4030_modinit(void) | 2271 | static int __init twl4030_modinit(void) |
2274 | { | 2272 | { |
2275 | return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | 2273 | return platform_driver_register(&twl4030_codec_driver); |
2276 | } | 2274 | } |
2277 | module_init(twl4030_modinit); | 2275 | module_init(twl4030_modinit); |
2278 | 2276 | ||
2279 | static void __exit twl4030_exit(void) | 2277 | static void __exit twl4030_exit(void) |
2280 | { | 2278 | { |
2281 | snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | 2279 | platform_driver_unregister(&twl4030_codec_driver); |
2282 | } | 2280 | } |
2283 | module_exit(twl4030_exit); | 2281 | module_exit(twl4030_exit); |
2284 | 2282 | ||
2283 | struct snd_soc_codec_device soc_codec_dev_twl4030 = { | ||
2284 | .probe = twl4030_soc_probe, | ||
2285 | .remove = twl4030_soc_remove, | ||
2286 | .suspend = twl4030_soc_suspend, | ||
2287 | .resume = twl4030_soc_resume, | ||
2288 | }; | ||
2289 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); | ||
2290 | |||
2285 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); | 2291 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); |
2286 | MODULE_AUTHOR("Steve Sakoman"); | 2292 | MODULE_AUTHOR("Steve Sakoman"); |
2287 | MODULE_LICENSE("GPL"); | 2293 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h index 2b4bfa23f985..f206d242ca31 100644 --- a/sound/soc/codecs/twl4030.h +++ b/sound/soc/codecs/twl4030.h | |||
@@ -22,245 +22,13 @@ | |||
22 | #ifndef __TWL4030_AUDIO_H__ | 22 | #ifndef __TWL4030_AUDIO_H__ |
23 | #define __TWL4030_AUDIO_H__ | 23 | #define __TWL4030_AUDIO_H__ |
24 | 24 | ||
25 | #define TWL4030_REG_CODEC_MODE 0x1 | 25 | /* Register descriptions are here */ |
26 | #define TWL4030_REG_OPTION 0x2 | 26 | #include <linux/mfd/twl4030-codec.h> |
27 | #define TWL4030_REG_UNKNOWN 0x3 | ||
28 | #define TWL4030_REG_MICBIAS_CTL 0x4 | ||
29 | #define TWL4030_REG_ANAMICL 0x5 | ||
30 | #define TWL4030_REG_ANAMICR 0x6 | ||
31 | #define TWL4030_REG_AVADC_CTL 0x7 | ||
32 | #define TWL4030_REG_ADCMICSEL 0x8 | ||
33 | #define TWL4030_REG_DIGMIXING 0x9 | ||
34 | #define TWL4030_REG_ATXL1PGA 0xA | ||
35 | #define TWL4030_REG_ATXR1PGA 0xB | ||
36 | #define TWL4030_REG_AVTXL2PGA 0xC | ||
37 | #define TWL4030_REG_AVTXR2PGA 0xD | ||
38 | #define TWL4030_REG_AUDIO_IF 0xE | ||
39 | #define TWL4030_REG_VOICE_IF 0xF | ||
40 | #define TWL4030_REG_ARXR1PGA 0x10 | ||
41 | #define TWL4030_REG_ARXL1PGA 0x11 | ||
42 | #define TWL4030_REG_ARXR2PGA 0x12 | ||
43 | #define TWL4030_REG_ARXL2PGA 0x13 | ||
44 | #define TWL4030_REG_VRXPGA 0x14 | ||
45 | #define TWL4030_REG_VSTPGA 0x15 | ||
46 | #define TWL4030_REG_VRX2ARXPGA 0x16 | ||
47 | #define TWL4030_REG_AVDAC_CTL 0x17 | ||
48 | #define TWL4030_REG_ARX2VTXPGA 0x18 | ||
49 | #define TWL4030_REG_ARXL1_APGA_CTL 0x19 | ||
50 | #define TWL4030_REG_ARXR1_APGA_CTL 0x1A | ||
51 | #define TWL4030_REG_ARXL2_APGA_CTL 0x1B | ||
52 | #define TWL4030_REG_ARXR2_APGA_CTL 0x1C | ||
53 | #define TWL4030_REG_ATX2ARXPGA 0x1D | ||
54 | #define TWL4030_REG_BT_IF 0x1E | ||
55 | #define TWL4030_REG_BTPGA 0x1F | ||
56 | #define TWL4030_REG_BTSTPGA 0x20 | ||
57 | #define TWL4030_REG_EAR_CTL 0x21 | ||
58 | #define TWL4030_REG_HS_SEL 0x22 | ||
59 | #define TWL4030_REG_HS_GAIN_SET 0x23 | ||
60 | #define TWL4030_REG_HS_POPN_SET 0x24 | ||
61 | #define TWL4030_REG_PREDL_CTL 0x25 | ||
62 | #define TWL4030_REG_PREDR_CTL 0x26 | ||
63 | #define TWL4030_REG_PRECKL_CTL 0x27 | ||
64 | #define TWL4030_REG_PRECKR_CTL 0x28 | ||
65 | #define TWL4030_REG_HFL_CTL 0x29 | ||
66 | #define TWL4030_REG_HFR_CTL 0x2A | ||
67 | #define TWL4030_REG_ALC_CTL 0x2B | ||
68 | #define TWL4030_REG_ALC_SET1 0x2C | ||
69 | #define TWL4030_REG_ALC_SET2 0x2D | ||
70 | #define TWL4030_REG_BOOST_CTL 0x2E | ||
71 | #define TWL4030_REG_SOFTVOL_CTL 0x2F | ||
72 | #define TWL4030_REG_DTMF_FREQSEL 0x30 | ||
73 | #define TWL4030_REG_DTMF_TONEXT1H 0x31 | ||
74 | #define TWL4030_REG_DTMF_TONEXT1L 0x32 | ||
75 | #define TWL4030_REG_DTMF_TONEXT2H 0x33 | ||
76 | #define TWL4030_REG_DTMF_TONEXT2L 0x34 | ||
77 | #define TWL4030_REG_DTMF_TONOFF 0x35 | ||
78 | #define TWL4030_REG_DTMF_WANONOFF 0x36 | ||
79 | #define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37 | ||
80 | #define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38 | ||
81 | #define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39 | ||
82 | #define TWL4030_REG_APLL_CTL 0x3A | ||
83 | #define TWL4030_REG_DTMF_CTL 0x3B | ||
84 | #define TWL4030_REG_DTMF_PGA_CTL2 0x3C | ||
85 | #define TWL4030_REG_DTMF_PGA_CTL1 0x3D | ||
86 | #define TWL4030_REG_MISC_SET_1 0x3E | ||
87 | #define TWL4030_REG_PCMBTMUX 0x3F | ||
88 | #define TWL4030_REG_RX_PATH_SEL 0x43 | ||
89 | #define TWL4030_REG_VDL_APGA_CTL 0x44 | ||
90 | #define TWL4030_REG_VIBRA_CTL 0x45 | ||
91 | #define TWL4030_REG_VIBRA_SET 0x46 | ||
92 | #define TWL4030_REG_VIBRA_PWM_SET 0x47 | ||
93 | #define TWL4030_REG_ANAMIC_GAIN 0x48 | ||
94 | #define TWL4030_REG_MISC_SET_2 0x49 | ||
95 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
96 | 27 | ||
28 | /* Shadow register used by the audio driver */ | ||
29 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
97 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) | 30 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) |
98 | 31 | ||
99 | /* Bitfield Definitions */ | ||
100 | |||
101 | /* TWL4030_CODEC_MODE (0x01) Fields */ | ||
102 | |||
103 | #define TWL4030_APLL_RATE 0xF0 | ||
104 | #define TWL4030_APLL_RATE_8000 0x00 | ||
105 | #define TWL4030_APLL_RATE_11025 0x10 | ||
106 | #define TWL4030_APLL_RATE_12000 0x20 | ||
107 | #define TWL4030_APLL_RATE_16000 0x40 | ||
108 | #define TWL4030_APLL_RATE_22050 0x50 | ||
109 | #define TWL4030_APLL_RATE_24000 0x60 | ||
110 | #define TWL4030_APLL_RATE_32000 0x80 | ||
111 | #define TWL4030_APLL_RATE_44100 0x90 | ||
112 | #define TWL4030_APLL_RATE_48000 0xA0 | ||
113 | #define TWL4030_APLL_RATE_96000 0xE0 | ||
114 | #define TWL4030_SEL_16K 0x08 | ||
115 | #define TWL4030_CODECPDZ 0x02 | ||
116 | #define TWL4030_OPT_MODE 0x01 | ||
117 | #define TWL4030_OPTION_1 (1 << 0) | ||
118 | #define TWL4030_OPTION_2 (0 << 0) | ||
119 | |||
120 | /* TWL4030_OPTION (0x02) Fields */ | ||
121 | |||
122 | #define TWL4030_ATXL1_EN (1 << 0) | ||
123 | #define TWL4030_ATXR1_EN (1 << 1) | ||
124 | #define TWL4030_ATXL2_VTXL_EN (1 << 2) | ||
125 | #define TWL4030_ATXR2_VTXR_EN (1 << 3) | ||
126 | #define TWL4030_ARXL1_VRX_EN (1 << 4) | ||
127 | #define TWL4030_ARXR1_EN (1 << 5) | ||
128 | #define TWL4030_ARXL2_EN (1 << 6) | ||
129 | #define TWL4030_ARXR2_EN (1 << 7) | ||
130 | |||
131 | /* TWL4030_REG_MICBIAS_CTL (0x04) Fields */ | ||
132 | |||
133 | #define TWL4030_MICBIAS2_CTL 0x40 | ||
134 | #define TWL4030_MICBIAS1_CTL 0x20 | ||
135 | #define TWL4030_HSMICBIAS_EN 0x04 | ||
136 | #define TWL4030_MICBIAS2_EN 0x02 | ||
137 | #define TWL4030_MICBIAS1_EN 0x01 | ||
138 | |||
139 | /* ANAMICL (0x05) Fields */ | ||
140 | |||
141 | #define TWL4030_CNCL_OFFSET_START 0x80 | ||
142 | #define TWL4030_OFFSET_CNCL_SEL 0x60 | ||
143 | #define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00 | ||
144 | #define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20 | ||
145 | #define TWL4030_OFFSET_CNCL_SEL_VRX 0x40 | ||
146 | #define TWL4030_OFFSET_CNCL_SEL_ALL 0x60 | ||
147 | #define TWL4030_MICAMPL_EN 0x10 | ||
148 | #define TWL4030_CKMIC_EN 0x08 | ||
149 | #define TWL4030_AUXL_EN 0x04 | ||
150 | #define TWL4030_HSMIC_EN 0x02 | ||
151 | #define TWL4030_MAINMIC_EN 0x01 | ||
152 | |||
153 | /* ANAMICR (0x06) Fields */ | ||
154 | |||
155 | #define TWL4030_MICAMPR_EN 0x10 | ||
156 | #define TWL4030_AUXR_EN 0x04 | ||
157 | #define TWL4030_SUBMIC_EN 0x01 | ||
158 | |||
159 | /* AVADC_CTL (0x07) Fields */ | ||
160 | |||
161 | #define TWL4030_ADCL_EN 0x08 | ||
162 | #define TWL4030_AVADC_CLK_PRIORITY 0x04 | ||
163 | #define TWL4030_ADCR_EN 0x02 | ||
164 | |||
165 | /* TWL4030_REG_ADCMICSEL (0x08) Fields */ | ||
166 | |||
167 | #define TWL4030_DIGMIC1_EN 0x08 | ||
168 | #define TWL4030_TX2IN_SEL 0x04 | ||
169 | #define TWL4030_DIGMIC0_EN 0x02 | ||
170 | #define TWL4030_TX1IN_SEL 0x01 | ||
171 | |||
172 | /* AUDIO_IF (0x0E) Fields */ | ||
173 | |||
174 | #define TWL4030_AIF_SLAVE_EN 0x80 | ||
175 | #define TWL4030_DATA_WIDTH 0x60 | ||
176 | #define TWL4030_DATA_WIDTH_16S_16W 0x00 | ||
177 | #define TWL4030_DATA_WIDTH_32S_16W 0x40 | ||
178 | #define TWL4030_DATA_WIDTH_32S_24W 0x60 | ||
179 | #define TWL4030_AIF_FORMAT 0x18 | ||
180 | #define TWL4030_AIF_FORMAT_CODEC 0x00 | ||
181 | #define TWL4030_AIF_FORMAT_LEFT 0x08 | ||
182 | #define TWL4030_AIF_FORMAT_RIGHT 0x10 | ||
183 | #define TWL4030_AIF_FORMAT_TDM 0x18 | ||
184 | #define TWL4030_AIF_TRI_EN 0x04 | ||
185 | #define TWL4030_CLK256FS_EN 0x02 | ||
186 | #define TWL4030_AIF_EN 0x01 | ||
187 | |||
188 | /* VOICE_IF (0x0F) Fields */ | ||
189 | |||
190 | #define TWL4030_VIF_SLAVE_EN 0x80 | ||
191 | #define TWL4030_VIF_DIN_EN 0x40 | ||
192 | #define TWL4030_VIF_DOUT_EN 0x20 | ||
193 | #define TWL4030_VIF_SWAP 0x10 | ||
194 | #define TWL4030_VIF_FORMAT 0x08 | ||
195 | #define TWL4030_VIF_TRI_EN 0x04 | ||
196 | #define TWL4030_VIF_SUB_EN 0x02 | ||
197 | #define TWL4030_VIF_EN 0x01 | ||
198 | |||
199 | /* EAR_CTL (0x21) */ | ||
200 | #define TWL4030_EAR_GAIN 0x30 | ||
201 | |||
202 | /* HS_GAIN_SET (0x23) Fields */ | ||
203 | |||
204 | #define TWL4030_HSR_GAIN 0x0C | ||
205 | #define TWL4030_HSR_GAIN_PWR_DOWN 0x00 | ||
206 | #define TWL4030_HSR_GAIN_PLUS_6DB 0x04 | ||
207 | #define TWL4030_HSR_GAIN_0DB 0x08 | ||
208 | #define TWL4030_HSR_GAIN_MINUS_6DB 0x0C | ||
209 | #define TWL4030_HSL_GAIN 0x03 | ||
210 | #define TWL4030_HSL_GAIN_PWR_DOWN 0x00 | ||
211 | #define TWL4030_HSL_GAIN_PLUS_6DB 0x01 | ||
212 | #define TWL4030_HSL_GAIN_0DB 0x02 | ||
213 | #define TWL4030_HSL_GAIN_MINUS_6DB 0x03 | ||
214 | |||
215 | /* HS_POPN_SET (0x24) Fields */ | ||
216 | |||
217 | #define TWL4030_VMID_EN 0x40 | ||
218 | #define TWL4030_EXTMUTE 0x20 | ||
219 | #define TWL4030_RAMP_DELAY 0x1C | ||
220 | #define TWL4030_RAMP_DELAY_20MS 0x00 | ||
221 | #define TWL4030_RAMP_DELAY_40MS 0x04 | ||
222 | #define TWL4030_RAMP_DELAY_81MS 0x08 | ||
223 | #define TWL4030_RAMP_DELAY_161MS 0x0C | ||
224 | #define TWL4030_RAMP_DELAY_323MS 0x10 | ||
225 | #define TWL4030_RAMP_DELAY_645MS 0x14 | ||
226 | #define TWL4030_RAMP_DELAY_1291MS 0x18 | ||
227 | #define TWL4030_RAMP_DELAY_2581MS 0x1C | ||
228 | #define TWL4030_RAMP_EN 0x02 | ||
229 | |||
230 | /* PREDL_CTL (0x25) */ | ||
231 | #define TWL4030_PREDL_GAIN 0x30 | ||
232 | |||
233 | /* PREDR_CTL (0x26) */ | ||
234 | #define TWL4030_PREDR_GAIN 0x30 | ||
235 | |||
236 | /* PRECKL_CTL (0x27) */ | ||
237 | #define TWL4030_PRECKL_GAIN 0x30 | ||
238 | |||
239 | /* PRECKR_CTL (0x28) */ | ||
240 | #define TWL4030_PRECKR_GAIN 0x30 | ||
241 | |||
242 | /* HFL_CTL (0x29, 0x2A) Fields */ | ||
243 | #define TWL4030_HF_CTL_HB_EN 0x04 | ||
244 | #define TWL4030_HF_CTL_LOOP_EN 0x08 | ||
245 | #define TWL4030_HF_CTL_RAMP_EN 0x10 | ||
246 | #define TWL4030_HF_CTL_REF_EN 0x20 | ||
247 | |||
248 | /* APLL_CTL (0x3A) Fields */ | ||
249 | |||
250 | #define TWL4030_APLL_EN 0x10 | ||
251 | #define TWL4030_APLL_INFREQ 0x0F | ||
252 | #define TWL4030_APLL_INFREQ_19200KHZ 0x05 | ||
253 | #define TWL4030_APLL_INFREQ_26000KHZ 0x06 | ||
254 | #define TWL4030_APLL_INFREQ_38400KHZ 0x0F | ||
255 | |||
256 | /* REG_MISC_SET_1 (0x3E) Fields */ | ||
257 | |||
258 | #define TWL4030_CLK64_EN 0x80 | ||
259 | #define TWL4030_SCRAMBLE_EN 0x40 | ||
260 | #define TWL4030_FMLOOP_EN 0x20 | ||
261 | #define TWL4030_SMOOTH_ANAVOL_EN 0x02 | ||
262 | #define TWL4030_DIGMIC_LR_SWAP_EN 0x01 | ||
263 | |||
264 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ | 32 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ |
265 | #define TWL4030_HFL_EN 0x01 | 33 | #define TWL4030_HFL_EN 0x01 |
266 | #define TWL4030_HFR_EN 0x02 | 34 | #define TWL4030_HFR_EN 0x02 |
@@ -279,3 +47,5 @@ struct twl4030_setup_data { | |||
279 | }; | 47 | }; |
280 | 48 | ||
281 | #endif /* End of __TWL4030_AUDIO_H__ */ | 49 | #endif /* End of __TWL4030_AUDIO_H__ */ |
50 | |||
51 | |||
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index c33b92edbded..a8dcd5a5bbcb 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/slab.h> | ||
18 | #include <sound/pcm.h> | 19 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> | 20 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
@@ -101,7 +102,7 @@ static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, | |||
101 | pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); | 102 | pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); |
102 | 103 | ||
103 | if (reg >= UDA134X_REGS_NUM) { | 104 | if (reg >= UDA134X_REGS_NUM) { |
104 | printk(KERN_ERR "%s unkown register: reg: %u", | 105 | printk(KERN_ERR "%s unknown register: reg: %u", |
105 | __func__, reg); | 106 | __func__, reg); |
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | } | 108 | } |
@@ -552,7 +553,7 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
552 | ARRAY_SIZE(uda1341_snd_controls)); | 553 | ARRAY_SIZE(uda1341_snd_controls)); |
553 | break; | 554 | break; |
554 | default: | 555 | default: |
555 | printk(KERN_ERR "%s unkown codec type: %d", | 556 | printk(KERN_ERR "%s unknown codec type: %d", |
556 | __func__, pd->model); | 557 | __func__, pd->model); |
557 | return -EINVAL; | 558 | return -EINVAL; |
558 | } | 559 | } |
@@ -562,17 +563,8 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
562 | goto pcm_err; | 563 | goto pcm_err; |
563 | } | 564 | } |
564 | 565 | ||
565 | ret = snd_soc_init_card(socdev); | ||
566 | if (ret < 0) { | ||
567 | printk(KERN_ERR "UDA134X: failed to register card\n"); | ||
568 | goto card_err; | ||
569 | } | ||
570 | |||
571 | return 0; | 566 | return 0; |
572 | 567 | ||
573 | card_err: | ||
574 | snd_soc_free_pcms(socdev); | ||
575 | snd_soc_dapm_free(socdev); | ||
576 | pcm_err: | 568 | pcm_err: |
577 | kfree(codec->reg_cache); | 569 | kfree(codec->reg_cache); |
578 | reg_err: | 570 | reg_err: |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 92ec03442154..9cd0a66b7663 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -137,7 +137,7 @@ static void uda1380_flush_work(struct work_struct *work) | |||
137 | { | 137 | { |
138 | int bit, reg; | 138 | int bit, reg; |
139 | 139 | ||
140 | for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { | 140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { |
141 | reg = 0x10 + bit; | 141 | reg = 0x10 + bit; |
142 | pr_debug("uda1380: flush reg %x val %x:\n", reg, | 142 | pr_debug("uda1380: flush reg %x val %x:\n", reg, |
143 | uda1380_read_reg_cache(uda1380_codec, reg)); | 143 | uda1380_read_reg_cache(uda1380_codec, reg)); |
@@ -378,7 +378,6 @@ static int uda1380_add_widgets(struct snd_soc_codec *codec) | |||
378 | 378 | ||
379 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 379 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
380 | 380 | ||
381 | snd_soc_dapm_new_widgets(codec); | ||
382 | return 0; | 381 | return 0; |
383 | } | 382 | } |
384 | 383 | ||
@@ -713,17 +712,9 @@ static int uda1380_probe(struct platform_device *pdev) | |||
713 | snd_soc_add_controls(codec, uda1380_snd_controls, | 712 | snd_soc_add_controls(codec, uda1380_snd_controls, |
714 | ARRAY_SIZE(uda1380_snd_controls)); | 713 | ARRAY_SIZE(uda1380_snd_controls)); |
715 | uda1380_add_widgets(codec); | 714 | uda1380_add_widgets(codec); |
716 | ret = snd_soc_init_card(socdev); | ||
717 | if (ret < 0) { | ||
718 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
719 | goto card_err; | ||
720 | } | ||
721 | 715 | ||
722 | return ret; | 716 | return ret; |
723 | 717 | ||
724 | card_err: | ||
725 | snd_soc_free_pcms(socdev); | ||
726 | snd_soc_dapm_free(socdev); | ||
727 | pcm_err: | 718 | pcm_err: |
728 | return ret; | 719 | return ret; |
729 | } | 720 | } |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c new file mode 100644 index 000000000000..002e289d1255 --- /dev/null +++ b/sound/soc/codecs/wm2000.c | |||
@@ -0,0 +1,888 @@ | |||
1 | /* | ||
2 | * wm2000.c -- WM2000 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright 2008-2010 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@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 | * The download image for the WM2000 will be requested as | ||
13 | * 'wm2000_anc.bin' by default (overridable via platform data) at | ||
14 | * runtime and is expected to be in flat binary format. This is | ||
15 | * generated by Wolfson configuration tools and includes | ||
16 | * system-specific callibration information. If supplied as a | ||
17 | * sequence of ASCII-encoded hexidecimal bytes this can be converted | ||
18 | * into a flat binary with a command such as this on the command line: | ||
19 | * | ||
20 | * perl -e 'while (<>) { s/[\r\n]+// ; printf("%c", hex($_)); }' | ||
21 | * < file > wm2000_anc.bin | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/pcm_params.h> | ||
38 | #include <sound/soc.h> | ||
39 | #include <sound/soc-dapm.h> | ||
40 | #include <sound/initval.h> | ||
41 | #include <sound/tlv.h> | ||
42 | |||
43 | #include <sound/wm2000.h> | ||
44 | |||
45 | #include "wm2000.h" | ||
46 | |||
47 | enum wm2000_anc_mode { | ||
48 | ANC_ACTIVE = 0, | ||
49 | ANC_BYPASS = 1, | ||
50 | ANC_STANDBY = 2, | ||
51 | ANC_OFF = 3, | ||
52 | }; | ||
53 | |||
54 | struct wm2000_priv { | ||
55 | struct i2c_client *i2c; | ||
56 | |||
57 | enum wm2000_anc_mode anc_mode; | ||
58 | |||
59 | unsigned int anc_active:1; | ||
60 | unsigned int anc_eng_ena:1; | ||
61 | unsigned int spk_ena:1; | ||
62 | |||
63 | unsigned int mclk_div:1; | ||
64 | unsigned int speech_clarity:1; | ||
65 | |||
66 | int anc_download_size; | ||
67 | char *anc_download; | ||
68 | }; | ||
69 | |||
70 | static struct i2c_client *wm2000_i2c; | ||
71 | |||
72 | static int wm2000_write(struct i2c_client *i2c, unsigned int reg, | ||
73 | unsigned int value) | ||
74 | { | ||
75 | u8 data[3]; | ||
76 | int ret; | ||
77 | |||
78 | data[0] = (reg >> 8) & 0xff; | ||
79 | data[1] = reg & 0xff; | ||
80 | data[2] = value & 0xff; | ||
81 | |||
82 | dev_vdbg(&i2c->dev, "write %x = %x\n", reg, value); | ||
83 | |||
84 | ret = i2c_master_send(i2c, data, 3); | ||
85 | if (ret == 3) | ||
86 | return 0; | ||
87 | if (ret < 0) | ||
88 | return ret; | ||
89 | else | ||
90 | return -EIO; | ||
91 | } | ||
92 | |||
93 | static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r) | ||
94 | { | ||
95 | struct i2c_msg xfer[2]; | ||
96 | u8 reg[2]; | ||
97 | u8 data; | ||
98 | int ret; | ||
99 | |||
100 | /* Write register */ | ||
101 | reg[0] = (r >> 8) & 0xff; | ||
102 | reg[1] = r & 0xff; | ||
103 | xfer[0].addr = i2c->addr; | ||
104 | xfer[0].flags = 0; | ||
105 | xfer[0].len = sizeof(reg); | ||
106 | xfer[0].buf = ®[0]; | ||
107 | |||
108 | /* Read data */ | ||
109 | xfer[1].addr = i2c->addr; | ||
110 | xfer[1].flags = I2C_M_RD; | ||
111 | xfer[1].len = 1; | ||
112 | xfer[1].buf = &data; | ||
113 | |||
114 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
115 | if (ret != 2) { | ||
116 | dev_err(&i2c->dev, "i2c_transfer() returned %d\n", ret); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | dev_vdbg(&i2c->dev, "read %x from %x\n", data, r); | ||
121 | |||
122 | return data; | ||
123 | } | ||
124 | |||
125 | static void wm2000_reset(struct wm2000_priv *wm2000) | ||
126 | { | ||
127 | struct i2c_client *i2c = wm2000->i2c; | ||
128 | |||
129 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR); | ||
130 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); | ||
131 | wm2000_write(i2c, WM2000_REG_ID1, 0); | ||
132 | |||
133 | wm2000->anc_mode = ANC_OFF; | ||
134 | } | ||
135 | |||
136 | static int wm2000_poll_bit(struct i2c_client *i2c, | ||
137 | unsigned int reg, u8 mask, int timeout) | ||
138 | { | ||
139 | int val; | ||
140 | |||
141 | val = wm2000_read(i2c, reg); | ||
142 | |||
143 | while (!(val & mask) && --timeout) { | ||
144 | msleep(1); | ||
145 | val = wm2000_read(i2c, reg); | ||
146 | } | ||
147 | |||
148 | if (timeout == 0) | ||
149 | return 0; | ||
150 | else | ||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | static int wm2000_power_up(struct i2c_client *i2c, int analogue) | ||
155 | { | ||
156 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
157 | int ret, timeout; | ||
158 | |||
159 | BUG_ON(wm2000->anc_mode != ANC_OFF); | ||
160 | |||
161 | dev_dbg(&i2c->dev, "Beginning power up\n"); | ||
162 | |||
163 | if (!wm2000->mclk_div) { | ||
164 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); | ||
165 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | ||
166 | WM2000_MCLK_DIV2_ENA_CLR); | ||
167 | } else { | ||
168 | dev_dbg(&i2c->dev, "Enabling MCLK divider\n"); | ||
169 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | ||
170 | WM2000_MCLK_DIV2_ENA_SET); | ||
171 | } | ||
172 | |||
173 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR); | ||
174 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET); | ||
175 | |||
176 | /* Wait for ANC engine to become ready */ | ||
177 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | ||
178 | WM2000_ANC_ENG_IDLE, 1)) { | ||
179 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); | ||
180 | return -ETIMEDOUT; | ||
181 | } | ||
182 | |||
183 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
184 | WM2000_STATUS_BOOT_COMPLETE, 1)) { | ||
185 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); | ||
186 | return -ETIMEDOUT; | ||
187 | } | ||
188 | |||
189 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); | ||
190 | |||
191 | /* Open code download of the data since it is the only bulk | ||
192 | * write we do. */ | ||
193 | dev_dbg(&i2c->dev, "Downloading %d bytes\n", | ||
194 | wm2000->anc_download_size - 2); | ||
195 | |||
196 | ret = i2c_master_send(i2c, wm2000->anc_download, | ||
197 | wm2000->anc_download_size); | ||
198 | if (ret < 0) { | ||
199 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); | ||
200 | return ret; | ||
201 | } | ||
202 | if (ret != wm2000->anc_download_size) { | ||
203 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", | ||
204 | ret, wm2000->anc_download_size); | ||
205 | return -EIO; | ||
206 | } | ||
207 | |||
208 | dev_dbg(&i2c->dev, "Download complete\n"); | ||
209 | |||
210 | if (analogue) { | ||
211 | timeout = 248; | ||
212 | wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); | ||
213 | |||
214 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
215 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
216 | WM2000_MODE_MOUSE_ENABLE | | ||
217 | WM2000_MODE_THERMAL_ENABLE); | ||
218 | } else { | ||
219 | timeout = 10; | ||
220 | |||
221 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
222 | WM2000_MODE_MOUSE_ENABLE | | ||
223 | WM2000_MODE_THERMAL_ENABLE); | ||
224 | } | ||
225 | |||
226 | ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); | ||
227 | if (wm2000->speech_clarity) | ||
228 | ret &= ~WM2000_SPEECH_CLARITY; | ||
229 | else | ||
230 | ret |= WM2000_SPEECH_CLARITY; | ||
231 | wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); | ||
232 | |||
233 | wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); | ||
234 | wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02); | ||
235 | |||
236 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); | ||
237 | |||
238 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
239 | WM2000_STATUS_MOUSE_ACTIVE, timeout)) { | ||
240 | dev_err(&i2c->dev, "Timed out waiting for device after %dms\n", | ||
241 | timeout * 10); | ||
242 | return -ETIMEDOUT; | ||
243 | } | ||
244 | |||
245 | dev_dbg(&i2c->dev, "ANC active\n"); | ||
246 | if (analogue) | ||
247 | dev_dbg(&i2c->dev, "Analogue active\n"); | ||
248 | wm2000->anc_mode = ANC_ACTIVE; | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int wm2000_power_down(struct i2c_client *i2c, int analogue) | ||
254 | { | ||
255 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
256 | int timeout; | ||
257 | |||
258 | if (analogue) { | ||
259 | timeout = 248; | ||
260 | wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); | ||
261 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
262 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
263 | WM2000_MODE_POWER_DOWN); | ||
264 | } else { | ||
265 | timeout = 10; | ||
266 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
267 | WM2000_MODE_POWER_DOWN); | ||
268 | } | ||
269 | |||
270 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
271 | WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) { | ||
272 | dev_err(&i2c->dev, "Timeout waiting for ANC power down\n"); | ||
273 | return -ETIMEDOUT; | ||
274 | } | ||
275 | |||
276 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | ||
277 | WM2000_ANC_ENG_IDLE, 1)) { | ||
278 | dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); | ||
279 | return -ETIMEDOUT; | ||
280 | } | ||
281 | |||
282 | dev_dbg(&i2c->dev, "powered off\n"); | ||
283 | wm2000->anc_mode = ANC_OFF; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue) | ||
289 | { | ||
290 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
291 | |||
292 | BUG_ON(wm2000->anc_mode != ANC_ACTIVE); | ||
293 | |||
294 | if (analogue) { | ||
295 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
296 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
297 | WM2000_MODE_THERMAL_ENABLE | | ||
298 | WM2000_MODE_BYPASS_ENTRY); | ||
299 | } else { | ||
300 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
301 | WM2000_MODE_THERMAL_ENABLE | | ||
302 | WM2000_MODE_BYPASS_ENTRY); | ||
303 | } | ||
304 | |||
305 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
306 | WM2000_STATUS_ANC_DISABLED, 10)) { | ||
307 | dev_err(&i2c->dev, "Timeout waiting for ANC disable\n"); | ||
308 | return -ETIMEDOUT; | ||
309 | } | ||
310 | |||
311 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | ||
312 | WM2000_ANC_ENG_IDLE, 1)) { | ||
313 | dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); | ||
314 | return -ETIMEDOUT; | ||
315 | } | ||
316 | |||
317 | wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY); | ||
318 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); | ||
319 | |||
320 | wm2000->anc_mode = ANC_BYPASS; | ||
321 | dev_dbg(&i2c->dev, "bypass enabled\n"); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) | ||
327 | { | ||
328 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
329 | |||
330 | BUG_ON(wm2000->anc_mode != ANC_BYPASS); | ||
331 | |||
332 | wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); | ||
333 | |||
334 | if (analogue) { | ||
335 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
336 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
337 | WM2000_MODE_MOUSE_ENABLE | | ||
338 | WM2000_MODE_THERMAL_ENABLE); | ||
339 | } else { | ||
340 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
341 | WM2000_MODE_MOUSE_ENABLE | | ||
342 | WM2000_MODE_THERMAL_ENABLE); | ||
343 | } | ||
344 | |||
345 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); | ||
346 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); | ||
347 | |||
348 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
349 | WM2000_STATUS_MOUSE_ACTIVE, 10)) { | ||
350 | dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); | ||
351 | return -ETIMEDOUT; | ||
352 | } | ||
353 | |||
354 | wm2000->anc_mode = ANC_ACTIVE; | ||
355 | dev_dbg(&i2c->dev, "MOUSE active\n"); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) | ||
361 | { | ||
362 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
363 | int timeout; | ||
364 | |||
365 | BUG_ON(wm2000->anc_mode != ANC_ACTIVE); | ||
366 | |||
367 | if (analogue) { | ||
368 | timeout = 248; | ||
369 | wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); | ||
370 | |||
371 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
372 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
373 | WM2000_MODE_THERMAL_ENABLE | | ||
374 | WM2000_MODE_STANDBY_ENTRY); | ||
375 | } else { | ||
376 | timeout = 10; | ||
377 | |||
378 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
379 | WM2000_MODE_THERMAL_ENABLE | | ||
380 | WM2000_MODE_STANDBY_ENTRY); | ||
381 | } | ||
382 | |||
383 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
384 | WM2000_STATUS_ANC_DISABLED, timeout)) { | ||
385 | dev_err(&i2c->dev, | ||
386 | "Timed out waiting for ANC disable after 1ms\n"); | ||
387 | return -ETIMEDOUT; | ||
388 | } | ||
389 | |||
390 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE, | ||
391 | 1)) { | ||
392 | dev_err(&i2c->dev, | ||
393 | "Timed out waiting for standby after %dms\n", | ||
394 | timeout * 10); | ||
395 | return -ETIMEDOUT; | ||
396 | } | ||
397 | |||
398 | wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY); | ||
399 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); | ||
400 | |||
401 | wm2000->anc_mode = ANC_STANDBY; | ||
402 | dev_dbg(&i2c->dev, "standby\n"); | ||
403 | if (analogue) | ||
404 | dev_dbg(&i2c->dev, "Analogue disabled\n"); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) | ||
410 | { | ||
411 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
412 | int timeout; | ||
413 | |||
414 | BUG_ON(wm2000->anc_mode != ANC_STANDBY); | ||
415 | |||
416 | wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); | ||
417 | |||
418 | if (analogue) { | ||
419 | timeout = 248; | ||
420 | wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); | ||
421 | |||
422 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
423 | WM2000_MODE_ANA_SEQ_INCLUDE | | ||
424 | WM2000_MODE_THERMAL_ENABLE | | ||
425 | WM2000_MODE_MOUSE_ENABLE); | ||
426 | } else { | ||
427 | timeout = 10; | ||
428 | |||
429 | wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, | ||
430 | WM2000_MODE_THERMAL_ENABLE | | ||
431 | WM2000_MODE_MOUSE_ENABLE); | ||
432 | } | ||
433 | |||
434 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); | ||
435 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); | ||
436 | |||
437 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | ||
438 | WM2000_STATUS_MOUSE_ACTIVE, timeout)) { | ||
439 | dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n", | ||
440 | timeout * 10); | ||
441 | return -ETIMEDOUT; | ||
442 | } | ||
443 | |||
444 | wm2000->anc_mode = ANC_ACTIVE; | ||
445 | dev_dbg(&i2c->dev, "MOUSE active\n"); | ||
446 | if (analogue) | ||
447 | dev_dbg(&i2c->dev, "Analogue enabled\n"); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | typedef int (*wm2000_mode_fn)(struct i2c_client *i2c, int analogue); | ||
453 | |||
454 | static struct { | ||
455 | enum wm2000_anc_mode source; | ||
456 | enum wm2000_anc_mode dest; | ||
457 | int analogue; | ||
458 | wm2000_mode_fn step[2]; | ||
459 | } anc_transitions[] = { | ||
460 | { | ||
461 | .source = ANC_OFF, | ||
462 | .dest = ANC_ACTIVE, | ||
463 | .analogue = 1, | ||
464 | .step = { | ||
465 | wm2000_power_up, | ||
466 | }, | ||
467 | }, | ||
468 | { | ||
469 | .source = ANC_OFF, | ||
470 | .dest = ANC_STANDBY, | ||
471 | .step = { | ||
472 | wm2000_power_up, | ||
473 | wm2000_enter_standby, | ||
474 | }, | ||
475 | }, | ||
476 | { | ||
477 | .source = ANC_OFF, | ||
478 | .dest = ANC_BYPASS, | ||
479 | .analogue = 1, | ||
480 | .step = { | ||
481 | wm2000_power_up, | ||
482 | wm2000_enter_bypass, | ||
483 | }, | ||
484 | }, | ||
485 | { | ||
486 | .source = ANC_ACTIVE, | ||
487 | .dest = ANC_BYPASS, | ||
488 | .analogue = 1, | ||
489 | .step = { | ||
490 | wm2000_enter_bypass, | ||
491 | }, | ||
492 | }, | ||
493 | { | ||
494 | .source = ANC_ACTIVE, | ||
495 | .dest = ANC_STANDBY, | ||
496 | .analogue = 1, | ||
497 | .step = { | ||
498 | wm2000_enter_standby, | ||
499 | }, | ||
500 | }, | ||
501 | { | ||
502 | .source = ANC_ACTIVE, | ||
503 | .dest = ANC_OFF, | ||
504 | .analogue = 1, | ||
505 | .step = { | ||
506 | wm2000_power_down, | ||
507 | }, | ||
508 | }, | ||
509 | { | ||
510 | .source = ANC_BYPASS, | ||
511 | .dest = ANC_ACTIVE, | ||
512 | .analogue = 1, | ||
513 | .step = { | ||
514 | wm2000_exit_bypass, | ||
515 | }, | ||
516 | }, | ||
517 | { | ||
518 | .source = ANC_BYPASS, | ||
519 | .dest = ANC_STANDBY, | ||
520 | .analogue = 1, | ||
521 | .step = { | ||
522 | wm2000_exit_bypass, | ||
523 | wm2000_enter_standby, | ||
524 | }, | ||
525 | }, | ||
526 | { | ||
527 | .source = ANC_BYPASS, | ||
528 | .dest = ANC_OFF, | ||
529 | .step = { | ||
530 | wm2000_exit_bypass, | ||
531 | wm2000_power_down, | ||
532 | }, | ||
533 | }, | ||
534 | { | ||
535 | .source = ANC_STANDBY, | ||
536 | .dest = ANC_ACTIVE, | ||
537 | .analogue = 1, | ||
538 | .step = { | ||
539 | wm2000_exit_standby, | ||
540 | }, | ||
541 | }, | ||
542 | { | ||
543 | .source = ANC_STANDBY, | ||
544 | .dest = ANC_BYPASS, | ||
545 | .analogue = 1, | ||
546 | .step = { | ||
547 | wm2000_exit_standby, | ||
548 | wm2000_enter_bypass, | ||
549 | }, | ||
550 | }, | ||
551 | { | ||
552 | .source = ANC_STANDBY, | ||
553 | .dest = ANC_OFF, | ||
554 | .step = { | ||
555 | wm2000_exit_standby, | ||
556 | wm2000_power_down, | ||
557 | }, | ||
558 | }, | ||
559 | }; | ||
560 | |||
561 | static int wm2000_anc_transition(struct wm2000_priv *wm2000, | ||
562 | enum wm2000_anc_mode mode) | ||
563 | { | ||
564 | struct i2c_client *i2c = wm2000->i2c; | ||
565 | int i, j; | ||
566 | int ret; | ||
567 | |||
568 | if (wm2000->anc_mode == mode) | ||
569 | return 0; | ||
570 | |||
571 | for (i = 0; i < ARRAY_SIZE(anc_transitions); i++) | ||
572 | if (anc_transitions[i].source == wm2000->anc_mode && | ||
573 | anc_transitions[i].dest == mode) | ||
574 | break; | ||
575 | if (i == ARRAY_SIZE(anc_transitions)) { | ||
576 | dev_err(&i2c->dev, "No transition for %d->%d\n", | ||
577 | wm2000->anc_mode, mode); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { | ||
582 | if (!anc_transitions[i].step[j]) | ||
583 | break; | ||
584 | ret = anc_transitions[i].step[j](i2c, | ||
585 | anc_transitions[i].analogue); | ||
586 | if (ret != 0) | ||
587 | return ret; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) | ||
594 | { | ||
595 | struct i2c_client *i2c = wm2000->i2c; | ||
596 | enum wm2000_anc_mode mode; | ||
597 | |||
598 | if (wm2000->anc_eng_ena && wm2000->spk_ena) | ||
599 | if (wm2000->anc_active) | ||
600 | mode = ANC_ACTIVE; | ||
601 | else | ||
602 | mode = ANC_BYPASS; | ||
603 | else | ||
604 | mode = ANC_STANDBY; | ||
605 | |||
606 | dev_dbg(&i2c->dev, "Set mode %d (enabled %d, mute %d, active %d)\n", | ||
607 | mode, wm2000->anc_eng_ena, !wm2000->spk_ena, | ||
608 | wm2000->anc_active); | ||
609 | |||
610 | return wm2000_anc_transition(wm2000, mode); | ||
611 | } | ||
612 | |||
613 | static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol, | ||
614 | struct snd_ctl_elem_value *ucontrol) | ||
615 | { | ||
616 | struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev); | ||
617 | |||
618 | ucontrol->value.enumerated.item[0] = wm2000->anc_active; | ||
619 | |||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, | ||
624 | struct snd_ctl_elem_value *ucontrol) | ||
625 | { | ||
626 | struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev); | ||
627 | int anc_active = ucontrol->value.enumerated.item[0]; | ||
628 | |||
629 | if (anc_active > 1) | ||
630 | return -EINVAL; | ||
631 | |||
632 | wm2000->anc_active = anc_active; | ||
633 | |||
634 | return wm2000_anc_set_mode(wm2000); | ||
635 | } | ||
636 | |||
637 | static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, | ||
638 | struct snd_ctl_elem_value *ucontrol) | ||
639 | { | ||
640 | struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev); | ||
641 | |||
642 | ucontrol->value.enumerated.item[0] = wm2000->spk_ena; | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, | ||
648 | struct snd_ctl_elem_value *ucontrol) | ||
649 | { | ||
650 | struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev); | ||
651 | int val = ucontrol->value.enumerated.item[0]; | ||
652 | |||
653 | if (val > 1) | ||
654 | return -EINVAL; | ||
655 | |||
656 | wm2000->spk_ena = val; | ||
657 | |||
658 | return wm2000_anc_set_mode(wm2000); | ||
659 | } | ||
660 | |||
661 | static const struct snd_kcontrol_new wm2000_controls[] = { | ||
662 | SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0, | ||
663 | wm2000_anc_mode_get, | ||
664 | wm2000_anc_mode_put), | ||
665 | SOC_SINGLE_BOOL_EXT("WM2000 Switch", 0, | ||
666 | wm2000_speaker_get, | ||
667 | wm2000_speaker_put), | ||
668 | }; | ||
669 | |||
670 | static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, | ||
671 | struct snd_kcontrol *kcontrol, int event) | ||
672 | { | ||
673 | struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev); | ||
674 | |||
675 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
676 | wm2000->anc_eng_ena = 1; | ||
677 | |||
678 | if (SND_SOC_DAPM_EVENT_OFF(event)) | ||
679 | wm2000->anc_eng_ena = 0; | ||
680 | |||
681 | return wm2000_anc_set_mode(wm2000); | ||
682 | } | ||
683 | |||
684 | static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { | ||
685 | /* Externally visible pins */ | ||
686 | SND_SOC_DAPM_OUTPUT("WM2000 SPKN"), | ||
687 | SND_SOC_DAPM_OUTPUT("WM2000 SPKP"), | ||
688 | |||
689 | SND_SOC_DAPM_INPUT("WM2000 LINN"), | ||
690 | SND_SOC_DAPM_INPUT("WM2000 LINP"), | ||
691 | |||
692 | SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
693 | wm2000_anc_power_event, | ||
694 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
695 | }; | ||
696 | |||
697 | /* Target, Path, Source */ | ||
698 | static const struct snd_soc_dapm_route audio_map[] = { | ||
699 | { "WM2000 SPKN", NULL, "ANC Engine" }, | ||
700 | { "WM2000 SPKP", NULL, "ANC Engine" }, | ||
701 | { "ANC Engine", NULL, "WM2000 LINN" }, | ||
702 | { "ANC Engine", NULL, "WM2000 LINP" }, | ||
703 | }; | ||
704 | |||
705 | /* Called from the machine driver */ | ||
706 | int wm2000_add_controls(struct snd_soc_codec *codec) | ||
707 | { | ||
708 | int ret; | ||
709 | |||
710 | if (!wm2000_i2c) { | ||
711 | pr_err("WM2000 not yet probed\n"); | ||
712 | return -ENODEV; | ||
713 | } | ||
714 | |||
715 | ret = snd_soc_dapm_new_controls(codec, wm2000_dapm_widgets, | ||
716 | ARRAY_SIZE(wm2000_dapm_widgets)); | ||
717 | if (ret < 0) | ||
718 | return ret; | ||
719 | |||
720 | ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
721 | if (ret < 0) | ||
722 | return ret; | ||
723 | |||
724 | return snd_soc_add_controls(codec, wm2000_controls, | ||
725 | ARRAY_SIZE(wm2000_controls)); | ||
726 | } | ||
727 | EXPORT_SYMBOL_GPL(wm2000_add_controls); | ||
728 | |||
729 | static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | ||
730 | const struct i2c_device_id *i2c_id) | ||
731 | { | ||
732 | struct wm2000_priv *wm2000; | ||
733 | struct wm2000_platform_data *pdata; | ||
734 | const char *filename; | ||
735 | const struct firmware *fw; | ||
736 | int reg, ret; | ||
737 | u16 id; | ||
738 | |||
739 | if (wm2000_i2c) { | ||
740 | dev_err(&i2c->dev, "Another WM2000 is already registered\n"); | ||
741 | return -EINVAL; | ||
742 | } | ||
743 | |||
744 | wm2000 = kzalloc(sizeof(struct wm2000_priv), GFP_KERNEL); | ||
745 | if (wm2000 == NULL) { | ||
746 | dev_err(&i2c->dev, "Unable to allocate private data\n"); | ||
747 | return -ENOMEM; | ||
748 | } | ||
749 | |||
750 | /* Verify that this is a WM2000 */ | ||
751 | reg = wm2000_read(i2c, WM2000_REG_ID1); | ||
752 | id = reg << 8; | ||
753 | reg = wm2000_read(i2c, WM2000_REG_ID2); | ||
754 | id |= reg & 0xff; | ||
755 | |||
756 | if (id != 0x2000) { | ||
757 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); | ||
758 | ret = -ENODEV; | ||
759 | goto err; | ||
760 | } | ||
761 | |||
762 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | ||
763 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); | ||
764 | |||
765 | filename = "wm2000_anc.bin"; | ||
766 | pdata = dev_get_platdata(&i2c->dev); | ||
767 | if (pdata) { | ||
768 | wm2000->mclk_div = pdata->mclkdiv2; | ||
769 | wm2000->speech_clarity = !pdata->speech_enh_disable; | ||
770 | |||
771 | if (pdata->download_file) | ||
772 | filename = pdata->download_file; | ||
773 | } | ||
774 | |||
775 | ret = request_firmware(&fw, filename, &i2c->dev); | ||
776 | if (ret != 0) { | ||
777 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); | ||
778 | goto err; | ||
779 | } | ||
780 | |||
781 | /* Pre-cook the concatenation of the register address onto the image */ | ||
782 | wm2000->anc_download_size = fw->size + 2; | ||
783 | wm2000->anc_download = kmalloc(wm2000->anc_download_size, GFP_KERNEL); | ||
784 | if (wm2000->anc_download == NULL) { | ||
785 | dev_err(&i2c->dev, "Out of memory\n"); | ||
786 | ret = -ENOMEM; | ||
787 | goto err_fw; | ||
788 | } | ||
789 | |||
790 | wm2000->anc_download[0] = 0x80; | ||
791 | wm2000->anc_download[1] = 0x00; | ||
792 | memcpy(wm2000->anc_download + 2, fw->data, fw->size); | ||
793 | |||
794 | release_firmware(fw); | ||
795 | |||
796 | dev_set_drvdata(&i2c->dev, wm2000); | ||
797 | wm2000->anc_eng_ena = 1; | ||
798 | wm2000->i2c = i2c; | ||
799 | |||
800 | wm2000_reset(wm2000); | ||
801 | |||
802 | /* This will trigger a transition to standby mode by default */ | ||
803 | wm2000_anc_set_mode(wm2000); | ||
804 | |||
805 | wm2000_i2c = i2c; | ||
806 | |||
807 | return 0; | ||
808 | |||
809 | err_fw: | ||
810 | release_firmware(fw); | ||
811 | err: | ||
812 | kfree(wm2000); | ||
813 | return ret; | ||
814 | } | ||
815 | |||
816 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) | ||
817 | { | ||
818 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
819 | |||
820 | wm2000_anc_transition(wm2000, ANC_OFF); | ||
821 | |||
822 | wm2000_i2c = NULL; | ||
823 | kfree(wm2000->anc_download); | ||
824 | kfree(wm2000); | ||
825 | |||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | static void wm2000_i2c_shutdown(struct i2c_client *i2c) | ||
830 | { | ||
831 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
832 | |||
833 | wm2000_anc_transition(wm2000, ANC_OFF); | ||
834 | } | ||
835 | |||
836 | #ifdef CONFIG_PM | ||
837 | static int wm2000_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | ||
838 | { | ||
839 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
840 | |||
841 | return wm2000_anc_transition(wm2000, ANC_OFF); | ||
842 | } | ||
843 | |||
844 | static int wm2000_i2c_resume(struct i2c_client *i2c) | ||
845 | { | ||
846 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
847 | |||
848 | return wm2000_anc_set_mode(wm2000); | ||
849 | } | ||
850 | #else | ||
851 | #define wm2000_i2c_suspend NULL | ||
852 | #define wm2000_i2c_resume NULL | ||
853 | #endif | ||
854 | |||
855 | static const struct i2c_device_id wm2000_i2c_id[] = { | ||
856 | { "wm2000", 0 }, | ||
857 | { } | ||
858 | }; | ||
859 | MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id); | ||
860 | |||
861 | static struct i2c_driver wm2000_i2c_driver = { | ||
862 | .driver = { | ||
863 | .name = "wm2000", | ||
864 | .owner = THIS_MODULE, | ||
865 | }, | ||
866 | .probe = wm2000_i2c_probe, | ||
867 | .remove = __devexit_p(wm2000_i2c_remove), | ||
868 | .suspend = wm2000_i2c_suspend, | ||
869 | .resume = wm2000_i2c_resume, | ||
870 | .shutdown = wm2000_i2c_shutdown, | ||
871 | .id_table = wm2000_i2c_id, | ||
872 | }; | ||
873 | |||
874 | static int __init wm2000_init(void) | ||
875 | { | ||
876 | return i2c_add_driver(&wm2000_i2c_driver); | ||
877 | } | ||
878 | module_init(wm2000_init); | ||
879 | |||
880 | static void __exit wm2000_exit(void) | ||
881 | { | ||
882 | i2c_del_driver(&wm2000_i2c_driver); | ||
883 | } | ||
884 | module_exit(wm2000_exit); | ||
885 | |||
886 | MODULE_DESCRIPTION("ASoC WM2000 driver"); | ||
887 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | ||
888 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h new file mode 100644 index 000000000000..c18e261c3c7f --- /dev/null +++ b/sound/soc/codecs/wm2000.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * wm2000.h -- WM2000 Soc Audio driver | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _WM2000_H | ||
10 | #define _WM2000_H | ||
11 | |||
12 | struct wm2000_setup_data { | ||
13 | unsigned short i2c_address; | ||
14 | int mclk_div; /* Set to a non-zero value if MCLK_DIV_2 required */ | ||
15 | }; | ||
16 | |||
17 | extern int wm2000_add_controls(struct snd_soc_codec *codec); | ||
18 | |||
19 | extern struct snd_soc_dai wm2000_dai; | ||
20 | extern struct snd_soc_codec_device soc_codec_dev_wm2000; | ||
21 | |||
22 | #define WM2000_REG_SYS_START 0x8000 | ||
23 | #define WM2000_REG_SPEECH_CLARITY 0x8fef | ||
24 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 | ||
25 | #define WM2000_REG_ANA_VMID_PD_TIME 0x8ff7 | ||
26 | #define WM2000_REG_ANA_VMID_PU_TIME 0x8ff8 | ||
27 | #define WM2000_REG_CAT_FLTR_INDX 0x8ff9 | ||
28 | #define WM2000_REG_CAT_GAIN_0 0x8ffa | ||
29 | #define WM2000_REG_SYS_STATUS 0x8ffc | ||
30 | #define WM2000_REG_SYS_MODE_CNTRL 0x8ffd | ||
31 | #define WM2000_REG_SYS_START0 0x8ffe | ||
32 | #define WM2000_REG_SYS_START1 0x8fff | ||
33 | #define WM2000_REG_ID1 0xf000 | ||
34 | #define WM2000_REG_ID2 0xf001 | ||
35 | #define WM2000_REG_REVISON 0xf002 | ||
36 | #define WM2000_REG_SYS_CTL1 0xf003 | ||
37 | #define WM2000_REG_SYS_CTL2 0xf004 | ||
38 | #define WM2000_REG_ANC_STAT 0xf005 | ||
39 | #define WM2000_REG_IF_CTL 0xf006 | ||
40 | |||
41 | /* SPEECH_CLARITY */ | ||
42 | #define WM2000_SPEECH_CLARITY 0x01 | ||
43 | |||
44 | /* SYS_STATUS */ | ||
45 | #define WM2000_STATUS_MOUSE_ACTIVE 0x40 | ||
46 | #define WM2000_STATUS_CAT_FREQ_COMPLETE 0x20 | ||
47 | #define WM2000_STATUS_CAT_GAIN_COMPLETE 0x10 | ||
48 | #define WM2000_STATUS_THERMAL_SHUTDOWN_COMPLETE 0x08 | ||
49 | #define WM2000_STATUS_ANC_DISABLED 0x04 | ||
50 | #define WM2000_STATUS_POWER_DOWN_COMPLETE 0x02 | ||
51 | #define WM2000_STATUS_BOOT_COMPLETE 0x01 | ||
52 | |||
53 | /* SYS_MODE_CNTRL */ | ||
54 | #define WM2000_MODE_ANA_SEQ_INCLUDE 0x80 | ||
55 | #define WM2000_MODE_MOUSE_ENABLE 0x40 | ||
56 | #define WM2000_MODE_CAT_FREQ_ENABLE 0x20 | ||
57 | #define WM2000_MODE_CAT_GAIN_ENABLE 0x10 | ||
58 | #define WM2000_MODE_BYPASS_ENTRY 0x08 | ||
59 | #define WM2000_MODE_STANDBY_ENTRY 0x04 | ||
60 | #define WM2000_MODE_THERMAL_ENABLE 0x02 | ||
61 | #define WM2000_MODE_POWER_DOWN 0x01 | ||
62 | |||
63 | /* SYS_CTL1 */ | ||
64 | #define WM2000_SYS_STBY 0x01 | ||
65 | |||
66 | /* SYS_CTL2 */ | ||
67 | #define WM2000_MCLK_DIV2_ENA_CLR 0x80 | ||
68 | #define WM2000_MCLK_DIV2_ENA_SET 0x40 | ||
69 | #define WM2000_ANC_ENG_CLR 0x20 | ||
70 | #define WM2000_ANC_ENG_SET 0x10 | ||
71 | #define WM2000_ANC_INT_N_CLR 0x08 | ||
72 | #define WM2000_ANC_INT_N_SET 0x04 | ||
73 | #define WM2000_RAM_CLR 0x02 | ||
74 | #define WM2000_RAM_SET 0x01 | ||
75 | |||
76 | /* ANC_STAT */ | ||
77 | #define WM2000_ANC_ENG_IDLE 0x01 | ||
78 | |||
79 | #endif | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 593d5b9c9f03..2e0772f9c456 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
@@ -800,7 +801,7 @@ static int wm8350_add_widgets(struct snd_soc_codec *codec) | |||
800 | return ret; | 801 | return ret; |
801 | } | 802 | } |
802 | 803 | ||
803 | return snd_soc_dapm_new_widgets(codec); | 804 | return 0; |
804 | } | 805 | } |
805 | 806 | ||
806 | static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 807 | static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
@@ -925,7 +926,7 @@ static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
925 | iface |= 0x3 << 8; | 926 | iface |= 0x3 << 8; |
926 | break; | 927 | break; |
927 | case SND_SOC_DAIFMT_DSP_B: | 928 | case SND_SOC_DAIFMT_DSP_B: |
928 | iface |= 0x3 << 8; /* lg not sure which mode */ | 929 | iface |= 0x3 << 8 | WM8350_AIF_LRCLK_INV; |
929 | break; | 930 | break; |
930 | default: | 931 | default: |
931 | return -EINVAL; | 932 | return -EINVAL; |
@@ -1101,7 +1102,7 @@ static inline int fll_factors(struct _fll_div *fll_div, unsigned int input, | |||
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | static int wm8350_set_fll(struct snd_soc_dai *codec_dai, | 1104 | static int wm8350_set_fll(struct snd_soc_dai *codec_dai, |
1104 | int pll_id, unsigned int freq_in, | 1105 | int pll_id, int source, unsigned int freq_in, |
1105 | unsigned int freq_out) | 1106 | unsigned int freq_out) |
1106 | { | 1107 | { |
1107 | struct snd_soc_codec *codec = codec_dai->codec; | 1108 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -1340,15 +1341,16 @@ static int wm8350_resume(struct platform_device *pdev) | |||
1340 | return 0; | 1341 | return 0; |
1341 | } | 1342 | } |
1342 | 1343 | ||
1343 | static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | 1344 | static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) |
1344 | { | 1345 | { |
1345 | struct wm8350_data *priv = data; | 1346 | struct wm8350_data *priv = data; |
1347 | struct wm8350 *wm8350 = priv->codec.control_data; | ||
1346 | u16 reg; | 1348 | u16 reg; |
1347 | int report; | 1349 | int report; |
1348 | int mask; | 1350 | int mask; |
1349 | struct wm8350_jack_data *jack = NULL; | 1351 | struct wm8350_jack_data *jack = NULL; |
1350 | 1352 | ||
1351 | switch (irq) { | 1353 | switch (irq - wm8350->irq_base) { |
1352 | case WM8350_IRQ_CODEC_JCK_DET_L: | 1354 | case WM8350_IRQ_CODEC_JCK_DET_L: |
1353 | jack = &priv->hpl; | 1355 | jack = &priv->hpl; |
1354 | mask = WM8350_JACK_L_LVL; | 1356 | mask = WM8350_JACK_L_LVL; |
@@ -1365,7 +1367,7 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | |||
1365 | 1367 | ||
1366 | if (!jack->jack) { | 1368 | if (!jack->jack) { |
1367 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | 1369 | dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); |
1368 | return; | 1370 | return IRQ_NONE; |
1369 | } | 1371 | } |
1370 | 1372 | ||
1371 | /* Debounce */ | 1373 | /* Debounce */ |
@@ -1378,6 +1380,8 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) | |||
1378 | report = 0; | 1380 | report = 0; |
1379 | 1381 | ||
1380 | snd_soc_jack_report(jack->jack, report, jack->report); | 1382 | snd_soc_jack_report(jack->jack, report, jack->report); |
1383 | |||
1384 | return IRQ_HANDLED; | ||
1381 | } | 1385 | } |
1382 | 1386 | ||
1383 | /** | 1387 | /** |
@@ -1421,9 +1425,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, | |||
1421 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); | 1425 | wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); |
1422 | 1426 | ||
1423 | /* Sync status */ | 1427 | /* Sync status */ |
1424 | wm8350_hp_jack_handler(wm8350, irq, priv); | 1428 | wm8350_hp_jack_handler(irq + wm8350->irq_base, priv); |
1425 | |||
1426 | wm8350_unmask_irq(wm8350, irq); | ||
1427 | 1429 | ||
1428 | return 0; | 1430 | return 0; |
1429 | } | 1431 | } |
@@ -1482,12 +1484,16 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1482 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, | 1484 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, |
1483 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); | 1485 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); |
1484 | 1486 | ||
1485 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | 1487 | /* Make sure jack detect is disabled to start off with */ |
1486 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | 1488 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, |
1489 | WM8350_JDL_ENA | WM8350_JDR_ENA); | ||
1490 | |||
1487 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, | 1491 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, |
1488 | wm8350_hp_jack_handler, priv); | 1492 | wm8350_hp_jack_handler, 0, "Left jack detect", |
1493 | priv); | ||
1489 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, | 1494 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, |
1490 | wm8350_hp_jack_handler, priv); | 1495 | wm8350_hp_jack_handler, 0, "Right jack detect", |
1496 | priv); | ||
1491 | 1497 | ||
1492 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1498 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1493 | if (ret < 0) { | 1499 | if (ret < 0) { |
@@ -1501,18 +1507,7 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1501 | 1507 | ||
1502 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1508 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1503 | 1509 | ||
1504 | ret = snd_soc_init_card(socdev); | ||
1505 | if (ret < 0) { | ||
1506 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1507 | goto card_err; | ||
1508 | } | ||
1509 | |||
1510 | return 0; | 1510 | return 0; |
1511 | |||
1512 | card_err: | ||
1513 | snd_soc_free_pcms(socdev); | ||
1514 | snd_soc_dapm_free(socdev); | ||
1515 | return ret; | ||
1516 | } | 1511 | } |
1517 | 1512 | ||
1518 | static int wm8350_remove(struct platform_device *pdev) | 1513 | static int wm8350_remove(struct platform_device *pdev) |
@@ -1527,10 +1522,8 @@ static int wm8350_remove(struct platform_device *pdev) | |||
1527 | WM8350_JDL_ENA | WM8350_JDR_ENA); | 1522 | WM8350_JDL_ENA | WM8350_JDR_ENA); |
1528 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | 1523 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); |
1529 | 1524 | ||
1530 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | 1525 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); |
1531 | wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | 1526 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); |
1532 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); | ||
1533 | wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); | ||
1534 | 1527 | ||
1535 | priv->hpl.jack = NULL; | 1528 | priv->hpl.jack = NULL; |
1536 | priv->hpr.jack = NULL; | 1529 | priv->hpr.jack = NULL; |
@@ -1680,21 +1673,6 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev) | |||
1680 | return 0; | 1673 | return 0; |
1681 | } | 1674 | } |
1682 | 1675 | ||
1683 | #ifdef CONFIG_PM | ||
1684 | static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m) | ||
1685 | { | ||
1686 | return snd_soc_suspend_device(&pdev->dev); | ||
1687 | } | ||
1688 | |||
1689 | static int wm8350_codec_resume(struct platform_device *pdev) | ||
1690 | { | ||
1691 | return snd_soc_resume_device(&pdev->dev); | ||
1692 | } | ||
1693 | #else | ||
1694 | #define wm8350_codec_suspend NULL | ||
1695 | #define wm8350_codec_resume NULL | ||
1696 | #endif | ||
1697 | |||
1698 | static struct platform_driver wm8350_codec_driver = { | 1676 | static struct platform_driver wm8350_codec_driver = { |
1699 | .driver = { | 1677 | .driver = { |
1700 | .name = "wm8350-codec", | 1678 | .name = "wm8350-codec", |
@@ -1702,8 +1680,6 @@ static struct platform_driver wm8350_codec_driver = { | |||
1702 | }, | 1680 | }, |
1703 | .probe = wm8350_codec_probe, | 1681 | .probe = wm8350_codec_probe, |
1704 | .remove = __devexit_p(wm8350_codec_remove), | 1682 | .remove = __devexit_p(wm8350_codec_remove), |
1705 | .suspend = wm8350_codec_suspend, | ||
1706 | .resume = wm8350_codec_resume, | ||
1707 | }; | 1683 | }; |
1708 | 1684 | ||
1709 | static __init int wm8350_init(void) | 1685 | static __init int wm8350_init(void) |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b9ef4d915221..6acc885cf9b7 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
@@ -915,7 +916,6 @@ static int wm8400_add_widgets(struct snd_soc_codec *codec) | |||
915 | 916 | ||
916 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 917 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
917 | 918 | ||
918 | snd_soc_dapm_new_widgets(codec); | ||
919 | return 0; | 919 | return 0; |
920 | } | 920 | } |
921 | 921 | ||
@@ -1011,7 +1011,8 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors, | |||
1011 | } | 1011 | } |
1012 | 1012 | ||
1013 | static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | 1013 | static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
1014 | unsigned int freq_in, unsigned int freq_out) | 1014 | int source, unsigned int freq_in, |
1015 | unsigned int freq_out) | ||
1015 | { | 1016 | { |
1016 | struct snd_soc_codec *codec = codec_dai->codec; | 1017 | struct snd_soc_codec *codec = codec_dai->codec; |
1017 | struct wm8400_priv *wm8400 = codec->private_data; | 1018 | struct wm8400_priv *wm8400 = codec->private_data; |
@@ -1399,17 +1400,6 @@ static int wm8400_probe(struct platform_device *pdev) | |||
1399 | wm8400_add_controls(codec); | 1400 | wm8400_add_controls(codec); |
1400 | wm8400_add_widgets(codec); | 1401 | wm8400_add_widgets(codec); |
1401 | 1402 | ||
1402 | ret = snd_soc_init_card(socdev); | ||
1403 | if (ret < 0) { | ||
1404 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1405 | goto card_err; | ||
1406 | } | ||
1407 | |||
1408 | return ret; | ||
1409 | |||
1410 | card_err: | ||
1411 | snd_soc_free_pcms(socdev); | ||
1412 | snd_soc_dapm_free(socdev); | ||
1413 | pcm_err: | 1403 | pcm_err: |
1414 | return ret; | 1404 | return ret; |
1415 | } | 1405 | } |
@@ -1558,21 +1548,6 @@ static int __exit wm8400_codec_remove(struct platform_device *dev) | |||
1558 | return 0; | 1548 | return 0; |
1559 | } | 1549 | } |
1560 | 1550 | ||
1561 | #ifdef CONFIG_PM | ||
1562 | static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg) | ||
1563 | { | ||
1564 | return snd_soc_suspend_device(&pdev->dev); | ||
1565 | } | ||
1566 | |||
1567 | static int wm8400_pdev_resume(struct platform_device *pdev) | ||
1568 | { | ||
1569 | return snd_soc_resume_device(&pdev->dev); | ||
1570 | } | ||
1571 | #else | ||
1572 | #define wm8400_pdev_suspend NULL | ||
1573 | #define wm8400_pdev_resume NULL | ||
1574 | #endif | ||
1575 | |||
1576 | static struct platform_driver wm8400_codec_driver = { | 1551 | static struct platform_driver wm8400_codec_driver = { |
1577 | .driver = { | 1552 | .driver = { |
1578 | .name = "wm8400-codec", | 1553 | .name = "wm8400-codec", |
@@ -1580,8 +1555,6 @@ static struct platform_driver wm8400_codec_driver = { | |||
1580 | }, | 1555 | }, |
1581 | .probe = wm8400_codec_probe, | 1556 | .probe = wm8400_codec_probe, |
1582 | .remove = __exit_p(wm8400_codec_remove), | 1557 | .remove = __exit_p(wm8400_codec_remove), |
1583 | .suspend = wm8400_pdev_suspend, | ||
1584 | .resume = wm8400_pdev_resume, | ||
1585 | }; | 1558 | }; |
1586 | 1559 | ||
1587 | static int __init wm8400_codec_init(void) | 1560 | static int __init wm8400_codec_init(void) |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 060d5d06ba95..9000b1d19afb 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -219,7 +220,6 @@ static int wm8510_add_widgets(struct snd_soc_codec *codec) | |||
219 | 220 | ||
220 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 221 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
221 | 222 | ||
222 | snd_soc_dapm_new_widgets(codec); | ||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
@@ -271,8 +271,8 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
271 | pll_div.k = K; | 271 | pll_div.k = K; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, | 274 | static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
275 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 275 | int source, unsigned int freq_in, unsigned int freq_out) |
276 | { | 276 | { |
277 | struct snd_soc_codec *codec = codec_dai->codec; | 277 | struct snd_soc_codec *codec = codec_dai->codec; |
278 | u16 reg; | 278 | u16 reg; |
@@ -425,23 +425,23 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | |||
425 | 425 | ||
426 | /* filter coefficient */ | 426 | /* filter coefficient */ |
427 | switch (params_rate(params)) { | 427 | switch (params_rate(params)) { |
428 | case SNDRV_PCM_RATE_8000: | 428 | case 8000: |
429 | adn |= 0x5 << 1; | 429 | adn |= 0x5 << 1; |
430 | break; | 430 | break; |
431 | case SNDRV_PCM_RATE_11025: | 431 | case 11025: |
432 | adn |= 0x4 << 1; | 432 | adn |= 0x4 << 1; |
433 | break; | 433 | break; |
434 | case SNDRV_PCM_RATE_16000: | 434 | case 16000: |
435 | adn |= 0x3 << 1; | 435 | adn |= 0x3 << 1; |
436 | break; | 436 | break; |
437 | case SNDRV_PCM_RATE_22050: | 437 | case 22050: |
438 | adn |= 0x2 << 1; | 438 | adn |= 0x2 << 1; |
439 | break; | 439 | break; |
440 | case SNDRV_PCM_RATE_32000: | 440 | case 32000: |
441 | adn |= 0x1 << 1; | 441 | adn |= 0x1 << 1; |
442 | break; | 442 | break; |
443 | case SNDRV_PCM_RATE_44100: | 443 | case 44100: |
444 | case SNDRV_PCM_RATE_48000: | 444 | case 48000: |
445 | break; | 445 | break; |
446 | } | 446 | } |
447 | 447 | ||
@@ -604,16 +604,9 @@ static int wm8510_init(struct snd_soc_device *socdev, | |||
604 | snd_soc_add_controls(codec, wm8510_snd_controls, | 604 | snd_soc_add_controls(codec, wm8510_snd_controls, |
605 | ARRAY_SIZE(wm8510_snd_controls)); | 605 | ARRAY_SIZE(wm8510_snd_controls)); |
606 | wm8510_add_widgets(codec); | 606 | wm8510_add_widgets(codec); |
607 | ret = snd_soc_init_card(socdev); | 607 | |
608 | if (ret < 0) { | ||
609 | printk(KERN_ERR "wm8510: failed to register card\n"); | ||
610 | goto card_err; | ||
611 | } | ||
612 | return ret; | 608 | return ret; |
613 | 609 | ||
614 | card_err: | ||
615 | snd_soc_free_pcms(socdev); | ||
616 | snd_soc_dapm_free(socdev); | ||
617 | err: | 610 | err: |
618 | kfree(codec->reg_cache); | 611 | kfree(codec->reg_cache); |
619 | return ret; | 612 | return ret; |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 25870a4652fb..19cd47293424 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
22 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -117,7 +118,6 @@ static int wm8523_add_widgets(struct snd_soc_codec *codec) | |||
117 | 118 | ||
118 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 119 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
119 | 120 | ||
120 | snd_soc_dapm_new_widgets(codec); | ||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | 123 | ||
@@ -448,17 +448,9 @@ static int wm8523_probe(struct platform_device *pdev) | |||
448 | snd_soc_add_controls(codec, wm8523_snd_controls, | 448 | snd_soc_add_controls(codec, wm8523_snd_controls, |
449 | ARRAY_SIZE(wm8523_snd_controls)); | 449 | ARRAY_SIZE(wm8523_snd_controls)); |
450 | wm8523_add_widgets(codec); | 450 | wm8523_add_widgets(codec); |
451 | ret = snd_soc_init_card(socdev); | ||
452 | if (ret < 0) { | ||
453 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
454 | goto card_err; | ||
455 | } | ||
456 | 451 | ||
457 | return ret; | 452 | return ret; |
458 | 453 | ||
459 | card_err: | ||
460 | snd_soc_free_pcms(socdev); | ||
461 | snd_soc_dapm_free(socdev); | ||
462 | pcm_err: | 454 | pcm_err: |
463 | return ret; | 455 | return ret; |
464 | } | 456 | } |
@@ -638,21 +630,6 @@ static __devexit int wm8523_i2c_remove(struct i2c_client *client) | |||
638 | return 0; | 630 | return 0; |
639 | } | 631 | } |
640 | 632 | ||
641 | #ifdef CONFIG_PM | ||
642 | static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) | ||
643 | { | ||
644 | return snd_soc_suspend_device(&i2c->dev); | ||
645 | } | ||
646 | |||
647 | static int wm8523_i2c_resume(struct i2c_client *i2c) | ||
648 | { | ||
649 | return snd_soc_resume_device(&i2c->dev); | ||
650 | } | ||
651 | #else | ||
652 | #define wm8523_i2c_suspend NULL | ||
653 | #define wm8523_i2c_resume NULL | ||
654 | #endif | ||
655 | |||
656 | static const struct i2c_device_id wm8523_i2c_id[] = { | 633 | static const struct i2c_device_id wm8523_i2c_id[] = { |
657 | { "wm8523", 0 }, | 634 | { "wm8523", 0 }, |
658 | { } | 635 | { } |
@@ -666,8 +643,6 @@ static struct i2c_driver wm8523_i2c_driver = { | |||
666 | }, | 643 | }, |
667 | .probe = wm8523_i2c_probe, | 644 | .probe = wm8523_i2c_probe, |
668 | .remove = __devexit_p(wm8523_i2c_remove), | 645 | .remove = __devexit_p(wm8523_i2c_remove), |
669 | .suspend = wm8523_i2c_suspend, | ||
670 | .resume = wm8523_i2c_resume, | ||
671 | .id_table = wm8523_i2c_id, | 646 | .id_table = wm8523_i2c_id, |
672 | }; | 647 | }; |
673 | #endif | 648 | #endif |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 6bded8c78150..8cc9042965eb 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | ||
28 | 29 | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
@@ -315,7 +316,6 @@ static int wm8580_add_widgets(struct snd_soc_codec *codec) | |||
315 | 316 | ||
316 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 317 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
317 | 318 | ||
318 | snd_soc_dapm_new_widgets(codec); | ||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
@@ -407,8 +407,8 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, | 410 | static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
411 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 411 | int source, unsigned int freq_in, unsigned int freq_out) |
412 | { | 412 | { |
413 | int offset; | 413 | int offset; |
414 | struct snd_soc_codec *codec = codec_dai->codec; | 414 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -800,17 +800,9 @@ static int wm8580_probe(struct platform_device *pdev) | |||
800 | snd_soc_add_controls(codec, wm8580_snd_controls, | 800 | snd_soc_add_controls(codec, wm8580_snd_controls, |
801 | ARRAY_SIZE(wm8580_snd_controls)); | 801 | ARRAY_SIZE(wm8580_snd_controls)); |
802 | wm8580_add_widgets(codec); | 802 | wm8580_add_widgets(codec); |
803 | ret = snd_soc_init_card(socdev); | ||
804 | if (ret < 0) { | ||
805 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
806 | goto card_err; | ||
807 | } | ||
808 | 803 | ||
809 | return ret; | 804 | return ret; |
810 | 805 | ||
811 | card_err: | ||
812 | snd_soc_free_pcms(socdev); | ||
813 | snd_soc_dapm_free(socdev); | ||
814 | pcm_err: | 806 | pcm_err: |
815 | return ret; | 807 | return ret; |
816 | } | 808 | } |
@@ -961,21 +953,6 @@ static int wm8580_i2c_remove(struct i2c_client *client) | |||
961 | return 0; | 953 | return 0; |
962 | } | 954 | } |
963 | 955 | ||
964 | #ifdef CONFIG_PM | ||
965 | static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
966 | { | ||
967 | return snd_soc_suspend_device(&client->dev); | ||
968 | } | ||
969 | |||
970 | static int wm8580_i2c_resume(struct i2c_client *client) | ||
971 | { | ||
972 | return snd_soc_resume_device(&client->dev); | ||
973 | } | ||
974 | #else | ||
975 | #define wm8580_i2c_suspend NULL | ||
976 | #define wm8580_i2c_resume NULL | ||
977 | #endif | ||
978 | |||
979 | static const struct i2c_device_id wm8580_i2c_id[] = { | 956 | static const struct i2c_device_id wm8580_i2c_id[] = { |
980 | { "wm8580", 0 }, | 957 | { "wm8580", 0 }, |
981 | { } | 958 | { } |
@@ -989,8 +966,6 @@ static struct i2c_driver wm8580_i2c_driver = { | |||
989 | }, | 966 | }, |
990 | .probe = wm8580_i2c_probe, | 967 | .probe = wm8580_i2c_probe, |
991 | .remove = wm8580_i2c_remove, | 968 | .remove = wm8580_i2c_remove, |
992 | .suspend = wm8580_i2c_suspend, | ||
993 | .resume = wm8580_i2c_resume, | ||
994 | .id_table = wm8580_i2c_id, | 969 | .id_table = wm8580_i2c_id, |
995 | }; | 970 | }; |
996 | #endif | 971 | #endif |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c new file mode 100644 index 000000000000..8ca3812f2f2f --- /dev/null +++ b/sound/soc/codecs/wm8711.c | |||
@@ -0,0 +1,634 @@ | |||
1 | /* | ||
2 | * wm8711.c -- WM8711 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2006 Wolfson Microelectronics | ||
5 | * | ||
6 | * Author: Mike Arthur <linux@wolfsonmicro.com> | ||
7 | * | ||
8 | * Based on wm8731.c by Richard Purdie | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <sound/initval.h> | ||
31 | |||
32 | #include "wm8711.h" | ||
33 | |||
34 | static struct snd_soc_codec *wm8711_codec; | ||
35 | |||
36 | /* codec private data */ | ||
37 | struct wm8711_priv { | ||
38 | struct snd_soc_codec codec; | ||
39 | u16 reg_cache[WM8711_CACHEREGNUM]; | ||
40 | unsigned int sysclk; | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * wm8711 register cache | ||
45 | * We can't read the WM8711 register space when we are | ||
46 | * using 2 wire for device control, so we cache them instead. | ||
47 | * There is no point in caching the reset register | ||
48 | */ | ||
49 | static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { | ||
50 | 0x0079, 0x0079, 0x000a, 0x0008, | ||
51 | 0x009f, 0x000a, 0x0000, 0x0000 | ||
52 | }; | ||
53 | |||
54 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) | ||
55 | |||
56 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | ||
57 | |||
58 | static const struct snd_kcontrol_new wm8711_snd_controls[] = { | ||
59 | |||
60 | SOC_DOUBLE_R_TLV("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V, | ||
61 | 0, 127, 0, out_tlv), | ||
62 | SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V, | ||
63 | 7, 1, 0), | ||
64 | |||
65 | }; | ||
66 | |||
67 | /* Output Mixer */ | ||
68 | static const struct snd_kcontrol_new wm8711_output_mixer_controls[] = { | ||
69 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0), | ||
70 | SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0), | ||
71 | }; | ||
72 | |||
73 | static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = { | ||
74 | SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1, | ||
75 | &wm8711_output_mixer_controls[0], | ||
76 | ARRAY_SIZE(wm8711_output_mixer_controls)), | ||
77 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1), | ||
78 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
79 | SND_SOC_DAPM_OUTPUT("LHPOUT"), | ||
80 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
81 | SND_SOC_DAPM_OUTPUT("RHPOUT"), | ||
82 | }; | ||
83 | |||
84 | static const struct snd_soc_dapm_route intercon[] = { | ||
85 | /* output mixer */ | ||
86 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, | ||
87 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, | ||
88 | |||
89 | /* outputs */ | ||
90 | {"RHPOUT", NULL, "Output Mixer"}, | ||
91 | {"ROUT", NULL, "Output Mixer"}, | ||
92 | {"LHPOUT", NULL, "Output Mixer"}, | ||
93 | {"LOUT", NULL, "Output Mixer"}, | ||
94 | }; | ||
95 | |||
96 | static int wm8711_add_widgets(struct snd_soc_codec *codec) | ||
97 | { | ||
98 | snd_soc_dapm_new_controls(codec, wm8711_dapm_widgets, | ||
99 | ARRAY_SIZE(wm8711_dapm_widgets)); | ||
100 | |||
101 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | struct _coeff_div { | ||
107 | u32 mclk; | ||
108 | u32 rate; | ||
109 | u16 fs; | ||
110 | u8 sr:4; | ||
111 | u8 bosr:1; | ||
112 | u8 usb:1; | ||
113 | }; | ||
114 | |||
115 | /* codec mclk clock divider coefficients */ | ||
116 | static const struct _coeff_div coeff_div[] = { | ||
117 | /* 48k */ | ||
118 | {12288000, 48000, 256, 0x0, 0x0, 0x0}, | ||
119 | {18432000, 48000, 384, 0x0, 0x1, 0x0}, | ||
120 | {12000000, 48000, 250, 0x0, 0x0, 0x1}, | ||
121 | |||
122 | /* 32k */ | ||
123 | {12288000, 32000, 384, 0x6, 0x0, 0x0}, | ||
124 | {18432000, 32000, 576, 0x6, 0x1, 0x0}, | ||
125 | {12000000, 32000, 375, 0x6, 0x0, 0x1}, | ||
126 | |||
127 | /* 8k */ | ||
128 | {12288000, 8000, 1536, 0x3, 0x0, 0x0}, | ||
129 | {18432000, 8000, 2304, 0x3, 0x1, 0x0}, | ||
130 | {11289600, 8000, 1408, 0xb, 0x0, 0x0}, | ||
131 | {16934400, 8000, 2112, 0xb, 0x1, 0x0}, | ||
132 | {12000000, 8000, 1500, 0x3, 0x0, 0x1}, | ||
133 | |||
134 | /* 96k */ | ||
135 | {12288000, 96000, 128, 0x7, 0x0, 0x0}, | ||
136 | {18432000, 96000, 192, 0x7, 0x1, 0x0}, | ||
137 | {12000000, 96000, 125, 0x7, 0x0, 0x1}, | ||
138 | |||
139 | /* 44.1k */ | ||
140 | {11289600, 44100, 256, 0x8, 0x0, 0x0}, | ||
141 | {16934400, 44100, 384, 0x8, 0x1, 0x0}, | ||
142 | {12000000, 44100, 272, 0x8, 0x1, 0x1}, | ||
143 | |||
144 | /* 88.2k */ | ||
145 | {11289600, 88200, 128, 0xf, 0x0, 0x0}, | ||
146 | {16934400, 88200, 192, 0xf, 0x1, 0x0}, | ||
147 | {12000000, 88200, 136, 0xf, 0x1, 0x1}, | ||
148 | }; | ||
149 | |||
150 | static inline int get_coeff(int mclk, int rate) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { | ||
155 | if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) | ||
156 | return i; | ||
157 | } | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int wm8711_hw_params(struct snd_pcm_substream *substream, | ||
162 | struct snd_pcm_hw_params *params, | ||
163 | struct snd_soc_dai *dai) | ||
164 | { | ||
165 | struct snd_soc_codec *codec = dai->codec; | ||
166 | struct wm8711_priv *wm8711 = codec->private_data; | ||
167 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; | ||
168 | int i = get_coeff(wm8711->sysclk, params_rate(params)); | ||
169 | u16 srate = (coeff_div[i].sr << 2) | | ||
170 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; | ||
171 | |||
172 | snd_soc_write(codec, WM8711_SRATE, srate); | ||
173 | |||
174 | /* bit size */ | ||
175 | switch (params_format(params)) { | ||
176 | case SNDRV_PCM_FORMAT_S16_LE: | ||
177 | break; | ||
178 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
179 | iface |= 0x0004; | ||
180 | break; | ||
181 | case SNDRV_PCM_FORMAT_S24_LE: | ||
182 | iface |= 0x0008; | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | snd_soc_write(codec, WM8711_IFACE, iface); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int wm8711_pcm_prepare(struct snd_pcm_substream *substream, | ||
191 | struct snd_soc_dai *dai) | ||
192 | { | ||
193 | struct snd_soc_codec *codec = dai->codec; | ||
194 | |||
195 | /* set active */ | ||
196 | snd_soc_write(codec, WM8711_ACTIVE, 0x0001); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void wm8711_shutdown(struct snd_pcm_substream *substream, | ||
202 | struct snd_soc_dai *dai) | ||
203 | { | ||
204 | struct snd_soc_codec *codec = dai->codec; | ||
205 | |||
206 | /* deactivate */ | ||
207 | if (!codec->active) { | ||
208 | udelay(50); | ||
209 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int wm8711_mute(struct snd_soc_dai *dai, int mute) | ||
214 | { | ||
215 | struct snd_soc_codec *codec = dai->codec; | ||
216 | u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7; | ||
217 | |||
218 | if (mute) | ||
219 | snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8); | ||
220 | else | ||
221 | snd_soc_write(codec, WM8711_APDIGI, mute_reg); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
227 | int clk_id, unsigned int freq, int dir) | ||
228 | { | ||
229 | struct snd_soc_codec *codec = codec_dai->codec; | ||
230 | struct wm8711_priv *wm8711 = codec->private_data; | ||
231 | |||
232 | switch (freq) { | ||
233 | case 11289600: | ||
234 | case 12000000: | ||
235 | case 12288000: | ||
236 | case 16934400: | ||
237 | case 18432000: | ||
238 | wm8711->sysclk = freq; | ||
239 | return 0; | ||
240 | } | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | |||
244 | static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
245 | unsigned int fmt) | ||
246 | { | ||
247 | struct snd_soc_codec *codec = codec_dai->codec; | ||
248 | u16 iface = 0; | ||
249 | |||
250 | /* set master/slave audio interface */ | ||
251 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
252 | case SND_SOC_DAIFMT_CBM_CFM: | ||
253 | iface |= 0x0040; | ||
254 | break; | ||
255 | case SND_SOC_DAIFMT_CBS_CFS: | ||
256 | break; | ||
257 | default: | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | /* interface format */ | ||
262 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
263 | case SND_SOC_DAIFMT_I2S: | ||
264 | iface |= 0x0002; | ||
265 | break; | ||
266 | case SND_SOC_DAIFMT_RIGHT_J: | ||
267 | break; | ||
268 | case SND_SOC_DAIFMT_LEFT_J: | ||
269 | iface |= 0x0001; | ||
270 | break; | ||
271 | case SND_SOC_DAIFMT_DSP_A: | ||
272 | iface |= 0x0003; | ||
273 | break; | ||
274 | case SND_SOC_DAIFMT_DSP_B: | ||
275 | iface |= 0x0013; | ||
276 | break; | ||
277 | default: | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | |||
281 | /* clock inversion */ | ||
282 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
283 | case SND_SOC_DAIFMT_NB_NF: | ||
284 | break; | ||
285 | case SND_SOC_DAIFMT_IB_IF: | ||
286 | iface |= 0x0090; | ||
287 | break; | ||
288 | case SND_SOC_DAIFMT_IB_NF: | ||
289 | iface |= 0x0080; | ||
290 | break; | ||
291 | case SND_SOC_DAIFMT_NB_IF: | ||
292 | iface |= 0x0010; | ||
293 | break; | ||
294 | default: | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | /* set iface */ | ||
299 | snd_soc_write(codec, WM8711_IFACE, iface); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | |||
304 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, | ||
305 | enum snd_soc_bias_level level) | ||
306 | { | ||
307 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; | ||
308 | |||
309 | switch (level) { | ||
310 | case SND_SOC_BIAS_ON: | ||
311 | snd_soc_write(codec, WM8711_PWR, reg); | ||
312 | break; | ||
313 | case SND_SOC_BIAS_PREPARE: | ||
314 | break; | ||
315 | case SND_SOC_BIAS_STANDBY: | ||
316 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); | ||
317 | break; | ||
318 | case SND_SOC_BIAS_OFF: | ||
319 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | ||
320 | snd_soc_write(codec, WM8711_PWR, 0xffff); | ||
321 | break; | ||
322 | } | ||
323 | codec->bias_level = level; | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | #define WM8711_RATES SNDRV_PCM_RATE_8000_96000 | ||
328 | |||
329 | #define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
330 | SNDRV_PCM_FMTBIT_S24_LE) | ||
331 | |||
332 | static struct snd_soc_dai_ops wm8711_ops = { | ||
333 | .prepare = wm8711_pcm_prepare, | ||
334 | .hw_params = wm8711_hw_params, | ||
335 | .shutdown = wm8711_shutdown, | ||
336 | .digital_mute = wm8711_mute, | ||
337 | .set_sysclk = wm8711_set_dai_sysclk, | ||
338 | .set_fmt = wm8711_set_dai_fmt, | ||
339 | }; | ||
340 | |||
341 | struct snd_soc_dai wm8711_dai = { | ||
342 | .name = "WM8711", | ||
343 | .playback = { | ||
344 | .stream_name = "Playback", | ||
345 | .channels_min = 1, | ||
346 | .channels_max = 2, | ||
347 | .rates = WM8711_RATES, | ||
348 | .formats = WM8711_FORMATS, | ||
349 | }, | ||
350 | .ops = &wm8711_ops, | ||
351 | }; | ||
352 | EXPORT_SYMBOL_GPL(wm8711_dai); | ||
353 | |||
354 | static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) | ||
355 | { | ||
356 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
357 | struct snd_soc_codec *codec = socdev->card->codec; | ||
358 | |||
359 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | ||
360 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int wm8711_resume(struct platform_device *pdev) | ||
365 | { | ||
366 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
367 | struct snd_soc_codec *codec = socdev->card->codec; | ||
368 | int i; | ||
369 | u8 data[2]; | ||
370 | u16 *cache = codec->reg_cache; | ||
371 | |||
372 | /* Sync reg_cache with the hardware */ | ||
373 | for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) { | ||
374 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | ||
375 | data[1] = cache[i] & 0x00ff; | ||
376 | codec->hw_write(codec->control_data, data, 2); | ||
377 | } | ||
378 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
379 | wm8711_set_bias_level(codec, codec->suspend_bias_level); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int wm8711_probe(struct platform_device *pdev) | ||
384 | { | ||
385 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
386 | struct snd_soc_codec *codec; | ||
387 | int ret = 0; | ||
388 | |||
389 | if (wm8711_codec == NULL) { | ||
390 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | |||
394 | socdev->card->codec = wm8711_codec; | ||
395 | codec = wm8711_codec; | ||
396 | |||
397 | /* register pcms */ | ||
398 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
399 | if (ret < 0) { | ||
400 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
401 | goto pcm_err; | ||
402 | } | ||
403 | |||
404 | snd_soc_add_controls(codec, wm8711_snd_controls, | ||
405 | ARRAY_SIZE(wm8711_snd_controls)); | ||
406 | wm8711_add_widgets(codec); | ||
407 | |||
408 | return ret; | ||
409 | |||
410 | pcm_err: | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* power down chip */ | ||
415 | static int wm8711_remove(struct platform_device *pdev) | ||
416 | { | ||
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | |||
419 | snd_soc_free_pcms(socdev); | ||
420 | snd_soc_dapm_free(socdev); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | struct snd_soc_codec_device soc_codec_dev_wm8711 = { | ||
426 | .probe = wm8711_probe, | ||
427 | .remove = wm8711_remove, | ||
428 | .suspend = wm8711_suspend, | ||
429 | .resume = wm8711_resume, | ||
430 | }; | ||
431 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); | ||
432 | |||
433 | static int wm8711_register(struct wm8711_priv *wm8711, | ||
434 | enum snd_soc_control_type control) | ||
435 | { | ||
436 | int ret; | ||
437 | struct snd_soc_codec *codec = &wm8711->codec; | ||
438 | u16 reg; | ||
439 | |||
440 | if (wm8711_codec) { | ||
441 | dev_err(codec->dev, "Another WM8711 is registered\n"); | ||
442 | return -EINVAL; | ||
443 | } | ||
444 | |||
445 | mutex_init(&codec->mutex); | ||
446 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
447 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
448 | |||
449 | codec->private_data = wm8711; | ||
450 | codec->name = "WM8711"; | ||
451 | codec->owner = THIS_MODULE; | ||
452 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
453 | codec->set_bias_level = wm8711_set_bias_level; | ||
454 | codec->dai = &wm8711_dai; | ||
455 | codec->num_dai = 1; | ||
456 | codec->reg_cache_size = WM8711_CACHEREGNUM; | ||
457 | codec->reg_cache = &wm8711->reg_cache; | ||
458 | |||
459 | memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); | ||
460 | |||
461 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
462 | if (ret < 0) { | ||
463 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
464 | goto err; | ||
465 | } | ||
466 | |||
467 | ret = wm8711_reset(codec); | ||
468 | if (ret < 0) { | ||
469 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
470 | goto err; | ||
471 | } | ||
472 | |||
473 | wm8711_dai.dev = codec->dev; | ||
474 | |||
475 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
476 | |||
477 | /* Latch the update bits */ | ||
478 | reg = snd_soc_read(codec, WM8711_LOUT1V); | ||
479 | snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100); | ||
480 | reg = snd_soc_read(codec, WM8711_ROUT1V); | ||
481 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); | ||
482 | |||
483 | wm8711_codec = codec; | ||
484 | |||
485 | ret = snd_soc_register_codec(codec); | ||
486 | if (ret != 0) { | ||
487 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
488 | goto err; | ||
489 | } | ||
490 | |||
491 | ret = snd_soc_register_dai(&wm8711_dai); | ||
492 | if (ret != 0) { | ||
493 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
494 | goto err_codec; | ||
495 | } | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | err_codec: | ||
500 | snd_soc_unregister_codec(codec); | ||
501 | err: | ||
502 | kfree(wm8711); | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | static void wm8711_unregister(struct wm8711_priv *wm8711) | ||
507 | { | ||
508 | wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); | ||
509 | snd_soc_unregister_dai(&wm8711_dai); | ||
510 | snd_soc_unregister_codec(&wm8711->codec); | ||
511 | kfree(wm8711); | ||
512 | wm8711_codec = NULL; | ||
513 | } | ||
514 | |||
515 | #if defined(CONFIG_SPI_MASTER) | ||
516 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | ||
517 | { | ||
518 | struct snd_soc_codec *codec; | ||
519 | struct wm8711_priv *wm8711; | ||
520 | |||
521 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | ||
522 | if (wm8711 == NULL) | ||
523 | return -ENOMEM; | ||
524 | |||
525 | codec = &wm8711->codec; | ||
526 | codec->control_data = spi; | ||
527 | codec->dev = &spi->dev; | ||
528 | |||
529 | dev_set_drvdata(&spi->dev, wm8711); | ||
530 | |||
531 | return wm8711_register(wm8711, SND_SOC_SPI); | ||
532 | } | ||
533 | |||
534 | static int __devexit wm8711_spi_remove(struct spi_device *spi) | ||
535 | { | ||
536 | struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); | ||
537 | |||
538 | wm8711_unregister(wm8711); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static struct spi_driver wm8711_spi_driver = { | ||
544 | .driver = { | ||
545 | .name = "wm8711", | ||
546 | .bus = &spi_bus_type, | ||
547 | .owner = THIS_MODULE, | ||
548 | }, | ||
549 | .probe = wm8711_spi_probe, | ||
550 | .remove = __devexit_p(wm8711_spi_remove), | ||
551 | }; | ||
552 | #endif /* CONFIG_SPI_MASTER */ | ||
553 | |||
554 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
555 | static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, | ||
556 | const struct i2c_device_id *id) | ||
557 | { | ||
558 | struct wm8711_priv *wm8711; | ||
559 | struct snd_soc_codec *codec; | ||
560 | |||
561 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | ||
562 | if (wm8711 == NULL) | ||
563 | return -ENOMEM; | ||
564 | |||
565 | codec = &wm8711->codec; | ||
566 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
567 | |||
568 | i2c_set_clientdata(i2c, wm8711); | ||
569 | codec->control_data = i2c; | ||
570 | |||
571 | codec->dev = &i2c->dev; | ||
572 | |||
573 | return wm8711_register(wm8711, SND_SOC_I2C); | ||
574 | } | ||
575 | |||
576 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | ||
577 | { | ||
578 | struct wm8711_priv *wm8711 = i2c_get_clientdata(client); | ||
579 | wm8711_unregister(wm8711); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static const struct i2c_device_id wm8711_i2c_id[] = { | ||
584 | { "wm8711", 0 }, | ||
585 | { } | ||
586 | }; | ||
587 | MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | ||
588 | |||
589 | static struct i2c_driver wm8711_i2c_driver = { | ||
590 | .driver = { | ||
591 | .name = "WM8711 I2C Codec", | ||
592 | .owner = THIS_MODULE, | ||
593 | }, | ||
594 | .probe = wm8711_i2c_probe, | ||
595 | .remove = __devexit_p(wm8711_i2c_remove), | ||
596 | .id_table = wm8711_i2c_id, | ||
597 | }; | ||
598 | #endif | ||
599 | |||
600 | static int __init wm8711_modinit(void) | ||
601 | { | ||
602 | int ret; | ||
603 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
604 | ret = i2c_add_driver(&wm8711_i2c_driver); | ||
605 | if (ret != 0) { | ||
606 | printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", | ||
607 | ret); | ||
608 | } | ||
609 | #endif | ||
610 | #if defined(CONFIG_SPI_MASTER) | ||
611 | ret = spi_register_driver(&wm8711_spi_driver); | ||
612 | if (ret != 0) { | ||
613 | printk(KERN_ERR "Failed to register WM8711 SPI driver: %d\n", | ||
614 | ret); | ||
615 | } | ||
616 | #endif | ||
617 | return 0; | ||
618 | } | ||
619 | module_init(wm8711_modinit); | ||
620 | |||
621 | static void __exit wm8711_exit(void) | ||
622 | { | ||
623 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
624 | i2c_del_driver(&wm8711_i2c_driver); | ||
625 | #endif | ||
626 | #if defined(CONFIG_SPI_MASTER) | ||
627 | spi_unregister_driver(&wm8711_spi_driver); | ||
628 | #endif | ||
629 | } | ||
630 | module_exit(wm8711_exit); | ||
631 | |||
632 | MODULE_DESCRIPTION("ASoC WM8711 driver"); | ||
633 | MODULE_AUTHOR("Mike Arthur"); | ||
634 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h new file mode 100644 index 000000000000..381e84a43816 --- /dev/null +++ b/sound/soc/codecs/wm8711.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * wm8711.h -- WM8711 Soc Audio driver | ||
3 | * | ||
4 | * Copyright 2006 Wolfson Microelectronics | ||
5 | * | ||
6 | * Author: Mike Arthur <linux@wolfsonmicro.com> | ||
7 | * | ||
8 | * Based on wm8731.h | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef _WM8711_H | ||
16 | #define _WM8711_H | ||
17 | |||
18 | /* WM8711 register space */ | ||
19 | |||
20 | #define WM8711_LOUT1V 0x02 | ||
21 | #define WM8711_ROUT1V 0x03 | ||
22 | #define WM8711_APANA 0x04 | ||
23 | #define WM8711_APDIGI 0x05 | ||
24 | #define WM8711_PWR 0x06 | ||
25 | #define WM8711_IFACE 0x07 | ||
26 | #define WM8711_SRATE 0x08 | ||
27 | #define WM8711_ACTIVE 0x09 | ||
28 | #define WM8711_RESET 0x0f | ||
29 | |||
30 | #define WM8711_CACHEREGNUM 8 | ||
31 | |||
32 | #define WM8711_SYSCLK 0 | ||
33 | #define WM8711_DAI 0 | ||
34 | |||
35 | struct wm8711_setup_data { | ||
36 | unsigned short i2c_address; | ||
37 | }; | ||
38 | |||
39 | extern struct snd_soc_dai wm8711_dai; | ||
40 | extern struct snd_soc_codec_device soc_codec_dev_wm8711; | ||
41 | |||
42 | #endif | ||
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c new file mode 100644 index 000000000000..1072621e93fd --- /dev/null +++ b/sound/soc/codecs/wm8727.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * wm8727.c | ||
3 | * | ||
4 | * Created on: 15-Oct-2009 | ||
5 | * Author: neil.jones@imgtec.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Imagination Technologies Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/ac97_codec.h> | ||
23 | #include <sound/initval.h> | ||
24 | #include <sound/soc.h> | ||
25 | |||
26 | #include "wm8727.h" | ||
27 | /* | ||
28 | * Note this is a simple chip with no configuration interface, sample rate is | ||
29 | * determined automatically by examining the Master clock and Bit clock ratios | ||
30 | */ | ||
31 | #define WM8727_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
32 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\ | ||
33 | SNDRV_PCM_RATE_192000) | ||
34 | |||
35 | |||
36 | struct snd_soc_dai wm8727_dai = { | ||
37 | .name = "WM8727", | ||
38 | .playback = { | ||
39 | .stream_name = "Playback", | ||
40 | .channels_min = 2, | ||
41 | .channels_max = 2, | ||
42 | .rates = WM8727_RATES, | ||
43 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
44 | }, | ||
45 | }; | ||
46 | EXPORT_SYMBOL_GPL(wm8727_dai); | ||
47 | |||
48 | static struct snd_soc_codec *wm8727_codec; | ||
49 | |||
50 | static int wm8727_soc_probe(struct platform_device *pdev) | ||
51 | { | ||
52 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
53 | int ret = 0; | ||
54 | |||
55 | BUG_ON(!wm8727_codec); | ||
56 | |||
57 | socdev->card->codec = wm8727_codec; | ||
58 | |||
59 | /* register pcms */ | ||
60 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "wm8727: failed to create pcms\n"); | ||
63 | goto pcm_err; | ||
64 | } | ||
65 | |||
66 | return ret; | ||
67 | |||
68 | pcm_err: | ||
69 | kfree(socdev->card->codec); | ||
70 | socdev->card->codec = NULL; | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static int wm8727_soc_remove(struct platform_device *pdev) | ||
75 | { | ||
76 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
77 | |||
78 | snd_soc_free_pcms(socdev); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | struct snd_soc_codec_device soc_codec_dev_wm8727 = { | ||
84 | .probe = wm8727_soc_probe, | ||
85 | .remove = wm8727_soc_remove, | ||
86 | }; | ||
87 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727); | ||
88 | |||
89 | |||
90 | static __devinit int wm8727_platform_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct snd_soc_codec *codec; | ||
93 | int ret; | ||
94 | |||
95 | if (wm8727_codec) { | ||
96 | dev_err(&pdev->dev, "Another WM8727 is registered\n"); | ||
97 | return -EBUSY; | ||
98 | } | ||
99 | |||
100 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
101 | if (codec == NULL) | ||
102 | return -ENOMEM; | ||
103 | wm8727_codec = codec; | ||
104 | |||
105 | platform_set_drvdata(pdev, codec); | ||
106 | |||
107 | mutex_init(&codec->mutex); | ||
108 | codec->dev = &pdev->dev; | ||
109 | codec->name = "WM8727"; | ||
110 | codec->owner = THIS_MODULE; | ||
111 | codec->dai = &wm8727_dai; | ||
112 | codec->num_dai = 1; | ||
113 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
114 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
115 | |||
116 | wm8727_dai.dev = &pdev->dev; | ||
117 | |||
118 | ret = snd_soc_register_codec(codec); | ||
119 | if (ret != 0) { | ||
120 | dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret); | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | ret = snd_soc_register_dai(&wm8727_dai); | ||
125 | if (ret != 0) { | ||
126 | dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); | ||
127 | goto err_codec; | ||
128 | } | ||
129 | |||
130 | err_codec: | ||
131 | snd_soc_unregister_codec(codec); | ||
132 | err: | ||
133 | kfree(codec); | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | static int __devexit wm8727_platform_remove(struct platform_device *pdev) | ||
138 | { | ||
139 | snd_soc_unregister_dai(&wm8727_dai); | ||
140 | snd_soc_unregister_codec(platform_get_drvdata(pdev)); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static struct platform_driver wm8727_codec_driver = { | ||
145 | .driver = { | ||
146 | .name = "wm8727-codec", | ||
147 | .owner = THIS_MODULE, | ||
148 | }, | ||
149 | |||
150 | .probe = wm8727_platform_probe, | ||
151 | .remove = __devexit_p(wm8727_platform_remove), | ||
152 | }; | ||
153 | |||
154 | static int __init wm8727_init(void) | ||
155 | { | ||
156 | return platform_driver_register(&wm8727_codec_driver); | ||
157 | } | ||
158 | module_init(wm8727_init); | ||
159 | |||
160 | static void __exit wm8727_exit(void) | ||
161 | { | ||
162 | platform_driver_unregister(&wm8727_codec_driver); | ||
163 | } | ||
164 | module_exit(wm8727_exit); | ||
165 | |||
166 | MODULE_DESCRIPTION("ASoC wm8727 driver"); | ||
167 | MODULE_AUTHOR("Neil Jones"); | ||
168 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h new file mode 100644 index 000000000000..ee19aa71bcdc --- /dev/null +++ b/sound/soc/codecs/wm8727.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * wm8727.h | ||
3 | * | ||
4 | * Created on: 15-Oct-2009 | ||
5 | * Author: neil.jones@imgtec.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Imagination Technologies Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #ifndef WM8727_H_ | ||
16 | #define WM8727_H_ | ||
17 | |||
18 | extern struct snd_soc_dai wm8727_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8727; | ||
20 | |||
21 | #endif /* WM8727_H_ */ | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 16e969a762c3..07adc375a706 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -74,8 +75,6 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec) | |||
74 | 75 | ||
75 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 76 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
76 | 77 | ||
77 | snd_soc_dapm_new_widgets(codec); | ||
78 | |||
79 | return 0; | 78 | return 0; |
80 | } | 79 | } |
81 | 80 | ||
@@ -287,17 +286,9 @@ static int wm8728_init(struct snd_soc_device *socdev, | |||
287 | snd_soc_add_controls(codec, wm8728_snd_controls, | 286 | snd_soc_add_controls(codec, wm8728_snd_controls, |
288 | ARRAY_SIZE(wm8728_snd_controls)); | 287 | ARRAY_SIZE(wm8728_snd_controls)); |
289 | wm8728_add_widgets(codec); | 288 | wm8728_add_widgets(codec); |
290 | ret = snd_soc_init_card(socdev); | ||
291 | if (ret < 0) { | ||
292 | printk(KERN_ERR "wm8728: failed to register card\n"); | ||
293 | goto card_err; | ||
294 | } | ||
295 | 289 | ||
296 | return ret; | 290 | return ret; |
297 | 291 | ||
298 | card_err: | ||
299 | snd_soc_free_pcms(socdev); | ||
300 | snd_soc_dapm_free(socdev); | ||
301 | err: | 292 | err: |
302 | kfree(codec->reg_cache); | 293 | kfree(codec->reg_cache); |
303 | return ret; | 294 | return ret; |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index d3fd4f28d96e..e7c6bf163185 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -18,7 +18,9 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
23 | #include <sound/core.h> | 25 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -33,9 +35,18 @@ | |||
33 | static struct snd_soc_codec *wm8731_codec; | 35 | static struct snd_soc_codec *wm8731_codec; |
34 | struct snd_soc_codec_device soc_codec_dev_wm8731; | 36 | struct snd_soc_codec_device soc_codec_dev_wm8731; |
35 | 37 | ||
38 | #define WM8731_NUM_SUPPLIES 4 | ||
39 | static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | ||
40 | "AVDD", | ||
41 | "HPVDD", | ||
42 | "DCVDD", | ||
43 | "DBVDD", | ||
44 | }; | ||
45 | |||
36 | /* codec private data */ | 46 | /* codec private data */ |
37 | struct wm8731_priv { | 47 | struct wm8731_priv { |
38 | struct snd_soc_codec codec; | 48 | struct snd_soc_codec codec; |
49 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; | ||
39 | u16 reg_cache[WM8731_CACHEREGNUM]; | 50 | u16 reg_cache[WM8731_CACHEREGNUM]; |
40 | unsigned int sysclk; | 51 | unsigned int sysclk; |
41 | }; | 52 | }; |
@@ -149,7 +160,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec) | |||
149 | 160 | ||
150 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 161 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
151 | 162 | ||
152 | snd_soc_dapm_new_widgets(codec); | ||
153 | return 0; | 163 | return 0; |
154 | } | 164 | } |
155 | 165 | ||
@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
422 | { | 432 | { |
423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 433 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
424 | struct snd_soc_codec *codec = socdev->card->codec; | 434 | struct snd_soc_codec *codec = socdev->card->codec; |
435 | struct wm8731_priv *wm8731 = codec->private_data; | ||
425 | 436 | ||
426 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | 437 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
427 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 438 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
439 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | ||
440 | wm8731->supplies); | ||
428 | return 0; | 441 | return 0; |
429 | } | 442 | } |
430 | 443 | ||
@@ -432,18 +445,28 @@ static int wm8731_resume(struct platform_device *pdev) | |||
432 | { | 445 | { |
433 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 446 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
434 | struct snd_soc_codec *codec = socdev->card->codec; | 447 | struct snd_soc_codec *codec = socdev->card->codec; |
435 | int i; | 448 | struct wm8731_priv *wm8731 = codec->private_data; |
449 | int i, ret; | ||
436 | u8 data[2]; | 450 | u8 data[2]; |
437 | u16 *cache = codec->reg_cache; | 451 | u16 *cache = codec->reg_cache; |
438 | 452 | ||
453 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
454 | wm8731->supplies); | ||
455 | if (ret != 0) | ||
456 | return ret; | ||
457 | |||
439 | /* Sync reg_cache with the hardware */ | 458 | /* Sync reg_cache with the hardware */ |
440 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { | 459 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { |
460 | if (cache[i] == wm8731_reg[i]) | ||
461 | continue; | ||
462 | |||
441 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | 463 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); |
442 | data[1] = cache[i] & 0x00ff; | 464 | data[1] = cache[i] & 0x00ff; |
443 | codec->hw_write(codec->control_data, data, 2); | 465 | codec->hw_write(codec->control_data, data, 2); |
444 | } | 466 | } |
445 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 467 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
446 | wm8731_set_bias_level(codec, codec->suspend_bias_level); | 468 | wm8731_set_bias_level(codec, codec->suspend_bias_level); |
469 | |||
447 | return 0; | 470 | return 0; |
448 | } | 471 | } |
449 | #else | 472 | #else |
@@ -475,17 +498,9 @@ static int wm8731_probe(struct platform_device *pdev) | |||
475 | snd_soc_add_controls(codec, wm8731_snd_controls, | 498 | snd_soc_add_controls(codec, wm8731_snd_controls, |
476 | ARRAY_SIZE(wm8731_snd_controls)); | 499 | ARRAY_SIZE(wm8731_snd_controls)); |
477 | wm8731_add_widgets(codec); | 500 | wm8731_add_widgets(codec); |
478 | ret = snd_soc_init_card(socdev); | ||
479 | if (ret < 0) { | ||
480 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
481 | goto card_err; | ||
482 | } | ||
483 | 501 | ||
484 | return ret; | 502 | return ret; |
485 | 503 | ||
486 | card_err: | ||
487 | snd_soc_free_pcms(socdev); | ||
488 | snd_soc_dapm_free(socdev); | ||
489 | pcm_err: | 504 | pcm_err: |
490 | return ret; | 505 | return ret; |
491 | } | 506 | } |
@@ -512,7 +527,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | |||
512 | static int wm8731_register(struct wm8731_priv *wm8731, | 527 | static int wm8731_register(struct wm8731_priv *wm8731, |
513 | enum snd_soc_control_type control) | 528 | enum snd_soc_control_type control) |
514 | { | 529 | { |
515 | int ret; | 530 | int ret, i; |
516 | struct snd_soc_codec *codec = &wm8731->codec; | 531 | struct snd_soc_codec *codec = &wm8731->codec; |
517 | 532 | ||
518 | if (wm8731_codec) { | 533 | if (wm8731_codec) { |
@@ -543,10 +558,27 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
543 | goto err; | 558 | goto err; |
544 | } | 559 | } |
545 | 560 | ||
561 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | ||
562 | wm8731->supplies[i].supply = wm8731_supply_names[i]; | ||
563 | |||
564 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies), | ||
565 | wm8731->supplies); | ||
566 | if (ret != 0) { | ||
567 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
568 | goto err; | ||
569 | } | ||
570 | |||
571 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
572 | wm8731->supplies); | ||
573 | if (ret != 0) { | ||
574 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
575 | goto err_regulator_get; | ||
576 | } | ||
577 | |||
546 | ret = wm8731_reset(codec); | 578 | ret = wm8731_reset(codec); |
547 | if (ret < 0) { | 579 | if (ret < 0) { |
548 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 580 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
549 | goto err; | 581 | goto err_regulator_enable; |
550 | } | 582 | } |
551 | 583 | ||
552 | wm8731_dai.dev = codec->dev; | 584 | wm8731_dai.dev = codec->dev; |
@@ -567,7 +599,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
567 | ret = snd_soc_register_codec(codec); | 599 | ret = snd_soc_register_codec(codec); |
568 | if (ret != 0) { | 600 | if (ret != 0) { |
569 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 601 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); |
570 | goto err; | 602 | goto err_regulator_enable; |
571 | } | 603 | } |
572 | 604 | ||
573 | ret = snd_soc_register_dai(&wm8731_dai); | 605 | ret = snd_soc_register_dai(&wm8731_dai); |
@@ -581,6 +613,10 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
581 | 613 | ||
582 | err_codec: | 614 | err_codec: |
583 | snd_soc_unregister_codec(codec); | 615 | snd_soc_unregister_codec(codec); |
616 | err_regulator_enable: | ||
617 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
618 | err_regulator_get: | ||
619 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
584 | err: | 620 | err: |
585 | kfree(wm8731); | 621 | kfree(wm8731); |
586 | return ret; | 622 | return ret; |
@@ -591,6 +627,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) | |||
591 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); | 627 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); |
592 | snd_soc_unregister_dai(&wm8731_dai); | 628 | snd_soc_unregister_dai(&wm8731_dai); |
593 | snd_soc_unregister_codec(&wm8731->codec); | 629 | snd_soc_unregister_codec(&wm8731->codec); |
630 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
631 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
594 | kfree(wm8731); | 632 | kfree(wm8731); |
595 | wm8731_codec = NULL; | 633 | wm8731_codec = NULL; |
596 | } | 634 | } |
@@ -623,21 +661,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi) | |||
623 | return 0; | 661 | return 0; |
624 | } | 662 | } |
625 | 663 | ||
626 | #ifdef CONFIG_PM | ||
627 | static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg) | ||
628 | { | ||
629 | return snd_soc_suspend_device(&spi->dev); | ||
630 | } | ||
631 | |||
632 | static int wm8731_spi_resume(struct spi_device *spi) | ||
633 | { | ||
634 | return snd_soc_resume_device(&spi->dev); | ||
635 | } | ||
636 | #else | ||
637 | #define wm8731_spi_suspend NULL | ||
638 | #define wm8731_spi_resume NULL | ||
639 | #endif | ||
640 | |||
641 | static struct spi_driver wm8731_spi_driver = { | 664 | static struct spi_driver wm8731_spi_driver = { |
642 | .driver = { | 665 | .driver = { |
643 | .name = "wm8731", | 666 | .name = "wm8731", |
@@ -645,8 +668,6 @@ static struct spi_driver wm8731_spi_driver = { | |||
645 | .owner = THIS_MODULE, | 668 | .owner = THIS_MODULE, |
646 | }, | 669 | }, |
647 | .probe = wm8731_spi_probe, | 670 | .probe = wm8731_spi_probe, |
648 | .suspend = wm8731_spi_suspend, | ||
649 | .resume = wm8731_spi_resume, | ||
650 | .remove = __devexit_p(wm8731_spi_remove), | 671 | .remove = __devexit_p(wm8731_spi_remove), |
651 | }; | 672 | }; |
652 | #endif /* CONFIG_SPI_MASTER */ | 673 | #endif /* CONFIG_SPI_MASTER */ |
@@ -679,21 +700,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client) | |||
679 | return 0; | 700 | return 0; |
680 | } | 701 | } |
681 | 702 | ||
682 | #ifdef CONFIG_PM | ||
683 | static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) | ||
684 | { | ||
685 | return snd_soc_suspend_device(&i2c->dev); | ||
686 | } | ||
687 | |||
688 | static int wm8731_i2c_resume(struct i2c_client *i2c) | ||
689 | { | ||
690 | return snd_soc_resume_device(&i2c->dev); | ||
691 | } | ||
692 | #else | ||
693 | #define wm8731_i2c_suspend NULL | ||
694 | #define wm8731_i2c_resume NULL | ||
695 | #endif | ||
696 | |||
697 | static const struct i2c_device_id wm8731_i2c_id[] = { | 703 | static const struct i2c_device_id wm8731_i2c_id[] = { |
698 | { "wm8731", 0 }, | 704 | { "wm8731", 0 }, |
699 | { } | 705 | { } |
@@ -707,8 +713,6 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
707 | }, | 713 | }, |
708 | .probe = wm8731_i2c_probe, | 714 | .probe = wm8731_i2c_probe, |
709 | .remove = __devexit_p(wm8731_i2c_remove), | 715 | .remove = __devexit_p(wm8731_i2c_remove), |
710 | .suspend = wm8731_i2c_suspend, | ||
711 | .resume = wm8731_i2c_resume, | ||
712 | .id_table = wm8731_i2c_id, | 716 | .id_table = wm8731_i2c_id, |
713 | }; | 717 | }; |
714 | #endif | 718 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 4ba1e7e93fb4..2916ed4d3844 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -403,7 +404,6 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec) | |||
403 | 404 | ||
404 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 405 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
405 | 406 | ||
406 | snd_soc_dapm_new_widgets(codec); | ||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
@@ -772,16 +772,8 @@ static int wm8750_init(struct snd_soc_device *socdev, | |||
772 | snd_soc_add_controls(codec, wm8750_snd_controls, | 772 | snd_soc_add_controls(codec, wm8750_snd_controls, |
773 | ARRAY_SIZE(wm8750_snd_controls)); | 773 | ARRAY_SIZE(wm8750_snd_controls)); |
774 | wm8750_add_widgets(codec); | 774 | wm8750_add_widgets(codec); |
775 | ret = snd_soc_init_card(socdev); | ||
776 | if (ret < 0) { | ||
777 | printk(KERN_ERR "wm8750: failed to register card\n"); | ||
778 | goto card_err; | ||
779 | } | ||
780 | return ret; | 775 | return ret; |
781 | 776 | ||
782 | card_err: | ||
783 | snd_soc_free_pcms(socdev); | ||
784 | snd_soc_dapm_free(socdev); | ||
785 | err: | 777 | err: |
786 | kfree(codec->reg_cache); | 778 | kfree(codec->reg_cache); |
787 | return ret; | 779 | return ret; |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 5ad677ce80da..613199a0f799 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/spi/spi.h> | 42 | #include <linux/spi/spi.h> |
43 | #include <linux/slab.h> | ||
43 | #include <sound/core.h> | 44 | #include <sound/core.h> |
44 | #include <sound/pcm.h> | 45 | #include <sound/pcm.h> |
45 | #include <sound/pcm_params.h> | 46 | #include <sound/pcm_params.h> |
@@ -673,7 +674,6 @@ static int wm8753_add_widgets(struct snd_soc_codec *codec) | |||
673 | 674 | ||
674 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 675 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
675 | 676 | ||
676 | snd_soc_dapm_new_widgets(codec); | ||
677 | return 0; | 677 | return 0; |
678 | } | 678 | } |
679 | 679 | ||
@@ -724,8 +724,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
724 | pll_div->k = K; | 724 | pll_div->k = K; |
725 | } | 725 | } |
726 | 726 | ||
727 | static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, | 727 | static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
728 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 728 | int source, unsigned int freq_in, unsigned int freq_out) |
729 | { | 729 | { |
730 | u16 reg, enable; | 730 | u16 reg, enable; |
731 | int offset; | 731 | int offset; |
@@ -1508,10 +1508,6 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) | |||
1508 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1508 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1509 | struct snd_soc_codec *codec = socdev->card->codec; | 1509 | struct snd_soc_codec *codec = socdev->card->codec; |
1510 | 1510 | ||
1511 | /* we only need to suspend if we are a valid card */ | ||
1512 | if (!codec->card) | ||
1513 | return 0; | ||
1514 | |||
1515 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1511 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1516 | return 0; | 1512 | return 0; |
1517 | } | 1513 | } |
@@ -1524,10 +1520,6 @@ static int wm8753_resume(struct platform_device *pdev) | |||
1524 | u8 data[2]; | 1520 | u8 data[2]; |
1525 | u16 *cache = codec->reg_cache; | 1521 | u16 *cache = codec->reg_cache; |
1526 | 1522 | ||
1527 | /* we only need to resume if we are a valid card */ | ||
1528 | if (!codec->card) | ||
1529 | return 0; | ||
1530 | |||
1531 | /* Sync reg_cache with the hardware */ | 1523 | /* Sync reg_cache with the hardware */ |
1532 | for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { | 1524 | for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { |
1533 | if (i + 1 == WM8753_RESET) | 1525 | if (i + 1 == WM8753_RESET) |
@@ -1583,18 +1575,9 @@ static int wm8753_probe(struct platform_device *pdev) | |||
1583 | snd_soc_add_controls(codec, wm8753_snd_controls, | 1575 | snd_soc_add_controls(codec, wm8753_snd_controls, |
1584 | ARRAY_SIZE(wm8753_snd_controls)); | 1576 | ARRAY_SIZE(wm8753_snd_controls)); |
1585 | wm8753_add_widgets(codec); | 1577 | wm8753_add_widgets(codec); |
1586 | ret = snd_soc_init_card(socdev); | ||
1587 | if (ret < 0) { | ||
1588 | printk(KERN_ERR "wm8753: failed to register card\n"); | ||
1589 | goto card_err; | ||
1590 | } | ||
1591 | 1578 | ||
1592 | return 0; | 1579 | return 0; |
1593 | 1580 | ||
1594 | card_err: | ||
1595 | snd_soc_free_pcms(socdev); | ||
1596 | snd_soc_dapm_free(socdev); | ||
1597 | |||
1598 | pcm_err: | 1581 | pcm_err: |
1599 | return ret; | 1582 | return ret; |
1600 | } | 1583 | } |
@@ -1767,21 +1750,6 @@ static int wm8753_i2c_remove(struct i2c_client *client) | |||
1767 | return 0; | 1750 | return 0; |
1768 | } | 1751 | } |
1769 | 1752 | ||
1770 | #ifdef CONFIG_PM | ||
1771 | static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
1772 | { | ||
1773 | return snd_soc_suspend_device(&client->dev); | ||
1774 | } | ||
1775 | |||
1776 | static int wm8753_i2c_resume(struct i2c_client *client) | ||
1777 | { | ||
1778 | return snd_soc_resume_device(&client->dev); | ||
1779 | } | ||
1780 | #else | ||
1781 | #define wm8753_i2c_suspend NULL | ||
1782 | #define wm8753_i2c_resume NULL | ||
1783 | #endif | ||
1784 | |||
1785 | static const struct i2c_device_id wm8753_i2c_id[] = { | 1753 | static const struct i2c_device_id wm8753_i2c_id[] = { |
1786 | { "wm8753", 0 }, | 1754 | { "wm8753", 0 }, |
1787 | { } | 1755 | { } |
@@ -1795,8 +1763,6 @@ static struct i2c_driver wm8753_i2c_driver = { | |||
1795 | }, | 1763 | }, |
1796 | .probe = wm8753_i2c_probe, | 1764 | .probe = wm8753_i2c_probe, |
1797 | .remove = wm8753_i2c_remove, | 1765 | .remove = wm8753_i2c_remove, |
1798 | .suspend = wm8753_i2c_suspend, | ||
1799 | .resume = wm8753_i2c_resume, | ||
1800 | .id_table = wm8753_i2c_id, | 1766 | .id_table = wm8753_i2c_id, |
1801 | }; | 1767 | }; |
1802 | #endif | 1768 | #endif |
@@ -1852,22 +1818,6 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) | |||
1852 | return 0; | 1818 | return 0; |
1853 | } | 1819 | } |
1854 | 1820 | ||
1855 | #ifdef CONFIG_PM | ||
1856 | static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg) | ||
1857 | { | ||
1858 | return snd_soc_suspend_device(&spi->dev); | ||
1859 | } | ||
1860 | |||
1861 | static int wm8753_spi_resume(struct spi_device *spi) | ||
1862 | { | ||
1863 | return snd_soc_resume_device(&spi->dev); | ||
1864 | } | ||
1865 | |||
1866 | #else | ||
1867 | #define wm8753_spi_suspend NULL | ||
1868 | #define wm8753_spi_resume NULL | ||
1869 | #endif | ||
1870 | |||
1871 | static struct spi_driver wm8753_spi_driver = { | 1821 | static struct spi_driver wm8753_spi_driver = { |
1872 | .driver = { | 1822 | .driver = { |
1873 | .name = "wm8753", | 1823 | .name = "wm8753", |
@@ -1876,8 +1826,6 @@ static struct spi_driver wm8753_spi_driver = { | |||
1876 | }, | 1826 | }, |
1877 | .probe = wm8753_spi_probe, | 1827 | .probe = wm8753_spi_probe, |
1878 | .remove = __devexit_p(wm8753_spi_remove), | 1828 | .remove = __devexit_p(wm8753_spi_remove), |
1879 | .suspend = wm8753_spi_suspend, | ||
1880 | .resume = wm8753_spi_resume, | ||
1881 | }; | 1829 | }; |
1882 | #endif | 1830 | #endif |
1883 | 1831 | ||
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index a9829aa26e53..60b1b3e1094b 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -406,6 +407,8 @@ static int wm8776_resume(struct platform_device *pdev) | |||
406 | 407 | ||
407 | /* Sync reg_cache with the hardware */ | 408 | /* Sync reg_cache with the hardware */ |
408 | for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { | 409 | for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { |
410 | if (cache[i] == wm8776_reg[i]) | ||
411 | continue; | ||
409 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | 412 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); |
410 | data[1] = cache[i] & 0x00ff; | 413 | data[1] = cache[i] & 0x00ff; |
411 | codec->hw_write(codec->control_data, data, 2); | 414 | codec->hw_write(codec->control_data, data, 2); |
@@ -447,17 +450,8 @@ static int wm8776_probe(struct platform_device *pdev) | |||
447 | ARRAY_SIZE(wm8776_dapm_widgets)); | 450 | ARRAY_SIZE(wm8776_dapm_widgets)); |
448 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); | 451 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); |
449 | 452 | ||
450 | ret = snd_soc_init_card(socdev); | ||
451 | if (ret < 0) { | ||
452 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
453 | goto card_err; | ||
454 | } | ||
455 | |||
456 | return ret; | 453 | return ret; |
457 | 454 | ||
458 | card_err: | ||
459 | snd_soc_free_pcms(socdev); | ||
460 | snd_soc_dapm_free(socdev); | ||
461 | pcm_err: | 455 | pcm_err: |
462 | return ret; | 456 | return ret; |
463 | } | 457 | } |
@@ -616,21 +610,6 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi) | |||
616 | return 0; | 610 | return 0; |
617 | } | 611 | } |
618 | 612 | ||
619 | #ifdef CONFIG_PM | ||
620 | static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg) | ||
621 | { | ||
622 | return snd_soc_suspend_device(&spi->dev); | ||
623 | } | ||
624 | |||
625 | static int wm8776_spi_resume(struct spi_device *spi) | ||
626 | { | ||
627 | return snd_soc_resume_device(&spi->dev); | ||
628 | } | ||
629 | #else | ||
630 | #define wm8776_spi_suspend NULL | ||
631 | #define wm8776_spi_resume NULL | ||
632 | #endif | ||
633 | |||
634 | static struct spi_driver wm8776_spi_driver = { | 613 | static struct spi_driver wm8776_spi_driver = { |
635 | .driver = { | 614 | .driver = { |
636 | .name = "wm8776", | 615 | .name = "wm8776", |
@@ -638,8 +617,6 @@ static struct spi_driver wm8776_spi_driver = { | |||
638 | .owner = THIS_MODULE, | 617 | .owner = THIS_MODULE, |
639 | }, | 618 | }, |
640 | .probe = wm8776_spi_probe, | 619 | .probe = wm8776_spi_probe, |
641 | .suspend = wm8776_spi_suspend, | ||
642 | .resume = wm8776_spi_resume, | ||
643 | .remove = __devexit_p(wm8776_spi_remove), | 620 | .remove = __devexit_p(wm8776_spi_remove), |
644 | }; | 621 | }; |
645 | #endif /* CONFIG_SPI_MASTER */ | 622 | #endif /* CONFIG_SPI_MASTER */ |
@@ -673,21 +650,6 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client) | |||
673 | return 0; | 650 | return 0; |
674 | } | 651 | } |
675 | 652 | ||
676 | #ifdef CONFIG_PM | ||
677 | static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) | ||
678 | { | ||
679 | return snd_soc_suspend_device(&i2c->dev); | ||
680 | } | ||
681 | |||
682 | static int wm8776_i2c_resume(struct i2c_client *i2c) | ||
683 | { | ||
684 | return snd_soc_resume_device(&i2c->dev); | ||
685 | } | ||
686 | #else | ||
687 | #define wm8776_i2c_suspend NULL | ||
688 | #define wm8776_i2c_resume NULL | ||
689 | #endif | ||
690 | |||
691 | static const struct i2c_device_id wm8776_i2c_id[] = { | 653 | static const struct i2c_device_id wm8776_i2c_id[] = { |
692 | { "wm8776", 0 }, | 654 | { "wm8776", 0 }, |
693 | { } | 655 | { } |
@@ -701,8 +663,6 @@ static struct i2c_driver wm8776_i2c_driver = { | |||
701 | }, | 663 | }, |
702 | .probe = wm8776_i2c_probe, | 664 | .probe = wm8776_i2c_probe, |
703 | .remove = __devexit_p(wm8776_i2c_remove), | 665 | .remove = __devexit_p(wm8776_i2c_remove), |
704 | .suspend = wm8776_i2c_suspend, | ||
705 | .resume = wm8776_i2c_resume, | ||
706 | .id_table = wm8776_i2c_id, | 666 | .id_table = wm8776_i2c_id, |
707 | }; | 667 | }; |
708 | #endif | 668 | #endif |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5e9c855c0036..b7fd96adac64 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 30 | #include <sound/pcm_params.h> |
@@ -199,7 +200,7 @@ static void wm8900_reset(struct snd_soc_codec *codec) | |||
199 | snd_soc_write(codec, WM8900_REG_RESET, 0); | 200 | snd_soc_write(codec, WM8900_REG_RESET, 0); |
200 | 201 | ||
201 | memcpy(codec->reg_cache, wm8900_reg_defaults, | 202 | memcpy(codec->reg_cache, wm8900_reg_defaults, |
202 | sizeof(codec->reg_cache)); | 203 | sizeof(wm8900_reg_defaults)); |
203 | } | 204 | } |
204 | 205 | ||
205 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, | 206 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, |
@@ -618,8 +619,6 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec) | |||
618 | 619 | ||
619 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 620 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
620 | 621 | ||
621 | snd_soc_dapm_new_widgets(codec); | ||
622 | |||
623 | return 0; | 622 | return 0; |
624 | } | 623 | } |
625 | 624 | ||
@@ -814,8 +813,8 @@ reenable: | |||
814 | return 0; | 813 | return 0; |
815 | } | 814 | } |
816 | 815 | ||
817 | static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, | 816 | static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
818 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 817 | int source, unsigned int freq_in, unsigned int freq_out) |
819 | { | 818 | { |
820 | return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); | 819 | return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); |
821 | } | 820 | } |
@@ -1312,21 +1311,6 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client) | |||
1312 | return 0; | 1311 | return 0; |
1313 | } | 1312 | } |
1314 | 1313 | ||
1315 | #ifdef CONFIG_PM | ||
1316 | static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
1317 | { | ||
1318 | return snd_soc_suspend_device(&client->dev); | ||
1319 | } | ||
1320 | |||
1321 | static int wm8900_i2c_resume(struct i2c_client *client) | ||
1322 | { | ||
1323 | return snd_soc_resume_device(&client->dev); | ||
1324 | } | ||
1325 | #else | ||
1326 | #define wm8900_i2c_suspend NULL | ||
1327 | #define wm8900_i2c_resume NULL | ||
1328 | #endif | ||
1329 | |||
1330 | static const struct i2c_device_id wm8900_i2c_id[] = { | 1314 | static const struct i2c_device_id wm8900_i2c_id[] = { |
1331 | { "wm8900", 0 }, | 1315 | { "wm8900", 0 }, |
1332 | { } | 1316 | { } |
@@ -1340,8 +1324,6 @@ static struct i2c_driver wm8900_i2c_driver = { | |||
1340 | }, | 1324 | }, |
1341 | .probe = wm8900_i2c_probe, | 1325 | .probe = wm8900_i2c_probe, |
1342 | .remove = __devexit_p(wm8900_i2c_remove), | 1326 | .remove = __devexit_p(wm8900_i2c_remove), |
1343 | .suspend = wm8900_i2c_suspend, | ||
1344 | .resume = wm8900_i2c_resume, | ||
1345 | .id_table = wm8900_i2c_id, | 1327 | .id_table = wm8900_i2c_id, |
1346 | }; | 1328 | }; |
1347 | 1329 | ||
@@ -1370,17 +1352,6 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1370 | ARRAY_SIZE(wm8900_snd_controls)); | 1352 | ARRAY_SIZE(wm8900_snd_controls)); |
1371 | wm8900_add_widgets(codec); | 1353 | wm8900_add_widgets(codec); |
1372 | 1354 | ||
1373 | ret = snd_soc_init_card(socdev); | ||
1374 | if (ret < 0) { | ||
1375 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
1376 | goto card_err; | ||
1377 | } | ||
1378 | |||
1379 | return ret; | ||
1380 | |||
1381 | card_err: | ||
1382 | snd_soc_free_pcms(socdev); | ||
1383 | snd_soc_dapm_free(socdev); | ||
1384 | pcm_err: | 1355 | pcm_err: |
1385 | return ret; | 1356 | return ret; |
1386 | } | 1357 | } |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fe1307b500cf..fa5f99fde68b 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/slab.h> | ||
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
28 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
@@ -607,7 +608,7 @@ SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1, | |||
607 | SOC_SINGLE("DRC Switch", WM8903_DRC_0, 15, 1, 0), | 608 | SOC_SINGLE("DRC Switch", WM8903_DRC_0, 15, 1, 0), |
608 | SOC_ENUM("DRC Compressor Slope R0", drc_slope_r0), | 609 | SOC_ENUM("DRC Compressor Slope R0", drc_slope_r0), |
609 | SOC_ENUM("DRC Compressor Slope R1", drc_slope_r1), | 610 | SOC_ENUM("DRC Compressor Slope R1", drc_slope_r1), |
610 | SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8903_DRC_3, 5, 124, 1, | 611 | SOC_SINGLE_TLV("DRC Compressor Threshold Volume", WM8903_DRC_3, 5, 124, 1, |
611 | drc_tlv_thresh), | 612 | drc_tlv_thresh), |
612 | SOC_SINGLE_TLV("DRC Volume", WM8903_DRC_3, 0, 30, 1, drc_tlv_amp), | 613 | SOC_SINGLE_TLV("DRC Volume", WM8903_DRC_3, 0, 30, 1, drc_tlv_amp), |
613 | SOC_SINGLE_TLV("DRC Minimum Gain Volume", WM8903_DRC_1, 2, 3, 1, drc_tlv_min), | 614 | SOC_SINGLE_TLV("DRC Minimum Gain Volume", WM8903_DRC_1, 2, 3, 1, drc_tlv_min), |
@@ -617,11 +618,11 @@ SOC_ENUM("DRC Decay Rate", drc_decay), | |||
617 | SOC_ENUM("DRC FF Delay", drc_ff_delay), | 618 | SOC_ENUM("DRC FF Delay", drc_ff_delay), |
618 | SOC_SINGLE("DRC Anticlip Switch", WM8903_DRC_0, 1, 1, 0), | 619 | SOC_SINGLE("DRC Anticlip Switch", WM8903_DRC_0, 1, 1, 0), |
619 | SOC_SINGLE("DRC QR Switch", WM8903_DRC_0, 2, 1, 0), | 620 | SOC_SINGLE("DRC QR Switch", WM8903_DRC_0, 2, 1, 0), |
620 | SOC_SINGLE_TLV("DRC QR Threashold Volume", WM8903_DRC_0, 6, 3, 0, drc_tlv_max), | 621 | SOC_SINGLE_TLV("DRC QR Threshold Volume", WM8903_DRC_0, 6, 3, 0, drc_tlv_max), |
621 | SOC_ENUM("DRC QR Decay Rate", drc_qr_decay), | 622 | SOC_ENUM("DRC QR Decay Rate", drc_qr_decay), |
622 | SOC_SINGLE("DRC Smoothing Switch", WM8903_DRC_0, 3, 1, 0), | 623 | SOC_SINGLE("DRC Smoothing Switch", WM8903_DRC_0, 3, 1, 0), |
623 | SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0), | 624 | SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0), |
624 | SOC_ENUM("DRC Smoothing Threashold", drc_smoothing), | 625 | SOC_ENUM("DRC Smoothing Threshold", drc_smoothing), |
625 | SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), | 626 | SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), |
626 | 627 | ||
627 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, | 628 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, |
@@ -919,8 +920,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) | |||
919 | 920 | ||
920 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 921 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
921 | 922 | ||
922 | snd_soc_dapm_new_widgets(codec); | ||
923 | |||
924 | return 0; | 923 | return 0; |
925 | } | 924 | } |
926 | 925 | ||
@@ -1506,7 +1505,7 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1506 | struct i2c_client *i2c = codec->control_data; | 1505 | struct i2c_client *i2c = codec->control_data; |
1507 | int i; | 1506 | int i; |
1508 | u16 *reg_cache = codec->reg_cache; | 1507 | u16 *reg_cache = codec->reg_cache; |
1509 | u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults), | 1508 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), |
1510 | GFP_KERNEL); | 1509 | GFP_KERNEL); |
1511 | 1510 | ||
1512 | /* Bring the codec back up to standby first to minimise pop/clicks */ | 1511 | /* Bring the codec back up to standby first to minimise pop/clicks */ |
@@ -1518,6 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1518 | for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) | 1517 | for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) |
1519 | if (tmp_cache[i] != reg_cache[i]) | 1518 | if (tmp_cache[i] != reg_cache[i]) |
1520 | snd_soc_write(codec, i, tmp_cache[i]); | 1519 | snd_soc_write(codec, i, tmp_cache[i]); |
1520 | kfree(tmp_cache); | ||
1521 | } else { | 1521 | } else { |
1522 | dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); | 1522 | dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); |
1523 | } | 1523 | } |
@@ -1655,21 +1655,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) | |||
1655 | return 0; | 1655 | return 0; |
1656 | } | 1656 | } |
1657 | 1657 | ||
1658 | #ifdef CONFIG_PM | ||
1659 | static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
1660 | { | ||
1661 | return snd_soc_suspend_device(&client->dev); | ||
1662 | } | ||
1663 | |||
1664 | static int wm8903_i2c_resume(struct i2c_client *client) | ||
1665 | { | ||
1666 | return snd_soc_resume_device(&client->dev); | ||
1667 | } | ||
1668 | #else | ||
1669 | #define wm8903_i2c_suspend NULL | ||
1670 | #define wm8903_i2c_resume NULL | ||
1671 | #endif | ||
1672 | |||
1673 | /* i2c codec control layer */ | 1658 | /* i2c codec control layer */ |
1674 | static const struct i2c_device_id wm8903_i2c_id[] = { | 1659 | static const struct i2c_device_id wm8903_i2c_id[] = { |
1675 | { "wm8903", 0 }, | 1660 | { "wm8903", 0 }, |
@@ -1684,8 +1669,6 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
1684 | }, | 1669 | }, |
1685 | .probe = wm8903_i2c_probe, | 1670 | .probe = wm8903_i2c_probe, |
1686 | .remove = __devexit_p(wm8903_i2c_remove), | 1671 | .remove = __devexit_p(wm8903_i2c_remove), |
1687 | .suspend = wm8903_i2c_suspend, | ||
1688 | .resume = wm8903_i2c_resume, | ||
1689 | .id_table = wm8903_i2c_id, | 1672 | .id_table = wm8903_i2c_id, |
1690 | }; | 1673 | }; |
1691 | 1674 | ||
@@ -1712,17 +1695,8 @@ static int wm8903_probe(struct platform_device *pdev) | |||
1712 | ARRAY_SIZE(wm8903_snd_controls)); | 1695 | ARRAY_SIZE(wm8903_snd_controls)); |
1713 | wm8903_add_widgets(socdev->card->codec); | 1696 | wm8903_add_widgets(socdev->card->codec); |
1714 | 1697 | ||
1715 | ret = snd_soc_init_card(socdev); | ||
1716 | if (ret < 0) { | ||
1717 | dev_err(&pdev->dev, "wm8903: failed to register card\n"); | ||
1718 | goto card_err; | ||
1719 | } | ||
1720 | |||
1721 | return ret; | 1698 | return ret; |
1722 | 1699 | ||
1723 | card_err: | ||
1724 | snd_soc_free_pcms(socdev); | ||
1725 | snd_soc_dapm_free(socdev); | ||
1726 | err: | 1700 | err: |
1727 | return ret; | 1701 | return ret; |
1728 | } | 1702 | } |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c new file mode 100644 index 000000000000..c6f0abcc5711 --- /dev/null +++ b/sound/soc/codecs/wm8904.c | |||
@@ -0,0 +1,2657 @@ | |||
1 | /* | ||
2 | * wm8904.c -- WM8904 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2009 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <sound/wm8904.h> | ||
31 | |||
32 | #include "wm8904.h" | ||
33 | |||
34 | static struct snd_soc_codec *wm8904_codec; | ||
35 | struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
36 | |||
37 | enum wm8904_type { | ||
38 | WM8904, | ||
39 | WM8912, | ||
40 | }; | ||
41 | |||
42 | #define WM8904_NUM_DCS_CHANNELS 4 | ||
43 | |||
44 | #define WM8904_NUM_SUPPLIES 5 | ||
45 | static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { | ||
46 | "DCVDD", | ||
47 | "DBVDD", | ||
48 | "AVDD", | ||
49 | "CPVDD", | ||
50 | "MICVDD", | ||
51 | }; | ||
52 | |||
53 | /* codec private data */ | ||
54 | struct wm8904_priv { | ||
55 | struct snd_soc_codec codec; | ||
56 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; | ||
57 | |||
58 | enum wm8904_type devtype; | ||
59 | |||
60 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; | ||
61 | |||
62 | struct wm8904_pdata *pdata; | ||
63 | |||
64 | int deemph; | ||
65 | |||
66 | /* Platform provided DRC configuration */ | ||
67 | const char **drc_texts; | ||
68 | int drc_cfg; | ||
69 | struct soc_enum drc_enum; | ||
70 | |||
71 | /* Platform provided ReTune mobile configuration */ | ||
72 | int num_retune_mobile_texts; | ||
73 | const char **retune_mobile_texts; | ||
74 | int retune_mobile_cfg; | ||
75 | struct soc_enum retune_mobile_enum; | ||
76 | |||
77 | /* FLL setup */ | ||
78 | int fll_src; | ||
79 | int fll_fref; | ||
80 | int fll_fout; | ||
81 | |||
82 | /* Clocking configuration */ | ||
83 | unsigned int mclk_rate; | ||
84 | int sysclk_src; | ||
85 | unsigned int sysclk_rate; | ||
86 | |||
87 | int tdm_width; | ||
88 | int tdm_slots; | ||
89 | int bclk; | ||
90 | int fs; | ||
91 | |||
92 | /* DC servo configuration - cached offset values */ | ||
93 | int dcs_state[WM8904_NUM_DCS_CHANNELS]; | ||
94 | }; | ||
95 | |||
96 | static const u16 wm8904_reg[WM8904_MAX_REGISTER + 1] = { | ||
97 | 0x8904, /* R0 - SW Reset and ID */ | ||
98 | 0x0000, /* R1 - Revision */ | ||
99 | 0x0000, /* R2 */ | ||
100 | 0x0000, /* R3 */ | ||
101 | 0x0018, /* R4 - Bias Control 0 */ | ||
102 | 0x0000, /* R5 - VMID Control 0 */ | ||
103 | 0x0000, /* R6 - Mic Bias Control 0 */ | ||
104 | 0x0000, /* R7 - Mic Bias Control 1 */ | ||
105 | 0x0001, /* R8 - Analogue DAC 0 */ | ||
106 | 0x9696, /* R9 - mic Filter Control */ | ||
107 | 0x0001, /* R10 - Analogue ADC 0 */ | ||
108 | 0x0000, /* R11 */ | ||
109 | 0x0000, /* R12 - Power Management 0 */ | ||
110 | 0x0000, /* R13 */ | ||
111 | 0x0000, /* R14 - Power Management 2 */ | ||
112 | 0x0000, /* R15 - Power Management 3 */ | ||
113 | 0x0000, /* R16 */ | ||
114 | 0x0000, /* R17 */ | ||
115 | 0x0000, /* R18 - Power Management 6 */ | ||
116 | 0x0000, /* R19 */ | ||
117 | 0x945E, /* R20 - Clock Rates 0 */ | ||
118 | 0x0C05, /* R21 - Clock Rates 1 */ | ||
119 | 0x0006, /* R22 - Clock Rates 2 */ | ||
120 | 0x0000, /* R23 */ | ||
121 | 0x0050, /* R24 - Audio Interface 0 */ | ||
122 | 0x000A, /* R25 - Audio Interface 1 */ | ||
123 | 0x00E4, /* R26 - Audio Interface 2 */ | ||
124 | 0x0040, /* R27 - Audio Interface 3 */ | ||
125 | 0x0000, /* R28 */ | ||
126 | 0x0000, /* R29 */ | ||
127 | 0x00C0, /* R30 - DAC Digital Volume Left */ | ||
128 | 0x00C0, /* R31 - DAC Digital Volume Right */ | ||
129 | 0x0000, /* R32 - DAC Digital 0 */ | ||
130 | 0x0008, /* R33 - DAC Digital 1 */ | ||
131 | 0x0000, /* R34 */ | ||
132 | 0x0000, /* R35 */ | ||
133 | 0x00C0, /* R36 - ADC Digital Volume Left */ | ||
134 | 0x00C0, /* R37 - ADC Digital Volume Right */ | ||
135 | 0x0010, /* R38 - ADC Digital 0 */ | ||
136 | 0x0000, /* R39 - Digital Microphone 0 */ | ||
137 | 0x01AF, /* R40 - DRC 0 */ | ||
138 | 0x3248, /* R41 - DRC 1 */ | ||
139 | 0x0000, /* R42 - DRC 2 */ | ||
140 | 0x0000, /* R43 - DRC 3 */ | ||
141 | 0x0085, /* R44 - Analogue Left Input 0 */ | ||
142 | 0x0085, /* R45 - Analogue Right Input 0 */ | ||
143 | 0x0044, /* R46 - Analogue Left Input 1 */ | ||
144 | 0x0044, /* R47 - Analogue Right Input 1 */ | ||
145 | 0x0000, /* R48 */ | ||
146 | 0x0000, /* R49 */ | ||
147 | 0x0000, /* R50 */ | ||
148 | 0x0000, /* R51 */ | ||
149 | 0x0000, /* R52 */ | ||
150 | 0x0000, /* R53 */ | ||
151 | 0x0000, /* R54 */ | ||
152 | 0x0000, /* R55 */ | ||
153 | 0x0000, /* R56 */ | ||
154 | 0x002D, /* R57 - Analogue OUT1 Left */ | ||
155 | 0x002D, /* R58 - Analogue OUT1 Right */ | ||
156 | 0x0039, /* R59 - Analogue OUT2 Left */ | ||
157 | 0x0039, /* R60 - Analogue OUT2 Right */ | ||
158 | 0x0000, /* R61 - Analogue OUT12 ZC */ | ||
159 | 0x0000, /* R62 */ | ||
160 | 0x0000, /* R63 */ | ||
161 | 0x0000, /* R64 */ | ||
162 | 0x0000, /* R65 */ | ||
163 | 0x0000, /* R66 */ | ||
164 | 0x0000, /* R67 - DC Servo 0 */ | ||
165 | 0x0000, /* R68 - DC Servo 1 */ | ||
166 | 0xAAAA, /* R69 - DC Servo 2 */ | ||
167 | 0x0000, /* R70 */ | ||
168 | 0xAAAA, /* R71 - DC Servo 4 */ | ||
169 | 0xAAAA, /* R72 - DC Servo 5 */ | ||
170 | 0x0000, /* R73 - DC Servo 6 */ | ||
171 | 0x0000, /* R74 - DC Servo 7 */ | ||
172 | 0x0000, /* R75 - DC Servo 8 */ | ||
173 | 0x0000, /* R76 - DC Servo 9 */ | ||
174 | 0x0000, /* R77 - DC Servo Readback 0 */ | ||
175 | 0x0000, /* R78 */ | ||
176 | 0x0000, /* R79 */ | ||
177 | 0x0000, /* R80 */ | ||
178 | 0x0000, /* R81 */ | ||
179 | 0x0000, /* R82 */ | ||
180 | 0x0000, /* R83 */ | ||
181 | 0x0000, /* R84 */ | ||
182 | 0x0000, /* R85 */ | ||
183 | 0x0000, /* R86 */ | ||
184 | 0x0000, /* R87 */ | ||
185 | 0x0000, /* R88 */ | ||
186 | 0x0000, /* R89 */ | ||
187 | 0x0000, /* R90 - Analogue HP 0 */ | ||
188 | 0x0000, /* R91 */ | ||
189 | 0x0000, /* R92 */ | ||
190 | 0x0000, /* R93 */ | ||
191 | 0x0000, /* R94 - Analogue Lineout 0 */ | ||
192 | 0x0000, /* R95 */ | ||
193 | 0x0000, /* R96 */ | ||
194 | 0x0000, /* R97 */ | ||
195 | 0x0000, /* R98 - Charge Pump 0 */ | ||
196 | 0x0000, /* R99 */ | ||
197 | 0x0000, /* R100 */ | ||
198 | 0x0000, /* R101 */ | ||
199 | 0x0000, /* R102 */ | ||
200 | 0x0000, /* R103 */ | ||
201 | 0x0004, /* R104 - Class W 0 */ | ||
202 | 0x0000, /* R105 */ | ||
203 | 0x0000, /* R106 */ | ||
204 | 0x0000, /* R107 */ | ||
205 | 0x0000, /* R108 - Write Sequencer 0 */ | ||
206 | 0x0000, /* R109 - Write Sequencer 1 */ | ||
207 | 0x0000, /* R110 - Write Sequencer 2 */ | ||
208 | 0x0000, /* R111 - Write Sequencer 3 */ | ||
209 | 0x0000, /* R112 - Write Sequencer 4 */ | ||
210 | 0x0000, /* R113 */ | ||
211 | 0x0000, /* R114 */ | ||
212 | 0x0000, /* R115 */ | ||
213 | 0x0000, /* R116 - FLL Control 1 */ | ||
214 | 0x0007, /* R117 - FLL Control 2 */ | ||
215 | 0x0000, /* R118 - FLL Control 3 */ | ||
216 | 0x2EE0, /* R119 - FLL Control 4 */ | ||
217 | 0x0004, /* R120 - FLL Control 5 */ | ||
218 | 0x0014, /* R121 - GPIO Control 1 */ | ||
219 | 0x0010, /* R122 - GPIO Control 2 */ | ||
220 | 0x0010, /* R123 - GPIO Control 3 */ | ||
221 | 0x0000, /* R124 - GPIO Control 4 */ | ||
222 | 0x0000, /* R125 */ | ||
223 | 0x0000, /* R126 - Digital Pulls */ | ||
224 | 0x0000, /* R127 - Interrupt Status */ | ||
225 | 0xFFFF, /* R128 - Interrupt Status Mask */ | ||
226 | 0x0000, /* R129 - Interrupt Polarity */ | ||
227 | 0x0000, /* R130 - Interrupt Debounce */ | ||
228 | 0x0000, /* R131 */ | ||
229 | 0x0000, /* R132 */ | ||
230 | 0x0000, /* R133 */ | ||
231 | 0x0000, /* R134 - EQ1 */ | ||
232 | 0x000C, /* R135 - EQ2 */ | ||
233 | 0x000C, /* R136 - EQ3 */ | ||
234 | 0x000C, /* R137 - EQ4 */ | ||
235 | 0x000C, /* R138 - EQ5 */ | ||
236 | 0x000C, /* R139 - EQ6 */ | ||
237 | 0x0FCA, /* R140 - EQ7 */ | ||
238 | 0x0400, /* R141 - EQ8 */ | ||
239 | 0x00D8, /* R142 - EQ9 */ | ||
240 | 0x1EB5, /* R143 - EQ10 */ | ||
241 | 0xF145, /* R144 - EQ11 */ | ||
242 | 0x0B75, /* R145 - EQ12 */ | ||
243 | 0x01C5, /* R146 - EQ13 */ | ||
244 | 0x1C58, /* R147 - EQ14 */ | ||
245 | 0xF373, /* R148 - EQ15 */ | ||
246 | 0x0A54, /* R149 - EQ16 */ | ||
247 | 0x0558, /* R150 - EQ17 */ | ||
248 | 0x168E, /* R151 - EQ18 */ | ||
249 | 0xF829, /* R152 - EQ19 */ | ||
250 | 0x07AD, /* R153 - EQ20 */ | ||
251 | 0x1103, /* R154 - EQ21 */ | ||
252 | 0x0564, /* R155 - EQ22 */ | ||
253 | 0x0559, /* R156 - EQ23 */ | ||
254 | 0x4000, /* R157 - EQ24 */ | ||
255 | 0x0000, /* R158 */ | ||
256 | 0x0000, /* R159 */ | ||
257 | 0x0000, /* R160 */ | ||
258 | 0x0000, /* R161 - Control Interface Test 1 */ | ||
259 | 0x0000, /* R162 */ | ||
260 | 0x0000, /* R163 */ | ||
261 | 0x0000, /* R164 */ | ||
262 | 0x0000, /* R165 */ | ||
263 | 0x0000, /* R166 */ | ||
264 | 0x0000, /* R167 */ | ||
265 | 0x0000, /* R168 */ | ||
266 | 0x0000, /* R169 */ | ||
267 | 0x0000, /* R170 */ | ||
268 | 0x0000, /* R171 */ | ||
269 | 0x0000, /* R172 */ | ||
270 | 0x0000, /* R173 */ | ||
271 | 0x0000, /* R174 */ | ||
272 | 0x0000, /* R175 */ | ||
273 | 0x0000, /* R176 */ | ||
274 | 0x0000, /* R177 */ | ||
275 | 0x0000, /* R178 */ | ||
276 | 0x0000, /* R179 */ | ||
277 | 0x0000, /* R180 */ | ||
278 | 0x0000, /* R181 */ | ||
279 | 0x0000, /* R182 */ | ||
280 | 0x0000, /* R183 */ | ||
281 | 0x0000, /* R184 */ | ||
282 | 0x0000, /* R185 */ | ||
283 | 0x0000, /* R186 */ | ||
284 | 0x0000, /* R187 */ | ||
285 | 0x0000, /* R188 */ | ||
286 | 0x0000, /* R189 */ | ||
287 | 0x0000, /* R190 */ | ||
288 | 0x0000, /* R191 */ | ||
289 | 0x0000, /* R192 */ | ||
290 | 0x0000, /* R193 */ | ||
291 | 0x0000, /* R194 */ | ||
292 | 0x0000, /* R195 */ | ||
293 | 0x0000, /* R196 */ | ||
294 | 0x0000, /* R197 */ | ||
295 | 0x0000, /* R198 */ | ||
296 | 0x0000, /* R199 */ | ||
297 | 0x0000, /* R200 */ | ||
298 | 0x0000, /* R201 */ | ||
299 | 0x0000, /* R202 */ | ||
300 | 0x0000, /* R203 */ | ||
301 | 0x0000, /* R204 - Analogue Output Bias 0 */ | ||
302 | 0x0000, /* R205 */ | ||
303 | 0x0000, /* R206 */ | ||
304 | 0x0000, /* R207 */ | ||
305 | 0x0000, /* R208 */ | ||
306 | 0x0000, /* R209 */ | ||
307 | 0x0000, /* R210 */ | ||
308 | 0x0000, /* R211 */ | ||
309 | 0x0000, /* R212 */ | ||
310 | 0x0000, /* R213 */ | ||
311 | 0x0000, /* R214 */ | ||
312 | 0x0000, /* R215 */ | ||
313 | 0x0000, /* R216 */ | ||
314 | 0x0000, /* R217 */ | ||
315 | 0x0000, /* R218 */ | ||
316 | 0x0000, /* R219 */ | ||
317 | 0x0000, /* R220 */ | ||
318 | 0x0000, /* R221 */ | ||
319 | 0x0000, /* R222 */ | ||
320 | 0x0000, /* R223 */ | ||
321 | 0x0000, /* R224 */ | ||
322 | 0x0000, /* R225 */ | ||
323 | 0x0000, /* R226 */ | ||
324 | 0x0000, /* R227 */ | ||
325 | 0x0000, /* R228 */ | ||
326 | 0x0000, /* R229 */ | ||
327 | 0x0000, /* R230 */ | ||
328 | 0x0000, /* R231 */ | ||
329 | 0x0000, /* R232 */ | ||
330 | 0x0000, /* R233 */ | ||
331 | 0x0000, /* R234 */ | ||
332 | 0x0000, /* R235 */ | ||
333 | 0x0000, /* R236 */ | ||
334 | 0x0000, /* R237 */ | ||
335 | 0x0000, /* R238 */ | ||
336 | 0x0000, /* R239 */ | ||
337 | 0x0000, /* R240 */ | ||
338 | 0x0000, /* R241 */ | ||
339 | 0x0000, /* R242 */ | ||
340 | 0x0000, /* R243 */ | ||
341 | 0x0000, /* R244 */ | ||
342 | 0x0000, /* R245 */ | ||
343 | 0x0000, /* R246 */ | ||
344 | 0x0000, /* R247 - FLL NCO Test 0 */ | ||
345 | 0x0019, /* R248 - FLL NCO Test 1 */ | ||
346 | }; | ||
347 | |||
348 | static struct { | ||
349 | int readable; | ||
350 | int writable; | ||
351 | int vol; | ||
352 | } wm8904_access[] = { | ||
353 | { 0xFFFF, 0xFFFF, 1 }, /* R0 - SW Reset and ID */ | ||
354 | { 0x0000, 0x0000, 0 }, /* R1 - Revision */ | ||
355 | { 0x0000, 0x0000, 0 }, /* R2 */ | ||
356 | { 0x0000, 0x0000, 0 }, /* R3 */ | ||
357 | { 0x001F, 0x001F, 0 }, /* R4 - Bias Control 0 */ | ||
358 | { 0x0047, 0x0047, 0 }, /* R5 - VMID Control 0 */ | ||
359 | { 0x007F, 0x007F, 0 }, /* R6 - Mic Bias Control 0 */ | ||
360 | { 0xC007, 0xC007, 0 }, /* R7 - Mic Bias Control 1 */ | ||
361 | { 0x001E, 0x001E, 0 }, /* R8 - Analogue DAC 0 */ | ||
362 | { 0xFFFF, 0xFFFF, 0 }, /* R9 - mic Filter Control */ | ||
363 | { 0x0001, 0x0001, 0 }, /* R10 - Analogue ADC 0 */ | ||
364 | { 0x0000, 0x0000, 0 }, /* R11 */ | ||
365 | { 0x0003, 0x0003, 0 }, /* R12 - Power Management 0 */ | ||
366 | { 0x0000, 0x0000, 0 }, /* R13 */ | ||
367 | { 0x0003, 0x0003, 0 }, /* R14 - Power Management 2 */ | ||
368 | { 0x0003, 0x0003, 0 }, /* R15 - Power Management 3 */ | ||
369 | { 0x0000, 0x0000, 0 }, /* R16 */ | ||
370 | { 0x0000, 0x0000, 0 }, /* R17 */ | ||
371 | { 0x000F, 0x000F, 0 }, /* R18 - Power Management 6 */ | ||
372 | { 0x0000, 0x0000, 0 }, /* R19 */ | ||
373 | { 0x7001, 0x7001, 0 }, /* R20 - Clock Rates 0 */ | ||
374 | { 0x3C07, 0x3C07, 0 }, /* R21 - Clock Rates 1 */ | ||
375 | { 0xD00F, 0xD00F, 0 }, /* R22 - Clock Rates 2 */ | ||
376 | { 0x0000, 0x0000, 0 }, /* R23 */ | ||
377 | { 0x1FFF, 0x1FFF, 0 }, /* R24 - Audio Interface 0 */ | ||
378 | { 0x3DDF, 0x3DDF, 0 }, /* R25 - Audio Interface 1 */ | ||
379 | { 0x0F1F, 0x0F1F, 0 }, /* R26 - Audio Interface 2 */ | ||
380 | { 0x0FFF, 0x0FFF, 0 }, /* R27 - Audio Interface 3 */ | ||
381 | { 0x0000, 0x0000, 0 }, /* R28 */ | ||
382 | { 0x0000, 0x0000, 0 }, /* R29 */ | ||
383 | { 0x00FF, 0x01FF, 0 }, /* R30 - DAC Digital Volume Left */ | ||
384 | { 0x00FF, 0x01FF, 0 }, /* R31 - DAC Digital Volume Right */ | ||
385 | { 0x0FFF, 0x0FFF, 0 }, /* R32 - DAC Digital 0 */ | ||
386 | { 0x1E4E, 0x1E4E, 0 }, /* R33 - DAC Digital 1 */ | ||
387 | { 0x0000, 0x0000, 0 }, /* R34 */ | ||
388 | { 0x0000, 0x0000, 0 }, /* R35 */ | ||
389 | { 0x00FF, 0x01FF, 0 }, /* R36 - ADC Digital Volume Left */ | ||
390 | { 0x00FF, 0x01FF, 0 }, /* R37 - ADC Digital Volume Right */ | ||
391 | { 0x0073, 0x0073, 0 }, /* R38 - ADC Digital 0 */ | ||
392 | { 0x1800, 0x1800, 0 }, /* R39 - Digital Microphone 0 */ | ||
393 | { 0xDFEF, 0xDFEF, 0 }, /* R40 - DRC 0 */ | ||
394 | { 0xFFFF, 0xFFFF, 0 }, /* R41 - DRC 1 */ | ||
395 | { 0x003F, 0x003F, 0 }, /* R42 - DRC 2 */ | ||
396 | { 0x07FF, 0x07FF, 0 }, /* R43 - DRC 3 */ | ||
397 | { 0x009F, 0x009F, 0 }, /* R44 - Analogue Left Input 0 */ | ||
398 | { 0x009F, 0x009F, 0 }, /* R45 - Analogue Right Input 0 */ | ||
399 | { 0x007F, 0x007F, 0 }, /* R46 - Analogue Left Input 1 */ | ||
400 | { 0x007F, 0x007F, 0 }, /* R47 - Analogue Right Input 1 */ | ||
401 | { 0x0000, 0x0000, 0 }, /* R48 */ | ||
402 | { 0x0000, 0x0000, 0 }, /* R49 */ | ||
403 | { 0x0000, 0x0000, 0 }, /* R50 */ | ||
404 | { 0x0000, 0x0000, 0 }, /* R51 */ | ||
405 | { 0x0000, 0x0000, 0 }, /* R52 */ | ||
406 | { 0x0000, 0x0000, 0 }, /* R53 */ | ||
407 | { 0x0000, 0x0000, 0 }, /* R54 */ | ||
408 | { 0x0000, 0x0000, 0 }, /* R55 */ | ||
409 | { 0x0000, 0x0000, 0 }, /* R56 */ | ||
410 | { 0x017F, 0x01FF, 0 }, /* R57 - Analogue OUT1 Left */ | ||
411 | { 0x017F, 0x01FF, 0 }, /* R58 - Analogue OUT1 Right */ | ||
412 | { 0x017F, 0x01FF, 0 }, /* R59 - Analogue OUT2 Left */ | ||
413 | { 0x017F, 0x01FF, 0 }, /* R60 - Analogue OUT2 Right */ | ||
414 | { 0x000F, 0x000F, 0 }, /* R61 - Analogue OUT12 ZC */ | ||
415 | { 0x0000, 0x0000, 0 }, /* R62 */ | ||
416 | { 0x0000, 0x0000, 0 }, /* R63 */ | ||
417 | { 0x0000, 0x0000, 0 }, /* R64 */ | ||
418 | { 0x0000, 0x0000, 0 }, /* R65 */ | ||
419 | { 0x0000, 0x0000, 0 }, /* R66 */ | ||
420 | { 0x000F, 0x000F, 0 }, /* R67 - DC Servo 0 */ | ||
421 | { 0xFFFF, 0xFFFF, 1 }, /* R68 - DC Servo 1 */ | ||
422 | { 0x0F0F, 0x0F0F, 0 }, /* R69 - DC Servo 2 */ | ||
423 | { 0x0000, 0x0000, 0 }, /* R70 */ | ||
424 | { 0x007F, 0x007F, 0 }, /* R71 - DC Servo 4 */ | ||
425 | { 0x007F, 0x007F, 0 }, /* R72 - DC Servo 5 */ | ||
426 | { 0x00FF, 0x00FF, 1 }, /* R73 - DC Servo 6 */ | ||
427 | { 0x00FF, 0x00FF, 1 }, /* R74 - DC Servo 7 */ | ||
428 | { 0x00FF, 0x00FF, 1 }, /* R75 - DC Servo 8 */ | ||
429 | { 0x00FF, 0x00FF, 1 }, /* R76 - DC Servo 9 */ | ||
430 | { 0x0FFF, 0x0000, 1 }, /* R77 - DC Servo Readback 0 */ | ||
431 | { 0x0000, 0x0000, 0 }, /* R78 */ | ||
432 | { 0x0000, 0x0000, 0 }, /* R79 */ | ||
433 | { 0x0000, 0x0000, 0 }, /* R80 */ | ||
434 | { 0x0000, 0x0000, 0 }, /* R81 */ | ||
435 | { 0x0000, 0x0000, 0 }, /* R82 */ | ||
436 | { 0x0000, 0x0000, 0 }, /* R83 */ | ||
437 | { 0x0000, 0x0000, 0 }, /* R84 */ | ||
438 | { 0x0000, 0x0000, 0 }, /* R85 */ | ||
439 | { 0x0000, 0x0000, 0 }, /* R86 */ | ||
440 | { 0x0000, 0x0000, 0 }, /* R87 */ | ||
441 | { 0x0000, 0x0000, 0 }, /* R88 */ | ||
442 | { 0x0000, 0x0000, 0 }, /* R89 */ | ||
443 | { 0x00FF, 0x00FF, 0 }, /* R90 - Analogue HP 0 */ | ||
444 | { 0x0000, 0x0000, 0 }, /* R91 */ | ||
445 | { 0x0000, 0x0000, 0 }, /* R92 */ | ||
446 | { 0x0000, 0x0000, 0 }, /* R93 */ | ||
447 | { 0x00FF, 0x00FF, 0 }, /* R94 - Analogue Lineout 0 */ | ||
448 | { 0x0000, 0x0000, 0 }, /* R95 */ | ||
449 | { 0x0000, 0x0000, 0 }, /* R96 */ | ||
450 | { 0x0000, 0x0000, 0 }, /* R97 */ | ||
451 | { 0x0001, 0x0001, 0 }, /* R98 - Charge Pump 0 */ | ||
452 | { 0x0000, 0x0000, 0 }, /* R99 */ | ||
453 | { 0x0000, 0x0000, 0 }, /* R100 */ | ||
454 | { 0x0000, 0x0000, 0 }, /* R101 */ | ||
455 | { 0x0000, 0x0000, 0 }, /* R102 */ | ||
456 | { 0x0000, 0x0000, 0 }, /* R103 */ | ||
457 | { 0x0001, 0x0001, 0 }, /* R104 - Class W 0 */ | ||
458 | { 0x0000, 0x0000, 0 }, /* R105 */ | ||
459 | { 0x0000, 0x0000, 0 }, /* R106 */ | ||
460 | { 0x0000, 0x0000, 0 }, /* R107 */ | ||
461 | { 0x011F, 0x011F, 0 }, /* R108 - Write Sequencer 0 */ | ||
462 | { 0x7FFF, 0x7FFF, 0 }, /* R109 - Write Sequencer 1 */ | ||
463 | { 0x4FFF, 0x4FFF, 0 }, /* R110 - Write Sequencer 2 */ | ||
464 | { 0x003F, 0x033F, 0 }, /* R111 - Write Sequencer 3 */ | ||
465 | { 0x03F1, 0x0000, 0 }, /* R112 - Write Sequencer 4 */ | ||
466 | { 0x0000, 0x0000, 0 }, /* R113 */ | ||
467 | { 0x0000, 0x0000, 0 }, /* R114 */ | ||
468 | { 0x0000, 0x0000, 0 }, /* R115 */ | ||
469 | { 0x0007, 0x0007, 0 }, /* R116 - FLL Control 1 */ | ||
470 | { 0x3F77, 0x3F77, 0 }, /* R117 - FLL Control 2 */ | ||
471 | { 0xFFFF, 0xFFFF, 0 }, /* R118 - FLL Control 3 */ | ||
472 | { 0x7FEF, 0x7FEF, 0 }, /* R119 - FLL Control 4 */ | ||
473 | { 0x001B, 0x001B, 0 }, /* R120 - FLL Control 5 */ | ||
474 | { 0x003F, 0x003F, 0 }, /* R121 - GPIO Control 1 */ | ||
475 | { 0x003F, 0x003F, 0 }, /* R122 - GPIO Control 2 */ | ||
476 | { 0x003F, 0x003F, 0 }, /* R123 - GPIO Control 3 */ | ||
477 | { 0x038F, 0x038F, 0 }, /* R124 - GPIO Control 4 */ | ||
478 | { 0x0000, 0x0000, 0 }, /* R125 */ | ||
479 | { 0x00FF, 0x00FF, 0 }, /* R126 - Digital Pulls */ | ||
480 | { 0x07FF, 0x03FF, 1 }, /* R127 - Interrupt Status */ | ||
481 | { 0x03FF, 0x03FF, 0 }, /* R128 - Interrupt Status Mask */ | ||
482 | { 0x03FF, 0x03FF, 0 }, /* R129 - Interrupt Polarity */ | ||
483 | { 0x03FF, 0x03FF, 0 }, /* R130 - Interrupt Debounce */ | ||
484 | { 0x0000, 0x0000, 0 }, /* R131 */ | ||
485 | { 0x0000, 0x0000, 0 }, /* R132 */ | ||
486 | { 0x0000, 0x0000, 0 }, /* R133 */ | ||
487 | { 0x0001, 0x0001, 0 }, /* R134 - EQ1 */ | ||
488 | { 0x001F, 0x001F, 0 }, /* R135 - EQ2 */ | ||
489 | { 0x001F, 0x001F, 0 }, /* R136 - EQ3 */ | ||
490 | { 0x001F, 0x001F, 0 }, /* R137 - EQ4 */ | ||
491 | { 0x001F, 0x001F, 0 }, /* R138 - EQ5 */ | ||
492 | { 0x001F, 0x001F, 0 }, /* R139 - EQ6 */ | ||
493 | { 0xFFFF, 0xFFFF, 0 }, /* R140 - EQ7 */ | ||
494 | { 0xFFFF, 0xFFFF, 0 }, /* R141 - EQ8 */ | ||
495 | { 0xFFFF, 0xFFFF, 0 }, /* R142 - EQ9 */ | ||
496 | { 0xFFFF, 0xFFFF, 0 }, /* R143 - EQ10 */ | ||
497 | { 0xFFFF, 0xFFFF, 0 }, /* R144 - EQ11 */ | ||
498 | { 0xFFFF, 0xFFFF, 0 }, /* R145 - EQ12 */ | ||
499 | { 0xFFFF, 0xFFFF, 0 }, /* R146 - EQ13 */ | ||
500 | { 0xFFFF, 0xFFFF, 0 }, /* R147 - EQ14 */ | ||
501 | { 0xFFFF, 0xFFFF, 0 }, /* R148 - EQ15 */ | ||
502 | { 0xFFFF, 0xFFFF, 0 }, /* R149 - EQ16 */ | ||
503 | { 0xFFFF, 0xFFFF, 0 }, /* R150 - EQ17 */ | ||
504 | { 0xFFFF, 0xFFFF, 0 }, /* R151wm8523_dai - EQ18 */ | ||
505 | { 0xFFFF, 0xFFFF, 0 }, /* R152 - EQ19 */ | ||
506 | { 0xFFFF, 0xFFFF, 0 }, /* R153 - EQ20 */ | ||
507 | { 0xFFFF, 0xFFFF, 0 }, /* R154 - EQ21 */ | ||
508 | { 0xFFFF, 0xFFFF, 0 }, /* R155 - EQ22 */ | ||
509 | { 0xFFFF, 0xFFFF, 0 }, /* R156 - EQ23 */ | ||
510 | { 0xFFFF, 0xFFFF, 0 }, /* R157 - EQ24 */ | ||
511 | { 0x0000, 0x0000, 0 }, /* R158 */ | ||
512 | { 0x0000, 0x0000, 0 }, /* R159 */ | ||
513 | { 0x0000, 0x0000, 0 }, /* R160 */ | ||
514 | { 0x0002, 0x0002, 0 }, /* R161 - Control Interface Test 1 */ | ||
515 | { 0x0000, 0x0000, 0 }, /* R162 */ | ||
516 | { 0x0000, 0x0000, 0 }, /* R163 */ | ||
517 | { 0x0000, 0x0000, 0 }, /* R164 */ | ||
518 | { 0x0000, 0x0000, 0 }, /* R165 */ | ||
519 | { 0x0000, 0x0000, 0 }, /* R166 */ | ||
520 | { 0x0000, 0x0000, 0 }, /* R167 */ | ||
521 | { 0x0000, 0x0000, 0 }, /* R168 */ | ||
522 | { 0x0000, 0x0000, 0 }, /* R169 */ | ||
523 | { 0x0000, 0x0000, 0 }, /* R170 */ | ||
524 | { 0x0000, 0x0000, 0 }, /* R171 */ | ||
525 | { 0x0000, 0x0000, 0 }, /* R172 */ | ||
526 | { 0x0000, 0x0000, 0 }, /* R173 */ | ||
527 | { 0x0000, 0x0000, 0 }, /* R174 */ | ||
528 | { 0x0000, 0x0000, 0 }, /* R175 */ | ||
529 | { 0x0000, 0x0000, 0 }, /* R176 */ | ||
530 | { 0x0000, 0x0000, 0 }, /* R177 */ | ||
531 | { 0x0000, 0x0000, 0 }, /* R178 */ | ||
532 | { 0x0000, 0x0000, 0 }, /* R179 */ | ||
533 | { 0x0000, 0x0000, 0 }, /* R180 */ | ||
534 | { 0x0000, 0x0000, 0 }, /* R181 */ | ||
535 | { 0x0000, 0x0000, 0 }, /* R182 */ | ||
536 | { 0x0000, 0x0000, 0 }, /* R183 */ | ||
537 | { 0x0000, 0x0000, 0 }, /* R184 */ | ||
538 | { 0x0000, 0x0000, 0 }, /* R185 */ | ||
539 | { 0x0000, 0x0000, 0 }, /* R186 */ | ||
540 | { 0x0000, 0x0000, 0 }, /* R187 */ | ||
541 | { 0x0000, 0x0000, 0 }, /* R188 */ | ||
542 | { 0x0000, 0x0000, 0 }, /* R189 */ | ||
543 | { 0x0000, 0x0000, 0 }, /* R190 */ | ||
544 | { 0x0000, 0x0000, 0 }, /* R191 */ | ||
545 | { 0x0000, 0x0000, 0 }, /* R192 */ | ||
546 | { 0x0000, 0x0000, 0 }, /* R193 */ | ||
547 | { 0x0000, 0x0000, 0 }, /* R194 */ | ||
548 | { 0x0000, 0x0000, 0 }, /* R195 */ | ||
549 | { 0x0000, 0x0000, 0 }, /* R196 */ | ||
550 | { 0x0000, 0x0000, 0 }, /* R197 */ | ||
551 | { 0x0000, 0x0000, 0 }, /* R198 */ | ||
552 | { 0x0000, 0x0000, 0 }, /* R199 */ | ||
553 | { 0x0000, 0x0000, 0 }, /* R200 */ | ||
554 | { 0x0000, 0x0000, 0 }, /* R201 */ | ||
555 | { 0x0000, 0x0000, 0 }, /* R202 */ | ||
556 | { 0x0000, 0x0000, 0 }, /* R203 */ | ||
557 | { 0x0070, 0x0070, 0 }, /* R204 - Analogue Output Bias 0 */ | ||
558 | { 0x0000, 0x0000, 0 }, /* R205 */ | ||
559 | { 0x0000, 0x0000, 0 }, /* R206 */ | ||
560 | { 0x0000, 0x0000, 0 }, /* R207 */ | ||
561 | { 0x0000, 0x0000, 0 }, /* R208 */ | ||
562 | { 0x0000, 0x0000, 0 }, /* R209 */ | ||
563 | { 0x0000, 0x0000, 0 }, /* R210 */ | ||
564 | { 0x0000, 0x0000, 0 }, /* R211 */ | ||
565 | { 0x0000, 0x0000, 0 }, /* R212 */ | ||
566 | { 0x0000, 0x0000, 0 }, /* R213 */ | ||
567 | { 0x0000, 0x0000, 0 }, /* R214 */ | ||
568 | { 0x0000, 0x0000, 0 }, /* R215 */ | ||
569 | { 0x0000, 0x0000, 0 }, /* R216 */ | ||
570 | { 0x0000, 0x0000, 0 }, /* R217 */ | ||
571 | { 0x0000, 0x0000, 0 }, /* R218 */ | ||
572 | { 0x0000, 0x0000, 0 }, /* R219 */ | ||
573 | { 0x0000, 0x0000, 0 }, /* R220 */ | ||
574 | { 0x0000, 0x0000, 0 }, /* R221 */ | ||
575 | { 0x0000, 0x0000, 0 }, /* R222 */ | ||
576 | { 0x0000, 0x0000, 0 }, /* R223 */ | ||
577 | { 0x0000, 0x0000, 0 }, /* R224 */ | ||
578 | { 0x0000, 0x0000, 0 }, /* R225 */ | ||
579 | { 0x0000, 0x0000, 0 }, /* R226 */ | ||
580 | { 0x0000, 0x0000, 0 }, /* R227 */ | ||
581 | { 0x0000, 0x0000, 0 }, /* R228 */ | ||
582 | { 0x0000, 0x0000, 0 }, /* R229 */ | ||
583 | { 0x0000, 0x0000, 0 }, /* R230 */ | ||
584 | { 0x0000, 0x0000, 0 }, /* R231 */ | ||
585 | { 0x0000, 0x0000, 0 }, /* R232 */ | ||
586 | { 0x0000, 0x0000, 0 }, /* R233 */ | ||
587 | { 0x0000, 0x0000, 0 }, /* R234 */ | ||
588 | { 0x0000, 0x0000, 0 }, /* R235 */ | ||
589 | { 0x0000, 0x0000, 0 }, /* R236 */ | ||
590 | { 0x0000, 0x0000, 0 }, /* R237 */ | ||
591 | { 0x0000, 0x0000, 0 }, /* R238 */ | ||
592 | { 0x0000, 0x0000, 0 }, /* R239 */ | ||
593 | { 0x0000, 0x0000, 0 }, /* R240 */ | ||
594 | { 0x0000, 0x0000, 0 }, /* R241 */ | ||
595 | { 0x0000, 0x0000, 0 }, /* R242 */ | ||
596 | { 0x0000, 0x0000, 0 }, /* R243 */ | ||
597 | { 0x0000, 0x0000, 0 }, /* R244 */ | ||
598 | { 0x0000, 0x0000, 0 }, /* R245 */ | ||
599 | { 0x0000, 0x0000, 0 }, /* R246 */ | ||
600 | { 0x0001, 0x0001, 0 }, /* R247 - FLL NCO Test 0 */ | ||
601 | { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */ | ||
602 | }; | ||
603 | |||
604 | static int wm8904_volatile_register(unsigned int reg) | ||
605 | { | ||
606 | return wm8904_access[reg].vol; | ||
607 | } | ||
608 | |||
609 | static int wm8904_reset(struct snd_soc_codec *codec) | ||
610 | { | ||
611 | return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0); | ||
612 | } | ||
613 | |||
614 | static int wm8904_configure_clocking(struct snd_soc_codec *codec) | ||
615 | { | ||
616 | struct wm8904_priv *wm8904 = codec->private_data; | ||
617 | unsigned int clock0, clock2, rate; | ||
618 | |||
619 | /* Gate the clock while we're updating to avoid misclocking */ | ||
620 | clock2 = snd_soc_read(codec, WM8904_CLOCK_RATES_2); | ||
621 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, | ||
622 | WM8904_SYSCLK_SRC, 0); | ||
623 | |||
624 | /* This should be done on init() for bypass paths */ | ||
625 | switch (wm8904->sysclk_src) { | ||
626 | case WM8904_CLK_MCLK: | ||
627 | dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8904->mclk_rate); | ||
628 | |||
629 | clock2 &= ~WM8904_SYSCLK_SRC; | ||
630 | rate = wm8904->mclk_rate; | ||
631 | |||
632 | /* Ensure the FLL is stopped */ | ||
633 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
634 | WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); | ||
635 | break; | ||
636 | |||
637 | case WM8904_CLK_FLL: | ||
638 | dev_dbg(codec->dev, "Using %dHz FLL clock\n", | ||
639 | wm8904->fll_fout); | ||
640 | |||
641 | clock2 |= WM8904_SYSCLK_SRC; | ||
642 | rate = wm8904->fll_fout; | ||
643 | break; | ||
644 | |||
645 | default: | ||
646 | dev_err(codec->dev, "System clock not configured\n"); | ||
647 | return -EINVAL; | ||
648 | } | ||
649 | |||
650 | /* SYSCLK shouldn't be over 13.5MHz */ | ||
651 | if (rate > 13500000) { | ||
652 | clock0 = WM8904_MCLK_DIV; | ||
653 | wm8904->sysclk_rate = rate / 2; | ||
654 | } else { | ||
655 | clock0 = 0; | ||
656 | wm8904->sysclk_rate = rate; | ||
657 | } | ||
658 | |||
659 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, WM8904_MCLK_DIV, | ||
660 | clock0); | ||
661 | |||
662 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, | ||
663 | WM8904_CLK_SYS_ENA | WM8904_SYSCLK_SRC, clock2); | ||
664 | |||
665 | dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8904->sysclk_rate); | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static void wm8904_set_drc(struct snd_soc_codec *codec) | ||
671 | { | ||
672 | struct wm8904_priv *wm8904 = codec->private_data; | ||
673 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
674 | int save, i; | ||
675 | |||
676 | /* Save any enables; the configuration should clear them. */ | ||
677 | save = snd_soc_read(codec, WM8904_DRC_0); | ||
678 | |||
679 | for (i = 0; i < WM8904_DRC_REGS; i++) | ||
680 | snd_soc_update_bits(codec, WM8904_DRC_0 + i, 0xffff, | ||
681 | pdata->drc_cfgs[wm8904->drc_cfg].regs[i]); | ||
682 | |||
683 | /* Reenable the DRC */ | ||
684 | snd_soc_update_bits(codec, WM8904_DRC_0, | ||
685 | WM8904_DRC_ENA | WM8904_DRC_DAC_PATH, save); | ||
686 | } | ||
687 | |||
688 | static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol, | ||
689 | struct snd_ctl_elem_value *ucontrol) | ||
690 | { | ||
691 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
692 | struct wm8904_priv *wm8904 = codec->private_data; | ||
693 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
694 | int value = ucontrol->value.integer.value[0]; | ||
695 | |||
696 | if (value >= pdata->num_drc_cfgs) | ||
697 | return -EINVAL; | ||
698 | |||
699 | wm8904->drc_cfg = value; | ||
700 | |||
701 | wm8904_set_drc(codec); | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int wm8904_get_drc_enum(struct snd_kcontrol *kcontrol, | ||
707 | struct snd_ctl_elem_value *ucontrol) | ||
708 | { | ||
709 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
710 | struct wm8904_priv *wm8904 = codec->private_data; | ||
711 | |||
712 | ucontrol->value.enumerated.item[0] = wm8904->drc_cfg; | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static void wm8904_set_retune_mobile(struct snd_soc_codec *codec) | ||
718 | { | ||
719 | struct wm8904_priv *wm8904 = codec->private_data; | ||
720 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
721 | int best, best_val, save, i, cfg; | ||
722 | |||
723 | if (!pdata || !wm8904->num_retune_mobile_texts) | ||
724 | return; | ||
725 | |||
726 | /* Find the version of the currently selected configuration | ||
727 | * with the nearest sample rate. */ | ||
728 | cfg = wm8904->retune_mobile_cfg; | ||
729 | best = 0; | ||
730 | best_val = INT_MAX; | ||
731 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
732 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
733 | wm8904->retune_mobile_texts[cfg]) == 0 && | ||
734 | abs(pdata->retune_mobile_cfgs[i].rate | ||
735 | - wm8904->fs) < best_val) { | ||
736 | best = i; | ||
737 | best_val = abs(pdata->retune_mobile_cfgs[i].rate | ||
738 | - wm8904->fs); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | dev_dbg(codec->dev, "ReTune Mobile %s/%dHz for %dHz sample rate\n", | ||
743 | pdata->retune_mobile_cfgs[best].name, | ||
744 | pdata->retune_mobile_cfgs[best].rate, | ||
745 | wm8904->fs); | ||
746 | |||
747 | /* The EQ will be disabled while reconfiguring it, remember the | ||
748 | * current configuration. | ||
749 | */ | ||
750 | save = snd_soc_read(codec, WM8904_EQ1); | ||
751 | |||
752 | for (i = 0; i < WM8904_EQ_REGS; i++) | ||
753 | snd_soc_update_bits(codec, WM8904_EQ1 + i, 0xffff, | ||
754 | pdata->retune_mobile_cfgs[best].regs[i]); | ||
755 | |||
756 | snd_soc_update_bits(codec, WM8904_EQ1, WM8904_EQ_ENA, save); | ||
757 | } | ||
758 | |||
759 | static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
760 | struct snd_ctl_elem_value *ucontrol) | ||
761 | { | ||
762 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
763 | struct wm8904_priv *wm8904 = codec->private_data; | ||
764 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
765 | int value = ucontrol->value.integer.value[0]; | ||
766 | |||
767 | if (value >= pdata->num_retune_mobile_cfgs) | ||
768 | return -EINVAL; | ||
769 | |||
770 | wm8904->retune_mobile_cfg = value; | ||
771 | |||
772 | wm8904_set_retune_mobile(codec); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int wm8904_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
778 | struct snd_ctl_elem_value *ucontrol) | ||
779 | { | ||
780 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
781 | struct wm8904_priv *wm8904 = codec->private_data; | ||
782 | |||
783 | ucontrol->value.enumerated.item[0] = wm8904->retune_mobile_cfg; | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | static int deemph_settings[] = { 0, 32000, 44100, 48000 }; | ||
789 | |||
790 | static int wm8904_set_deemph(struct snd_soc_codec *codec) | ||
791 | { | ||
792 | struct wm8904_priv *wm8904 = codec->private_data; | ||
793 | int val, i, best; | ||
794 | |||
795 | /* If we're using deemphasis select the nearest available sample | ||
796 | * rate. | ||
797 | */ | ||
798 | if (wm8904->deemph) { | ||
799 | best = 1; | ||
800 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { | ||
801 | if (abs(deemph_settings[i] - wm8904->fs) < | ||
802 | abs(deemph_settings[best] - wm8904->fs)) | ||
803 | best = i; | ||
804 | } | ||
805 | |||
806 | val = best << WM8904_DEEMPH_SHIFT; | ||
807 | } else { | ||
808 | val = 0; | ||
809 | } | ||
810 | |||
811 | dev_dbg(codec->dev, "Set deemphasis %d\n", val); | ||
812 | |||
813 | return snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, | ||
814 | WM8904_DEEMPH_MASK, val); | ||
815 | } | ||
816 | |||
817 | static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, | ||
818 | struct snd_ctl_elem_value *ucontrol) | ||
819 | { | ||
820 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
821 | struct wm8904_priv *wm8904 = codec->private_data; | ||
822 | |||
823 | return wm8904->deemph; | ||
824 | } | ||
825 | |||
826 | static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, | ||
827 | struct snd_ctl_elem_value *ucontrol) | ||
828 | { | ||
829 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
830 | struct wm8904_priv *wm8904 = codec->private_data; | ||
831 | int deemph = ucontrol->value.enumerated.item[0]; | ||
832 | |||
833 | if (deemph > 1) | ||
834 | return -EINVAL; | ||
835 | |||
836 | wm8904->deemph = deemph; | ||
837 | |||
838 | return wm8904_set_deemph(codec); | ||
839 | } | ||
840 | |||
841 | static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); | ||
842 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | ||
843 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | ||
844 | static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); | ||
845 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
846 | |||
847 | static const char *input_mode_text[] = { | ||
848 | "Single-Ended", "Differential Line", "Differential Mic" | ||
849 | }; | ||
850 | |||
851 | static const struct soc_enum lin_mode = | ||
852 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); | ||
853 | |||
854 | static const struct soc_enum rin_mode = | ||
855 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); | ||
856 | |||
857 | static const char *hpf_mode_text[] = { | ||
858 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3" | ||
859 | }; | ||
860 | |||
861 | static const struct soc_enum hpf_mode = | ||
862 | SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); | ||
863 | |||
864 | static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = { | ||
865 | SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT, | ||
866 | WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv), | ||
867 | |||
868 | SOC_ENUM("Left Caputure Mode", lin_mode), | ||
869 | SOC_ENUM("Right Capture Mode", rin_mode), | ||
870 | |||
871 | /* No TLV since it depends on mode */ | ||
872 | SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0, | ||
873 | WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0), | ||
874 | SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0, | ||
875 | WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 0), | ||
876 | |||
877 | SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), | ||
878 | SOC_ENUM("High Pass Filter Mode", hpf_mode), | ||
879 | |||
880 | SOC_SINGLE("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0), | ||
881 | }; | ||
882 | |||
883 | static const char *drc_path_text[] = { | ||
884 | "ADC", "DAC" | ||
885 | }; | ||
886 | |||
887 | static const struct soc_enum drc_path = | ||
888 | SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); | ||
889 | |||
890 | static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { | ||
891 | SOC_SINGLE_TLV("Digital Playback Boost Volume", | ||
892 | WM8904_AUDIO_INTERFACE_0, 9, 3, 0, dac_boost_tlv), | ||
893 | SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8904_DAC_DIGITAL_VOLUME_LEFT, | ||
894 | WM8904_DAC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv), | ||
895 | |||
896 | SOC_DOUBLE_R_TLV("Headphone Volume", WM8904_ANALOGUE_OUT1_LEFT, | ||
897 | WM8904_ANALOGUE_OUT1_RIGHT, 0, 63, 0, out_tlv), | ||
898 | SOC_DOUBLE_R("Headphone Switch", WM8904_ANALOGUE_OUT1_LEFT, | ||
899 | WM8904_ANALOGUE_OUT1_RIGHT, 8, 1, 1), | ||
900 | SOC_DOUBLE_R("Headphone ZC Switch", WM8904_ANALOGUE_OUT1_LEFT, | ||
901 | WM8904_ANALOGUE_OUT1_RIGHT, 6, 1, 0), | ||
902 | |||
903 | SOC_DOUBLE_R_TLV("Line Output Volume", WM8904_ANALOGUE_OUT2_LEFT, | ||
904 | WM8904_ANALOGUE_OUT2_RIGHT, 0, 63, 0, out_tlv), | ||
905 | SOC_DOUBLE_R("Line Output Switch", WM8904_ANALOGUE_OUT2_LEFT, | ||
906 | WM8904_ANALOGUE_OUT2_RIGHT, 8, 1, 1), | ||
907 | SOC_DOUBLE_R("Line Output ZC Switch", WM8904_ANALOGUE_OUT2_LEFT, | ||
908 | WM8904_ANALOGUE_OUT2_RIGHT, 6, 1, 0), | ||
909 | |||
910 | SOC_SINGLE("EQ Switch", WM8904_EQ1, 0, 1, 0), | ||
911 | SOC_SINGLE("DRC Switch", WM8904_DRC_0, 15, 1, 0), | ||
912 | SOC_ENUM("DRC Path", drc_path), | ||
913 | SOC_SINGLE("DAC OSRx2 Switch", WM8904_DAC_DIGITAL_1, 6, 1, 0), | ||
914 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, | ||
915 | wm8904_get_deemph, wm8904_put_deemph), | ||
916 | }; | ||
917 | |||
918 | static const struct snd_kcontrol_new wm8904_snd_controls[] = { | ||
919 | SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8904_DAC_DIGITAL_0, 4, 8, 15, 0, | ||
920 | sidetone_tlv), | ||
921 | }; | ||
922 | |||
923 | static const struct snd_kcontrol_new wm8904_eq_controls[] = { | ||
924 | SOC_SINGLE_TLV("EQ1 Volume", WM8904_EQ2, 0, 24, 0, eq_tlv), | ||
925 | SOC_SINGLE_TLV("EQ2 Volume", WM8904_EQ3, 0, 24, 0, eq_tlv), | ||
926 | SOC_SINGLE_TLV("EQ3 Volume", WM8904_EQ4, 0, 24, 0, eq_tlv), | ||
927 | SOC_SINGLE_TLV("EQ4 Volume", WM8904_EQ5, 0, 24, 0, eq_tlv), | ||
928 | SOC_SINGLE_TLV("EQ5 Volume", WM8904_EQ6, 0, 24, 0, eq_tlv), | ||
929 | }; | ||
930 | |||
931 | static int cp_event(struct snd_soc_dapm_widget *w, | ||
932 | struct snd_kcontrol *kcontrol, int event) | ||
933 | { | ||
934 | BUG_ON(event != SND_SOC_DAPM_POST_PMU); | ||
935 | |||
936 | /* Maximum startup time */ | ||
937 | udelay(500); | ||
938 | |||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int sysclk_event(struct snd_soc_dapm_widget *w, | ||
943 | struct snd_kcontrol *kcontrol, int event) | ||
944 | { | ||
945 | struct snd_soc_codec *codec = w->codec; | ||
946 | struct wm8904_priv *wm8904 = codec->private_data; | ||
947 | |||
948 | switch (event) { | ||
949 | case SND_SOC_DAPM_PRE_PMU: | ||
950 | /* If we're using the FLL then we only start it when | ||
951 | * required; we assume that the configuration has been | ||
952 | * done previously and all we need to do is kick it | ||
953 | * off. | ||
954 | */ | ||
955 | switch (wm8904->sysclk_src) { | ||
956 | case WM8904_CLK_FLL: | ||
957 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
958 | WM8904_FLL_OSC_ENA, | ||
959 | WM8904_FLL_OSC_ENA); | ||
960 | |||
961 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
962 | WM8904_FLL_ENA, | ||
963 | WM8904_FLL_ENA); | ||
964 | break; | ||
965 | |||
966 | default: | ||
967 | break; | ||
968 | } | ||
969 | break; | ||
970 | |||
971 | case SND_SOC_DAPM_POST_PMD: | ||
972 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
973 | WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static int out_pga_event(struct snd_soc_dapm_widget *w, | ||
981 | struct snd_kcontrol *kcontrol, int event) | ||
982 | { | ||
983 | struct snd_soc_codec *codec = w->codec; | ||
984 | struct wm8904_priv *wm8904 = codec->private_data; | ||
985 | int reg, val; | ||
986 | int dcs_mask; | ||
987 | int dcs_l, dcs_r; | ||
988 | int dcs_l_reg, dcs_r_reg; | ||
989 | int timeout; | ||
990 | int pwr_reg; | ||
991 | |||
992 | /* This code is shared between HP and LINEOUT; we do all our | ||
993 | * power management in stereo pairs to avoid latency issues so | ||
994 | * we reuse shift to identify which rather than strcmp() the | ||
995 | * name. */ | ||
996 | reg = w->shift; | ||
997 | |||
998 | switch (reg) { | ||
999 | case WM8904_ANALOGUE_HP_0: | ||
1000 | pwr_reg = WM8904_POWER_MANAGEMENT_2; | ||
1001 | dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1; | ||
1002 | dcs_r_reg = WM8904_DC_SERVO_8; | ||
1003 | dcs_l_reg = WM8904_DC_SERVO_9; | ||
1004 | dcs_l = 0; | ||
1005 | dcs_r = 1; | ||
1006 | break; | ||
1007 | case WM8904_ANALOGUE_LINEOUT_0: | ||
1008 | pwr_reg = WM8904_POWER_MANAGEMENT_3; | ||
1009 | dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3; | ||
1010 | dcs_r_reg = WM8904_DC_SERVO_6; | ||
1011 | dcs_l_reg = WM8904_DC_SERVO_7; | ||
1012 | dcs_l = 2; | ||
1013 | dcs_r = 3; | ||
1014 | break; | ||
1015 | default: | ||
1016 | BUG(); | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | switch (event) { | ||
1021 | case SND_SOC_DAPM_PRE_PMU: | ||
1022 | /* Power on the PGAs */ | ||
1023 | snd_soc_update_bits(codec, pwr_reg, | ||
1024 | WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA, | ||
1025 | WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA); | ||
1026 | |||
1027 | /* Power on the amplifier */ | ||
1028 | snd_soc_update_bits(codec, reg, | ||
1029 | WM8904_HPL_ENA | WM8904_HPR_ENA, | ||
1030 | WM8904_HPL_ENA | WM8904_HPR_ENA); | ||
1031 | |||
1032 | |||
1033 | /* Enable the first stage */ | ||
1034 | snd_soc_update_bits(codec, reg, | ||
1035 | WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY, | ||
1036 | WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY); | ||
1037 | |||
1038 | /* Power up the DC servo */ | ||
1039 | snd_soc_update_bits(codec, WM8904_DC_SERVO_0, | ||
1040 | dcs_mask, dcs_mask); | ||
1041 | |||
1042 | /* Either calibrate the DC servo or restore cached state | ||
1043 | * if we have that. | ||
1044 | */ | ||
1045 | if (wm8904->dcs_state[dcs_l] || wm8904->dcs_state[dcs_r]) { | ||
1046 | dev_dbg(codec->dev, "Restoring DC servo state\n"); | ||
1047 | |||
1048 | snd_soc_write(codec, dcs_l_reg, | ||
1049 | wm8904->dcs_state[dcs_l]); | ||
1050 | snd_soc_write(codec, dcs_r_reg, | ||
1051 | wm8904->dcs_state[dcs_r]); | ||
1052 | |||
1053 | snd_soc_write(codec, WM8904_DC_SERVO_1, dcs_mask); | ||
1054 | |||
1055 | timeout = 20; | ||
1056 | } else { | ||
1057 | dev_dbg(codec->dev, "Calibrating DC servo\n"); | ||
1058 | |||
1059 | snd_soc_write(codec, WM8904_DC_SERVO_1, | ||
1060 | dcs_mask << WM8904_DCS_TRIG_STARTUP_0_SHIFT); | ||
1061 | |||
1062 | timeout = 500; | ||
1063 | } | ||
1064 | |||
1065 | /* Wait for DC servo to complete */ | ||
1066 | dcs_mask <<= WM8904_DCS_CAL_COMPLETE_SHIFT; | ||
1067 | do { | ||
1068 | val = snd_soc_read(codec, WM8904_DC_SERVO_READBACK_0); | ||
1069 | if ((val & dcs_mask) == dcs_mask) | ||
1070 | break; | ||
1071 | |||
1072 | msleep(1); | ||
1073 | } while (--timeout); | ||
1074 | |||
1075 | if ((val & dcs_mask) != dcs_mask) | ||
1076 | dev_warn(codec->dev, "DC servo timed out\n"); | ||
1077 | else | ||
1078 | dev_dbg(codec->dev, "DC servo ready\n"); | ||
1079 | |||
1080 | /* Enable the output stage */ | ||
1081 | snd_soc_update_bits(codec, reg, | ||
1082 | WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, | ||
1083 | WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP); | ||
1084 | break; | ||
1085 | |||
1086 | case SND_SOC_DAPM_POST_PMU: | ||
1087 | /* Unshort the output itself */ | ||
1088 | snd_soc_update_bits(codec, reg, | ||
1089 | WM8904_HPL_RMV_SHORT | | ||
1090 | WM8904_HPR_RMV_SHORT, | ||
1091 | WM8904_HPL_RMV_SHORT | | ||
1092 | WM8904_HPR_RMV_SHORT); | ||
1093 | |||
1094 | break; | ||
1095 | |||
1096 | case SND_SOC_DAPM_PRE_PMD: | ||
1097 | /* Short the output */ | ||
1098 | snd_soc_update_bits(codec, reg, | ||
1099 | WM8904_HPL_RMV_SHORT | | ||
1100 | WM8904_HPR_RMV_SHORT, 0); | ||
1101 | break; | ||
1102 | |||
1103 | case SND_SOC_DAPM_POST_PMD: | ||
1104 | /* Cache the DC servo configuration; this will be | ||
1105 | * invalidated if we change the configuration. */ | ||
1106 | wm8904->dcs_state[dcs_l] = snd_soc_read(codec, dcs_l_reg); | ||
1107 | wm8904->dcs_state[dcs_r] = snd_soc_read(codec, dcs_r_reg); | ||
1108 | |||
1109 | snd_soc_update_bits(codec, WM8904_DC_SERVO_0, | ||
1110 | dcs_mask, 0); | ||
1111 | |||
1112 | /* Disable the amplifier input and output stages */ | ||
1113 | snd_soc_update_bits(codec, reg, | ||
1114 | WM8904_HPL_ENA | WM8904_HPR_ENA | | ||
1115 | WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY | | ||
1116 | WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, | ||
1117 | 0); | ||
1118 | |||
1119 | /* PGAs too */ | ||
1120 | snd_soc_update_bits(codec, pwr_reg, | ||
1121 | WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA, | ||
1122 | 0); | ||
1123 | break; | ||
1124 | } | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static const char *lin_text[] = { | ||
1130 | "IN1L", "IN2L", "IN3L" | ||
1131 | }; | ||
1132 | |||
1133 | static const struct soc_enum lin_enum = | ||
1134 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); | ||
1135 | |||
1136 | static const struct snd_kcontrol_new lin_mux = | ||
1137 | SOC_DAPM_ENUM("Left Capture Mux", lin_enum); | ||
1138 | |||
1139 | static const struct soc_enum lin_inv_enum = | ||
1140 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); | ||
1141 | |||
1142 | static const struct snd_kcontrol_new lin_inv_mux = | ||
1143 | SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); | ||
1144 | |||
1145 | static const char *rin_text[] = { | ||
1146 | "IN1R", "IN2R", "IN3R" | ||
1147 | }; | ||
1148 | |||
1149 | static const struct soc_enum rin_enum = | ||
1150 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); | ||
1151 | |||
1152 | static const struct snd_kcontrol_new rin_mux = | ||
1153 | SOC_DAPM_ENUM("Right Capture Mux", rin_enum); | ||
1154 | |||
1155 | static const struct soc_enum rin_inv_enum = | ||
1156 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); | ||
1157 | |||
1158 | static const struct snd_kcontrol_new rin_inv_mux = | ||
1159 | SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); | ||
1160 | |||
1161 | static const char *aif_text[] = { | ||
1162 | "Left", "Right" | ||
1163 | }; | ||
1164 | |||
1165 | static const struct soc_enum aifoutl_enum = | ||
1166 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); | ||
1167 | |||
1168 | static const struct snd_kcontrol_new aifoutl_mux = | ||
1169 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); | ||
1170 | |||
1171 | static const struct soc_enum aifoutr_enum = | ||
1172 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); | ||
1173 | |||
1174 | static const struct snd_kcontrol_new aifoutr_mux = | ||
1175 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); | ||
1176 | |||
1177 | static const struct soc_enum aifinl_enum = | ||
1178 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); | ||
1179 | |||
1180 | static const struct snd_kcontrol_new aifinl_mux = | ||
1181 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); | ||
1182 | |||
1183 | static const struct soc_enum aifinr_enum = | ||
1184 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); | ||
1185 | |||
1186 | static const struct snd_kcontrol_new aifinr_mux = | ||
1187 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); | ||
1188 | |||
1189 | static const struct snd_soc_dapm_widget wm8904_core_dapm_widgets[] = { | ||
1190 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM8904_CLOCK_RATES_2, 2, 0, sysclk_event, | ||
1191 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
1192 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8904_CLOCK_RATES_2, 1, 0, NULL, 0), | ||
1193 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8904_CLOCK_RATES_2, 0, 0, NULL, 0), | ||
1194 | }; | ||
1195 | |||
1196 | static const struct snd_soc_dapm_widget wm8904_adc_dapm_widgets[] = { | ||
1197 | SND_SOC_DAPM_INPUT("IN1L"), | ||
1198 | SND_SOC_DAPM_INPUT("IN1R"), | ||
1199 | SND_SOC_DAPM_INPUT("IN2L"), | ||
1200 | SND_SOC_DAPM_INPUT("IN2R"), | ||
1201 | SND_SOC_DAPM_INPUT("IN3L"), | ||
1202 | SND_SOC_DAPM_INPUT("IN3R"), | ||
1203 | |||
1204 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0), | ||
1205 | |||
1206 | SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux), | ||
1207 | SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0, | ||
1208 | &lin_inv_mux), | ||
1209 | SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rin_mux), | ||
1210 | SND_SOC_DAPM_MUX("Right Capture Inverting Mux", SND_SOC_NOPM, 0, 0, | ||
1211 | &rin_inv_mux), | ||
1212 | |||
1213 | SND_SOC_DAPM_PGA("Left Capture PGA", WM8904_POWER_MANAGEMENT_0, 1, 0, | ||
1214 | NULL, 0), | ||
1215 | SND_SOC_DAPM_PGA("Right Capture PGA", WM8904_POWER_MANAGEMENT_0, 0, 0, | ||
1216 | NULL, 0), | ||
1217 | |||
1218 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8904_POWER_MANAGEMENT_6, 1, 0), | ||
1219 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8904_POWER_MANAGEMENT_6, 0, 0), | ||
1220 | |||
1221 | SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), | ||
1222 | SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), | ||
1223 | |||
1224 | SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), | ||
1225 | SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), | ||
1226 | }; | ||
1227 | |||
1228 | static const struct snd_soc_dapm_widget wm8904_dac_dapm_widgets[] = { | ||
1229 | SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
1230 | SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), | ||
1231 | |||
1232 | SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), | ||
1233 | SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), | ||
1234 | |||
1235 | SND_SOC_DAPM_DAC("DACL", NULL, WM8904_POWER_MANAGEMENT_6, 3, 0), | ||
1236 | SND_SOC_DAPM_DAC("DACR", NULL, WM8904_POWER_MANAGEMENT_6, 2, 0), | ||
1237 | |||
1238 | SND_SOC_DAPM_SUPPLY("Charge pump", WM8904_CHARGE_PUMP_0, 0, 0, cp_event, | ||
1239 | SND_SOC_DAPM_POST_PMU), | ||
1240 | |||
1241 | SND_SOC_DAPM_PGA("HPL PGA", SND_SOC_NOPM, 1, 0, NULL, 0), | ||
1242 | SND_SOC_DAPM_PGA("HPR PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1243 | |||
1244 | SND_SOC_DAPM_PGA("LINEL PGA", SND_SOC_NOPM, 1, 0, NULL, 0), | ||
1245 | SND_SOC_DAPM_PGA("LINER PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1246 | |||
1247 | SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, WM8904_ANALOGUE_HP_0, | ||
1248 | 0, NULL, 0, out_pga_event, | ||
1249 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | ||
1250 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | ||
1251 | SND_SOC_DAPM_PGA_E("Line Output", SND_SOC_NOPM, WM8904_ANALOGUE_LINEOUT_0, | ||
1252 | 0, NULL, 0, out_pga_event, | ||
1253 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | ||
1254 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), | ||
1255 | |||
1256 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | ||
1257 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | ||
1258 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | ||
1259 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | ||
1260 | }; | ||
1261 | |||
1262 | static const char *out_mux_text[] = { | ||
1263 | "DAC", "Bypass" | ||
1264 | }; | ||
1265 | |||
1266 | static const struct soc_enum hpl_enum = | ||
1267 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); | ||
1268 | |||
1269 | static const struct snd_kcontrol_new hpl_mux = | ||
1270 | SOC_DAPM_ENUM("HPL Mux", hpl_enum); | ||
1271 | |||
1272 | static const struct soc_enum hpr_enum = | ||
1273 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); | ||
1274 | |||
1275 | static const struct snd_kcontrol_new hpr_mux = | ||
1276 | SOC_DAPM_ENUM("HPR Mux", hpr_enum); | ||
1277 | |||
1278 | static const struct soc_enum linel_enum = | ||
1279 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); | ||
1280 | |||
1281 | static const struct snd_kcontrol_new linel_mux = | ||
1282 | SOC_DAPM_ENUM("LINEL Mux", linel_enum); | ||
1283 | |||
1284 | static const struct soc_enum liner_enum = | ||
1285 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); | ||
1286 | |||
1287 | static const struct snd_kcontrol_new liner_mux = | ||
1288 | SOC_DAPM_ENUM("LINEL Mux", liner_enum); | ||
1289 | |||
1290 | static const char *sidetone_text[] = { | ||
1291 | "None", "Left", "Right" | ||
1292 | }; | ||
1293 | |||
1294 | static const struct soc_enum dacl_sidetone_enum = | ||
1295 | SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); | ||
1296 | |||
1297 | static const struct snd_kcontrol_new dacl_sidetone_mux = | ||
1298 | SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); | ||
1299 | |||
1300 | static const struct soc_enum dacr_sidetone_enum = | ||
1301 | SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); | ||
1302 | |||
1303 | static const struct snd_kcontrol_new dacr_sidetone_mux = | ||
1304 | SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); | ||
1305 | |||
1306 | static const struct snd_soc_dapm_widget wm8904_dapm_widgets[] = { | ||
1307 | SND_SOC_DAPM_SUPPLY("Class G", WM8904_CLASS_W_0, 0, 1, NULL, 0), | ||
1308 | SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1309 | SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1310 | |||
1311 | SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &dacl_sidetone_mux), | ||
1312 | SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &dacr_sidetone_mux), | ||
1313 | |||
1314 | SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
1315 | SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
1316 | SND_SOC_DAPM_MUX("LINEL Mux", SND_SOC_NOPM, 0, 0, &linel_mux), | ||
1317 | SND_SOC_DAPM_MUX("LINER Mux", SND_SOC_NOPM, 0, 0, &liner_mux), | ||
1318 | }; | ||
1319 | |||
1320 | static const struct snd_soc_dapm_route core_intercon[] = { | ||
1321 | { "CLK_DSP", NULL, "SYSCLK" }, | ||
1322 | { "TOCLK", NULL, "SYSCLK" }, | ||
1323 | }; | ||
1324 | |||
1325 | static const struct snd_soc_dapm_route adc_intercon[] = { | ||
1326 | { "Left Capture Mux", "IN1L", "IN1L" }, | ||
1327 | { "Left Capture Mux", "IN2L", "IN2L" }, | ||
1328 | { "Left Capture Mux", "IN3L", "IN3L" }, | ||
1329 | |||
1330 | { "Left Capture Inverting Mux", "IN1L", "IN1L" }, | ||
1331 | { "Left Capture Inverting Mux", "IN2L", "IN2L" }, | ||
1332 | { "Left Capture Inverting Mux", "IN3L", "IN3L" }, | ||
1333 | |||
1334 | { "Right Capture Mux", "IN1R", "IN1R" }, | ||
1335 | { "Right Capture Mux", "IN2R", "IN2R" }, | ||
1336 | { "Right Capture Mux", "IN3R", "IN3R" }, | ||
1337 | |||
1338 | { "Right Capture Inverting Mux", "IN1R", "IN1R" }, | ||
1339 | { "Right Capture Inverting Mux", "IN2R", "IN2R" }, | ||
1340 | { "Right Capture Inverting Mux", "IN3R", "IN3R" }, | ||
1341 | |||
1342 | { "Left Capture PGA", NULL, "Left Capture Mux" }, | ||
1343 | { "Left Capture PGA", NULL, "Left Capture Inverting Mux" }, | ||
1344 | |||
1345 | { "Right Capture PGA", NULL, "Right Capture Mux" }, | ||
1346 | { "Right Capture PGA", NULL, "Right Capture Inverting Mux" }, | ||
1347 | |||
1348 | { "AIFOUTL", "Left", "ADCL" }, | ||
1349 | { "AIFOUTL", "Right", "ADCR" }, | ||
1350 | { "AIFOUTR", "Left", "ADCL" }, | ||
1351 | { "AIFOUTR", "Right", "ADCR" }, | ||
1352 | |||
1353 | { "ADCL", NULL, "CLK_DSP" }, | ||
1354 | { "ADCL", NULL, "Left Capture PGA" }, | ||
1355 | |||
1356 | { "ADCR", NULL, "CLK_DSP" }, | ||
1357 | { "ADCR", NULL, "Right Capture PGA" }, | ||
1358 | }; | ||
1359 | |||
1360 | static const struct snd_soc_dapm_route dac_intercon[] = { | ||
1361 | { "DACL", "Right", "AIFINR" }, | ||
1362 | { "DACL", "Left", "AIFINL" }, | ||
1363 | { "DACL", NULL, "CLK_DSP" }, | ||
1364 | |||
1365 | { "DACR", "Right", "AIFINR" }, | ||
1366 | { "DACR", "Left", "AIFINL" }, | ||
1367 | { "DACR", NULL, "CLK_DSP" }, | ||
1368 | |||
1369 | { "Charge pump", NULL, "SYSCLK" }, | ||
1370 | |||
1371 | { "Headphone Output", NULL, "HPL PGA" }, | ||
1372 | { "Headphone Output", NULL, "HPR PGA" }, | ||
1373 | { "Headphone Output", NULL, "Charge pump" }, | ||
1374 | { "Headphone Output", NULL, "TOCLK" }, | ||
1375 | |||
1376 | { "Line Output", NULL, "LINEL PGA" }, | ||
1377 | { "Line Output", NULL, "LINER PGA" }, | ||
1378 | { "Line Output", NULL, "Charge pump" }, | ||
1379 | { "Line Output", NULL, "TOCLK" }, | ||
1380 | |||
1381 | { "HPOUTL", NULL, "Headphone Output" }, | ||
1382 | { "HPOUTR", NULL, "Headphone Output" }, | ||
1383 | |||
1384 | { "LINEOUTL", NULL, "Line Output" }, | ||
1385 | { "LINEOUTR", NULL, "Line Output" }, | ||
1386 | }; | ||
1387 | |||
1388 | static const struct snd_soc_dapm_route wm8904_intercon[] = { | ||
1389 | { "Left Sidetone", "Left", "ADCL" }, | ||
1390 | { "Left Sidetone", "Right", "ADCR" }, | ||
1391 | { "DACL", NULL, "Left Sidetone" }, | ||
1392 | |||
1393 | { "Right Sidetone", "Left", "ADCL" }, | ||
1394 | { "Right Sidetone", "Right", "ADCR" }, | ||
1395 | { "DACR", NULL, "Right Sidetone" }, | ||
1396 | |||
1397 | { "Left Bypass", NULL, "Class G" }, | ||
1398 | { "Left Bypass", NULL, "Left Capture PGA" }, | ||
1399 | |||
1400 | { "Right Bypass", NULL, "Class G" }, | ||
1401 | { "Right Bypass", NULL, "Right Capture PGA" }, | ||
1402 | |||
1403 | { "HPL Mux", "DAC", "DACL" }, | ||
1404 | { "HPL Mux", "Bypass", "Left Bypass" }, | ||
1405 | |||
1406 | { "HPR Mux", "DAC", "DACR" }, | ||
1407 | { "HPR Mux", "Bypass", "Right Bypass" }, | ||
1408 | |||
1409 | { "LINEL Mux", "DAC", "DACL" }, | ||
1410 | { "LINEL Mux", "Bypass", "Left Bypass" }, | ||
1411 | |||
1412 | { "LINER Mux", "DAC", "DACR" }, | ||
1413 | { "LINER Mux", "Bypass", "Right Bypass" }, | ||
1414 | |||
1415 | { "HPL PGA", NULL, "HPL Mux" }, | ||
1416 | { "HPR PGA", NULL, "HPR Mux" }, | ||
1417 | |||
1418 | { "LINEL PGA", NULL, "LINEL Mux" }, | ||
1419 | { "LINER PGA", NULL, "LINER Mux" }, | ||
1420 | }; | ||
1421 | |||
1422 | static const struct snd_soc_dapm_route wm8912_intercon[] = { | ||
1423 | { "HPL PGA", NULL, "DACL" }, | ||
1424 | { "HPR PGA", NULL, "DACR" }, | ||
1425 | |||
1426 | { "LINEL PGA", NULL, "DACL" }, | ||
1427 | { "LINER PGA", NULL, "DACR" }, | ||
1428 | }; | ||
1429 | |||
1430 | static int wm8904_add_widgets(struct snd_soc_codec *codec) | ||
1431 | { | ||
1432 | struct wm8904_priv *wm8904 = codec->private_data; | ||
1433 | |||
1434 | snd_soc_dapm_new_controls(codec, wm8904_core_dapm_widgets, | ||
1435 | ARRAY_SIZE(wm8904_core_dapm_widgets)); | ||
1436 | snd_soc_dapm_add_routes(codec, core_intercon, | ||
1437 | ARRAY_SIZE(core_intercon)); | ||
1438 | |||
1439 | switch (wm8904->devtype) { | ||
1440 | case WM8904: | ||
1441 | snd_soc_add_controls(codec, wm8904_adc_snd_controls, | ||
1442 | ARRAY_SIZE(wm8904_adc_snd_controls)); | ||
1443 | snd_soc_add_controls(codec, wm8904_dac_snd_controls, | ||
1444 | ARRAY_SIZE(wm8904_dac_snd_controls)); | ||
1445 | snd_soc_add_controls(codec, wm8904_snd_controls, | ||
1446 | ARRAY_SIZE(wm8904_snd_controls)); | ||
1447 | |||
1448 | snd_soc_dapm_new_controls(codec, wm8904_adc_dapm_widgets, | ||
1449 | ARRAY_SIZE(wm8904_adc_dapm_widgets)); | ||
1450 | snd_soc_dapm_new_controls(codec, wm8904_dac_dapm_widgets, | ||
1451 | ARRAY_SIZE(wm8904_dac_dapm_widgets)); | ||
1452 | snd_soc_dapm_new_controls(codec, wm8904_dapm_widgets, | ||
1453 | ARRAY_SIZE(wm8904_dapm_widgets)); | ||
1454 | |||
1455 | snd_soc_dapm_add_routes(codec, core_intercon, | ||
1456 | ARRAY_SIZE(core_intercon)); | ||
1457 | snd_soc_dapm_add_routes(codec, adc_intercon, | ||
1458 | ARRAY_SIZE(adc_intercon)); | ||
1459 | snd_soc_dapm_add_routes(codec, dac_intercon, | ||
1460 | ARRAY_SIZE(dac_intercon)); | ||
1461 | snd_soc_dapm_add_routes(codec, wm8904_intercon, | ||
1462 | ARRAY_SIZE(wm8904_intercon)); | ||
1463 | break; | ||
1464 | |||
1465 | case WM8912: | ||
1466 | snd_soc_add_controls(codec, wm8904_dac_snd_controls, | ||
1467 | ARRAY_SIZE(wm8904_dac_snd_controls)); | ||
1468 | |||
1469 | snd_soc_dapm_new_controls(codec, wm8904_dac_dapm_widgets, | ||
1470 | ARRAY_SIZE(wm8904_dac_dapm_widgets)); | ||
1471 | |||
1472 | snd_soc_dapm_add_routes(codec, dac_intercon, | ||
1473 | ARRAY_SIZE(dac_intercon)); | ||
1474 | snd_soc_dapm_add_routes(codec, wm8912_intercon, | ||
1475 | ARRAY_SIZE(wm8912_intercon)); | ||
1476 | break; | ||
1477 | } | ||
1478 | |||
1479 | snd_soc_dapm_new_widgets(codec); | ||
1480 | return 0; | ||
1481 | } | ||
1482 | |||
1483 | static struct { | ||
1484 | int ratio; | ||
1485 | unsigned int clk_sys_rate; | ||
1486 | } clk_sys_rates[] = { | ||
1487 | { 64, 0 }, | ||
1488 | { 128, 1 }, | ||
1489 | { 192, 2 }, | ||
1490 | { 256, 3 }, | ||
1491 | { 384, 4 }, | ||
1492 | { 512, 5 }, | ||
1493 | { 786, 6 }, | ||
1494 | { 1024, 7 }, | ||
1495 | { 1408, 8 }, | ||
1496 | { 1536, 9 }, | ||
1497 | }; | ||
1498 | |||
1499 | static struct { | ||
1500 | int rate; | ||
1501 | int sample_rate; | ||
1502 | } sample_rates[] = { | ||
1503 | { 8000, 0 }, | ||
1504 | { 11025, 1 }, | ||
1505 | { 12000, 1 }, | ||
1506 | { 16000, 2 }, | ||
1507 | { 22050, 3 }, | ||
1508 | { 24000, 3 }, | ||
1509 | { 32000, 4 }, | ||
1510 | { 44100, 5 }, | ||
1511 | { 48000, 5 }, | ||
1512 | }; | ||
1513 | |||
1514 | static struct { | ||
1515 | int div; /* *10 due to .5s */ | ||
1516 | int bclk_div; | ||
1517 | } bclk_divs[] = { | ||
1518 | { 10, 0 }, | ||
1519 | { 15, 1 }, | ||
1520 | { 20, 2 }, | ||
1521 | { 30, 3 }, | ||
1522 | { 40, 4 }, | ||
1523 | { 50, 5 }, | ||
1524 | { 55, 6 }, | ||
1525 | { 60, 7 }, | ||
1526 | { 80, 8 }, | ||
1527 | { 100, 9 }, | ||
1528 | { 110, 10 }, | ||
1529 | { 120, 11 }, | ||
1530 | { 160, 12 }, | ||
1531 | { 200, 13 }, | ||
1532 | { 220, 14 }, | ||
1533 | { 240, 16 }, | ||
1534 | { 200, 17 }, | ||
1535 | { 320, 18 }, | ||
1536 | { 440, 19 }, | ||
1537 | { 480, 20 }, | ||
1538 | }; | ||
1539 | |||
1540 | |||
1541 | static int wm8904_hw_params(struct snd_pcm_substream *substream, | ||
1542 | struct snd_pcm_hw_params *params, | ||
1543 | struct snd_soc_dai *dai) | ||
1544 | { | ||
1545 | struct snd_soc_codec *codec = dai->codec; | ||
1546 | struct wm8904_priv *wm8904 = codec->private_data; | ||
1547 | int ret, i, best, best_val, cur_val; | ||
1548 | unsigned int aif1 = 0; | ||
1549 | unsigned int aif2 = 0; | ||
1550 | unsigned int aif3 = 0; | ||
1551 | unsigned int clock1 = 0; | ||
1552 | unsigned int dac_digital1 = 0; | ||
1553 | |||
1554 | /* What BCLK do we need? */ | ||
1555 | wm8904->fs = params_rate(params); | ||
1556 | if (wm8904->tdm_slots) { | ||
1557 | dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n", | ||
1558 | wm8904->tdm_slots, wm8904->tdm_width); | ||
1559 | wm8904->bclk = snd_soc_calc_bclk(wm8904->fs, | ||
1560 | wm8904->tdm_width, 2, | ||
1561 | wm8904->tdm_slots); | ||
1562 | } else { | ||
1563 | wm8904->bclk = snd_soc_params_to_bclk(params); | ||
1564 | } | ||
1565 | |||
1566 | switch (params_format(params)) { | ||
1567 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1568 | break; | ||
1569 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1570 | aif1 |= 0x40; | ||
1571 | break; | ||
1572 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1573 | aif1 |= 0x80; | ||
1574 | break; | ||
1575 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1576 | aif1 |= 0xc0; | ||
1577 | break; | ||
1578 | default: | ||
1579 | return -EINVAL; | ||
1580 | } | ||
1581 | |||
1582 | |||
1583 | dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8904->bclk); | ||
1584 | |||
1585 | ret = wm8904_configure_clocking(codec); | ||
1586 | if (ret != 0) | ||
1587 | return ret; | ||
1588 | |||
1589 | /* Select nearest CLK_SYS_RATE */ | ||
1590 | best = 0; | ||
1591 | best_val = abs((wm8904->sysclk_rate / clk_sys_rates[0].ratio) | ||
1592 | - wm8904->fs); | ||
1593 | for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { | ||
1594 | cur_val = abs((wm8904->sysclk_rate / | ||
1595 | clk_sys_rates[i].ratio) - wm8904->fs);; | ||
1596 | if (cur_val < best_val) { | ||
1597 | best = i; | ||
1598 | best_val = cur_val; | ||
1599 | } | ||
1600 | } | ||
1601 | dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", | ||
1602 | clk_sys_rates[best].ratio); | ||
1603 | clock1 |= (clk_sys_rates[best].clk_sys_rate | ||
1604 | << WM8904_CLK_SYS_RATE_SHIFT); | ||
1605 | |||
1606 | /* SAMPLE_RATE */ | ||
1607 | best = 0; | ||
1608 | best_val = abs(wm8904->fs - sample_rates[0].rate); | ||
1609 | for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { | ||
1610 | /* Closest match */ | ||
1611 | cur_val = abs(wm8904->fs - sample_rates[i].rate); | ||
1612 | if (cur_val < best_val) { | ||
1613 | best = i; | ||
1614 | best_val = cur_val; | ||
1615 | } | ||
1616 | } | ||
1617 | dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", | ||
1618 | sample_rates[best].rate); | ||
1619 | clock1 |= (sample_rates[best].sample_rate | ||
1620 | << WM8904_SAMPLE_RATE_SHIFT); | ||
1621 | |||
1622 | /* Enable sloping stopband filter for low sample rates */ | ||
1623 | if (wm8904->fs <= 24000) | ||
1624 | dac_digital1 |= WM8904_DAC_SB_FILT; | ||
1625 | |||
1626 | /* BCLK_DIV */ | ||
1627 | best = 0; | ||
1628 | best_val = INT_MAX; | ||
1629 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1630 | cur_val = ((wm8904->sysclk_rate * 10) / bclk_divs[i].div) | ||
1631 | - wm8904->bclk; | ||
1632 | if (cur_val < 0) /* Table is sorted */ | ||
1633 | break; | ||
1634 | if (cur_val < best_val) { | ||
1635 | best = i; | ||
1636 | best_val = cur_val; | ||
1637 | } | ||
1638 | } | ||
1639 | wm8904->bclk = (wm8904->sysclk_rate * 10) / bclk_divs[best].div; | ||
1640 | dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", | ||
1641 | bclk_divs[best].div, wm8904->bclk); | ||
1642 | aif2 |= bclk_divs[best].bclk_div; | ||
1643 | |||
1644 | /* LRCLK is a simple fraction of BCLK */ | ||
1645 | dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8904->bclk / wm8904->fs); | ||
1646 | aif3 |= wm8904->bclk / wm8904->fs; | ||
1647 | |||
1648 | /* Apply the settings */ | ||
1649 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, | ||
1650 | WM8904_DAC_SB_FILT, dac_digital1); | ||
1651 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, | ||
1652 | WM8904_AIF_WL_MASK, aif1); | ||
1653 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_2, | ||
1654 | WM8904_BCLK_DIV_MASK, aif2); | ||
1655 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_3, | ||
1656 | WM8904_LRCLK_RATE_MASK, aif3); | ||
1657 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_1, | ||
1658 | WM8904_SAMPLE_RATE_MASK | | ||
1659 | WM8904_CLK_SYS_RATE_MASK, clock1); | ||
1660 | |||
1661 | /* Update filters for the new settings */ | ||
1662 | wm8904_set_retune_mobile(codec); | ||
1663 | wm8904_set_deemph(codec); | ||
1664 | |||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | |||
1669 | static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
1670 | unsigned int freq, int dir) | ||
1671 | { | ||
1672 | struct snd_soc_codec *codec = dai->codec; | ||
1673 | struct wm8904_priv *priv = codec->private_data; | ||
1674 | |||
1675 | switch (clk_id) { | ||
1676 | case WM8904_CLK_MCLK: | ||
1677 | priv->sysclk_src = clk_id; | ||
1678 | priv->mclk_rate = freq; | ||
1679 | break; | ||
1680 | |||
1681 | case WM8904_CLK_FLL: | ||
1682 | priv->sysclk_src = clk_id; | ||
1683 | break; | ||
1684 | |||
1685 | default: | ||
1686 | return -EINVAL; | ||
1687 | } | ||
1688 | |||
1689 | dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); | ||
1690 | |||
1691 | wm8904_configure_clocking(codec); | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1696 | static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
1697 | { | ||
1698 | struct snd_soc_codec *codec = dai->codec; | ||
1699 | unsigned int aif1 = 0; | ||
1700 | unsigned int aif3 = 0; | ||
1701 | |||
1702 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1703 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1704 | break; | ||
1705 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1706 | aif3 |= WM8904_LRCLK_DIR; | ||
1707 | break; | ||
1708 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1709 | aif1 |= WM8904_BCLK_DIR; | ||
1710 | break; | ||
1711 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1712 | aif1 |= WM8904_BCLK_DIR; | ||
1713 | aif3 |= WM8904_LRCLK_DIR; | ||
1714 | break; | ||
1715 | default: | ||
1716 | return -EINVAL; | ||
1717 | } | ||
1718 | |||
1719 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1720 | case SND_SOC_DAIFMT_DSP_B: | ||
1721 | aif1 |= WM8904_AIF_LRCLK_INV; | ||
1722 | case SND_SOC_DAIFMT_DSP_A: | ||
1723 | aif1 |= 0x3; | ||
1724 | break; | ||
1725 | case SND_SOC_DAIFMT_I2S: | ||
1726 | aif1 |= 0x2; | ||
1727 | break; | ||
1728 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1729 | break; | ||
1730 | case SND_SOC_DAIFMT_LEFT_J: | ||
1731 | aif1 |= 0x1; | ||
1732 | break; | ||
1733 | default: | ||
1734 | return -EINVAL; | ||
1735 | } | ||
1736 | |||
1737 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1738 | case SND_SOC_DAIFMT_DSP_A: | ||
1739 | case SND_SOC_DAIFMT_DSP_B: | ||
1740 | /* frame inversion not valid for DSP modes */ | ||
1741 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1742 | case SND_SOC_DAIFMT_NB_NF: | ||
1743 | break; | ||
1744 | case SND_SOC_DAIFMT_IB_NF: | ||
1745 | aif1 |= WM8904_AIF_BCLK_INV; | ||
1746 | break; | ||
1747 | default: | ||
1748 | return -EINVAL; | ||
1749 | } | ||
1750 | break; | ||
1751 | |||
1752 | case SND_SOC_DAIFMT_I2S: | ||
1753 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1754 | case SND_SOC_DAIFMT_LEFT_J: | ||
1755 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1756 | case SND_SOC_DAIFMT_NB_NF: | ||
1757 | break; | ||
1758 | case SND_SOC_DAIFMT_IB_IF: | ||
1759 | aif1 |= WM8904_AIF_BCLK_INV | WM8904_AIF_LRCLK_INV; | ||
1760 | break; | ||
1761 | case SND_SOC_DAIFMT_IB_NF: | ||
1762 | aif1 |= WM8904_AIF_BCLK_INV; | ||
1763 | break; | ||
1764 | case SND_SOC_DAIFMT_NB_IF: | ||
1765 | aif1 |= WM8904_AIF_LRCLK_INV; | ||
1766 | break; | ||
1767 | default: | ||
1768 | return -EINVAL; | ||
1769 | } | ||
1770 | break; | ||
1771 | default: | ||
1772 | return -EINVAL; | ||
1773 | } | ||
1774 | |||
1775 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, | ||
1776 | WM8904_AIF_BCLK_INV | WM8904_AIF_LRCLK_INV | | ||
1777 | WM8904_AIF_FMT_MASK | WM8904_BCLK_DIR, aif1); | ||
1778 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_3, | ||
1779 | WM8904_LRCLK_DIR, aif3); | ||
1780 | |||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | |||
1785 | static int wm8904_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
1786 | unsigned int rx_mask, int slots, int slot_width) | ||
1787 | { | ||
1788 | struct snd_soc_codec *codec = dai->codec; | ||
1789 | struct wm8904_priv *wm8904 = codec->private_data; | ||
1790 | int aif1 = 0; | ||
1791 | |||
1792 | /* Don't need to validate anything if we're turning off TDM */ | ||
1793 | if (slots == 0) | ||
1794 | goto out; | ||
1795 | |||
1796 | /* Note that we allow configurations we can't handle ourselves - | ||
1797 | * for example, we can generate clocks for slots 2 and up even if | ||
1798 | * we can't use those slots ourselves. | ||
1799 | */ | ||
1800 | aif1 |= WM8904_AIFADC_TDM | WM8904_AIFDAC_TDM; | ||
1801 | |||
1802 | switch (rx_mask) { | ||
1803 | case 3: | ||
1804 | break; | ||
1805 | case 0xc: | ||
1806 | aif1 |= WM8904_AIFADC_TDM_CHAN; | ||
1807 | break; | ||
1808 | default: | ||
1809 | return -EINVAL; | ||
1810 | } | ||
1811 | |||
1812 | |||
1813 | switch (tx_mask) { | ||
1814 | case 3: | ||
1815 | break; | ||
1816 | case 0xc: | ||
1817 | aif1 |= WM8904_AIFDAC_TDM_CHAN; | ||
1818 | break; | ||
1819 | default: | ||
1820 | return -EINVAL; | ||
1821 | } | ||
1822 | |||
1823 | out: | ||
1824 | wm8904->tdm_width = slot_width; | ||
1825 | wm8904->tdm_slots = slots / 2; | ||
1826 | |||
1827 | snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, | ||
1828 | WM8904_AIFADC_TDM | WM8904_AIFADC_TDM_CHAN | | ||
1829 | WM8904_AIFDAC_TDM | WM8904_AIFDAC_TDM_CHAN, aif1); | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | struct _fll_div { | ||
1835 | u16 fll_fratio; | ||
1836 | u16 fll_outdiv; | ||
1837 | u16 fll_clk_ref_div; | ||
1838 | u16 n; | ||
1839 | u16 k; | ||
1840 | }; | ||
1841 | |||
1842 | /* The size in bits of the FLL divide multiplied by 10 | ||
1843 | * to allow rounding later */ | ||
1844 | #define FIXED_FLL_SIZE ((1 << 16) * 10) | ||
1845 | |||
1846 | static struct { | ||
1847 | unsigned int min; | ||
1848 | unsigned int max; | ||
1849 | u16 fll_fratio; | ||
1850 | int ratio; | ||
1851 | } fll_fratios[] = { | ||
1852 | { 0, 64000, 4, 16 }, | ||
1853 | { 64000, 128000, 3, 8 }, | ||
1854 | { 128000, 256000, 2, 4 }, | ||
1855 | { 256000, 1000000, 1, 2 }, | ||
1856 | { 1000000, 13500000, 0, 1 }, | ||
1857 | }; | ||
1858 | |||
1859 | static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | ||
1860 | unsigned int Fout) | ||
1861 | { | ||
1862 | u64 Kpart; | ||
1863 | unsigned int K, Ndiv, Nmod, target; | ||
1864 | unsigned int div; | ||
1865 | int i; | ||
1866 | |||
1867 | /* Fref must be <=13.5MHz */ | ||
1868 | div = 1; | ||
1869 | fll_div->fll_clk_ref_div = 0; | ||
1870 | while ((Fref / div) > 13500000) { | ||
1871 | div *= 2; | ||
1872 | fll_div->fll_clk_ref_div++; | ||
1873 | |||
1874 | if (div > 8) { | ||
1875 | pr_err("Can't scale %dMHz input down to <=13.5MHz\n", | ||
1876 | Fref); | ||
1877 | return -EINVAL; | ||
1878 | } | ||
1879 | } | ||
1880 | |||
1881 | pr_debug("Fref=%u Fout=%u\n", Fref, Fout); | ||
1882 | |||
1883 | /* Apply the division for our remaining calculations */ | ||
1884 | Fref /= div; | ||
1885 | |||
1886 | /* Fvco should be 90-100MHz; don't check the upper bound */ | ||
1887 | div = 4; | ||
1888 | while (Fout * div < 90000000) { | ||
1889 | div++; | ||
1890 | if (div > 64) { | ||
1891 | pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", | ||
1892 | Fout); | ||
1893 | return -EINVAL; | ||
1894 | } | ||
1895 | } | ||
1896 | target = Fout * div; | ||
1897 | fll_div->fll_outdiv = div - 1; | ||
1898 | |||
1899 | pr_debug("Fvco=%dHz\n", target); | ||
1900 | |||
1901 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | ||
1902 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | ||
1903 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | ||
1904 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; | ||
1905 | target /= fll_fratios[i].ratio; | ||
1906 | break; | ||
1907 | } | ||
1908 | } | ||
1909 | if (i == ARRAY_SIZE(fll_fratios)) { | ||
1910 | pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); | ||
1911 | return -EINVAL; | ||
1912 | } | ||
1913 | |||
1914 | /* Now, calculate N.K */ | ||
1915 | Ndiv = target / Fref; | ||
1916 | |||
1917 | fll_div->n = Ndiv; | ||
1918 | Nmod = target % Fref; | ||
1919 | pr_debug("Nmod=%d\n", Nmod); | ||
1920 | |||
1921 | /* Calculate fractional part - scale up so we can round. */ | ||
1922 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
1923 | |||
1924 | do_div(Kpart, Fref); | ||
1925 | |||
1926 | K = Kpart & 0xFFFFFFFF; | ||
1927 | |||
1928 | if ((K % 10) >= 5) | ||
1929 | K += 5; | ||
1930 | |||
1931 | /* Move down to proper range now rounding is done */ | ||
1932 | fll_div->k = K / 10; | ||
1933 | |||
1934 | pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", | ||
1935 | fll_div->n, fll_div->k, | ||
1936 | fll_div->fll_fratio, fll_div->fll_outdiv, | ||
1937 | fll_div->fll_clk_ref_div); | ||
1938 | |||
1939 | return 0; | ||
1940 | } | ||
1941 | |||
1942 | static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | ||
1943 | unsigned int Fref, unsigned int Fout) | ||
1944 | { | ||
1945 | struct snd_soc_codec *codec = dai->codec; | ||
1946 | struct wm8904_priv *wm8904 = codec->private_data; | ||
1947 | struct _fll_div fll_div; | ||
1948 | int ret, val; | ||
1949 | int clock2, fll1; | ||
1950 | |||
1951 | /* Any change? */ | ||
1952 | if (source == wm8904->fll_src && Fref == wm8904->fll_fref && | ||
1953 | Fout == wm8904->fll_fout) | ||
1954 | return 0; | ||
1955 | |||
1956 | clock2 = snd_soc_read(codec, WM8904_CLOCK_RATES_2); | ||
1957 | |||
1958 | if (Fout == 0) { | ||
1959 | dev_dbg(codec->dev, "FLL disabled\n"); | ||
1960 | |||
1961 | wm8904->fll_fref = 0; | ||
1962 | wm8904->fll_fout = 0; | ||
1963 | |||
1964 | /* Gate SYSCLK to avoid glitches */ | ||
1965 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, | ||
1966 | WM8904_CLK_SYS_ENA, 0); | ||
1967 | |||
1968 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
1969 | WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); | ||
1970 | |||
1971 | goto out; | ||
1972 | } | ||
1973 | |||
1974 | /* Validate the FLL ID */ | ||
1975 | switch (source) { | ||
1976 | case WM8904_FLL_MCLK: | ||
1977 | case WM8904_FLL_LRCLK: | ||
1978 | case WM8904_FLL_BCLK: | ||
1979 | ret = fll_factors(&fll_div, Fref, Fout); | ||
1980 | if (ret != 0) | ||
1981 | return ret; | ||
1982 | break; | ||
1983 | |||
1984 | case WM8904_FLL_FREE_RUNNING: | ||
1985 | dev_dbg(codec->dev, "Using free running FLL\n"); | ||
1986 | /* Force 12MHz and output/4 for now */ | ||
1987 | Fout = 12000000; | ||
1988 | Fref = 12000000; | ||
1989 | |||
1990 | memset(&fll_div, 0, sizeof(fll_div)); | ||
1991 | fll_div.fll_outdiv = 3; | ||
1992 | break; | ||
1993 | |||
1994 | default: | ||
1995 | dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); | ||
1996 | return -EINVAL; | ||
1997 | } | ||
1998 | |||
1999 | /* Save current state then disable the FLL and SYSCLK to avoid | ||
2000 | * misclocking */ | ||
2001 | fll1 = snd_soc_read(codec, WM8904_FLL_CONTROL_1); | ||
2002 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, | ||
2003 | WM8904_CLK_SYS_ENA, 0); | ||
2004 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
2005 | WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); | ||
2006 | |||
2007 | /* Unlock forced oscilator control to switch it on/off */ | ||
2008 | snd_soc_update_bits(codec, WM8904_CONTROL_INTERFACE_TEST_1, | ||
2009 | WM8904_USER_KEY, WM8904_USER_KEY); | ||
2010 | |||
2011 | if (fll_id == WM8904_FLL_FREE_RUNNING) { | ||
2012 | val = WM8904_FLL_FRC_NCO; | ||
2013 | } else { | ||
2014 | val = 0; | ||
2015 | } | ||
2016 | |||
2017 | snd_soc_update_bits(codec, WM8904_FLL_NCO_TEST_1, WM8904_FLL_FRC_NCO, | ||
2018 | val); | ||
2019 | snd_soc_update_bits(codec, WM8904_CONTROL_INTERFACE_TEST_1, | ||
2020 | WM8904_USER_KEY, 0); | ||
2021 | |||
2022 | switch (fll_id) { | ||
2023 | case WM8904_FLL_MCLK: | ||
2024 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, | ||
2025 | WM8904_FLL_CLK_REF_SRC_MASK, 0); | ||
2026 | break; | ||
2027 | |||
2028 | case WM8904_FLL_LRCLK: | ||
2029 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, | ||
2030 | WM8904_FLL_CLK_REF_SRC_MASK, 1); | ||
2031 | break; | ||
2032 | |||
2033 | case WM8904_FLL_BCLK: | ||
2034 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, | ||
2035 | WM8904_FLL_CLK_REF_SRC_MASK, 2); | ||
2036 | break; | ||
2037 | } | ||
2038 | |||
2039 | if (fll_div.k) | ||
2040 | val = WM8904_FLL_FRACN_ENA; | ||
2041 | else | ||
2042 | val = 0; | ||
2043 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
2044 | WM8904_FLL_FRACN_ENA, val); | ||
2045 | |||
2046 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_2, | ||
2047 | WM8904_FLL_OUTDIV_MASK | WM8904_FLL_FRATIO_MASK, | ||
2048 | (fll_div.fll_outdiv << WM8904_FLL_OUTDIV_SHIFT) | | ||
2049 | (fll_div.fll_fratio << WM8904_FLL_FRATIO_SHIFT)); | ||
2050 | |||
2051 | snd_soc_write(codec, WM8904_FLL_CONTROL_3, fll_div.k); | ||
2052 | |||
2053 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_4, WM8904_FLL_N_MASK, | ||
2054 | fll_div.n << WM8904_FLL_N_SHIFT); | ||
2055 | |||
2056 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, | ||
2057 | WM8904_FLL_CLK_REF_DIV_MASK, | ||
2058 | fll_div.fll_clk_ref_div | ||
2059 | << WM8904_FLL_CLK_REF_DIV_SHIFT); | ||
2060 | |||
2061 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | ||
2062 | |||
2063 | wm8904->fll_fref = Fref; | ||
2064 | wm8904->fll_fout = Fout; | ||
2065 | wm8904->fll_src = source; | ||
2066 | |||
2067 | /* Enable the FLL if it was previously active */ | ||
2068 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
2069 | WM8904_FLL_OSC_ENA, fll1); | ||
2070 | snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, | ||
2071 | WM8904_FLL_ENA, fll1); | ||
2072 | |||
2073 | out: | ||
2074 | /* Reenable SYSCLK if it was previously active */ | ||
2075 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, | ||
2076 | WM8904_CLK_SYS_ENA, clock2); | ||
2077 | |||
2078 | return 0; | ||
2079 | } | ||
2080 | |||
2081 | static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) | ||
2082 | { | ||
2083 | struct snd_soc_codec *codec = codec_dai->codec; | ||
2084 | int val; | ||
2085 | |||
2086 | if (mute) | ||
2087 | val = WM8904_DAC_MUTE; | ||
2088 | else | ||
2089 | val = 0; | ||
2090 | |||
2091 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, WM8904_DAC_MUTE, val); | ||
2092 | |||
2093 | return 0; | ||
2094 | } | ||
2095 | |||
2096 | static void wm8904_sync_cache(struct snd_soc_codec *codec) | ||
2097 | { | ||
2098 | struct wm8904_priv *wm8904 = codec->private_data; | ||
2099 | int i; | ||
2100 | |||
2101 | if (!codec->cache_sync) | ||
2102 | return; | ||
2103 | |||
2104 | codec->cache_only = 0; | ||
2105 | |||
2106 | /* Sync back cached values if they're different from the | ||
2107 | * hardware default. | ||
2108 | */ | ||
2109 | for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { | ||
2110 | if (!wm8904_access[i].writable) | ||
2111 | continue; | ||
2112 | |||
2113 | if (wm8904->reg_cache[i] == wm8904_reg[i]) | ||
2114 | continue; | ||
2115 | |||
2116 | snd_soc_write(codec, i, wm8904->reg_cache[i]); | ||
2117 | } | ||
2118 | |||
2119 | codec->cache_sync = 0; | ||
2120 | } | ||
2121 | |||
2122 | static int wm8904_set_bias_level(struct snd_soc_codec *codec, | ||
2123 | enum snd_soc_bias_level level) | ||
2124 | { | ||
2125 | struct wm8904_priv *wm8904 = codec->private_data; | ||
2126 | int ret; | ||
2127 | |||
2128 | switch (level) { | ||
2129 | case SND_SOC_BIAS_ON: | ||
2130 | break; | ||
2131 | |||
2132 | case SND_SOC_BIAS_PREPARE: | ||
2133 | /* VMID resistance 2*50k */ | ||
2134 | snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, | ||
2135 | WM8904_VMID_RES_MASK, | ||
2136 | 0x1 << WM8904_VMID_RES_SHIFT); | ||
2137 | |||
2138 | /* Normal bias current */ | ||
2139 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | ||
2140 | WM8904_ISEL_MASK, 2 << WM8904_ISEL_SHIFT); | ||
2141 | break; | ||
2142 | |||
2143 | case SND_SOC_BIAS_STANDBY: | ||
2144 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
2145 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | ||
2146 | wm8904->supplies); | ||
2147 | if (ret != 0) { | ||
2148 | dev_err(codec->dev, | ||
2149 | "Failed to enable supplies: %d\n", | ||
2150 | ret); | ||
2151 | return ret; | ||
2152 | } | ||
2153 | |||
2154 | wm8904_sync_cache(codec); | ||
2155 | |||
2156 | /* Enable bias */ | ||
2157 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | ||
2158 | WM8904_BIAS_ENA, WM8904_BIAS_ENA); | ||
2159 | |||
2160 | /* Enable VMID, VMID buffering, 2*5k resistance */ | ||
2161 | snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, | ||
2162 | WM8904_VMID_ENA | | ||
2163 | WM8904_VMID_RES_MASK, | ||
2164 | WM8904_VMID_ENA | | ||
2165 | 0x3 << WM8904_VMID_RES_SHIFT); | ||
2166 | |||
2167 | /* Let VMID ramp */ | ||
2168 | msleep(1); | ||
2169 | } | ||
2170 | |||
2171 | /* Maintain VMID with 2*250k */ | ||
2172 | snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, | ||
2173 | WM8904_VMID_RES_MASK, | ||
2174 | 0x2 << WM8904_VMID_RES_SHIFT); | ||
2175 | |||
2176 | /* Bias current *0.5 */ | ||
2177 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | ||
2178 | WM8904_ISEL_MASK, 0); | ||
2179 | break; | ||
2180 | |||
2181 | case SND_SOC_BIAS_OFF: | ||
2182 | /* Turn off VMID */ | ||
2183 | snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, | ||
2184 | WM8904_VMID_RES_MASK | WM8904_VMID_ENA, 0); | ||
2185 | |||
2186 | /* Stop bias generation */ | ||
2187 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | ||
2188 | WM8904_BIAS_ENA, 0); | ||
2189 | |||
2190 | #ifdef CONFIG_REGULATOR | ||
2191 | /* Post 2.6.34 we will be able to get a callback when | ||
2192 | * the regulators are disabled which we can use but | ||
2193 | * for now just assume that the power will be cut if | ||
2194 | * the regulator API is in use. | ||
2195 | */ | ||
2196 | codec->cache_sync = 1; | ||
2197 | #endif | ||
2198 | |||
2199 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), | ||
2200 | wm8904->supplies); | ||
2201 | break; | ||
2202 | } | ||
2203 | codec->bias_level = level; | ||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | #define WM8904_RATES SNDRV_PCM_RATE_8000_96000 | ||
2208 | |||
2209 | #define WM8904_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
2210 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
2211 | |||
2212 | static struct snd_soc_dai_ops wm8904_dai_ops = { | ||
2213 | .set_sysclk = wm8904_set_sysclk, | ||
2214 | .set_fmt = wm8904_set_fmt, | ||
2215 | .set_tdm_slot = wm8904_set_tdm_slot, | ||
2216 | .set_pll = wm8904_set_fll, | ||
2217 | .hw_params = wm8904_hw_params, | ||
2218 | .digital_mute = wm8904_digital_mute, | ||
2219 | }; | ||
2220 | |||
2221 | struct snd_soc_dai wm8904_dai = { | ||
2222 | .name = "WM8904", | ||
2223 | .playback = { | ||
2224 | .stream_name = "Playback", | ||
2225 | .channels_min = 2, | ||
2226 | .channels_max = 2, | ||
2227 | .rates = WM8904_RATES, | ||
2228 | .formats = WM8904_FORMATS, | ||
2229 | }, | ||
2230 | .capture = { | ||
2231 | .stream_name = "Capture", | ||
2232 | .channels_min = 2, | ||
2233 | .channels_max = 2, | ||
2234 | .rates = WM8904_RATES, | ||
2235 | .formats = WM8904_FORMATS, | ||
2236 | }, | ||
2237 | .ops = &wm8904_dai_ops, | ||
2238 | .symmetric_rates = 1, | ||
2239 | }; | ||
2240 | EXPORT_SYMBOL_GPL(wm8904_dai); | ||
2241 | |||
2242 | #ifdef CONFIG_PM | ||
2243 | static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) | ||
2244 | { | ||
2245 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2246 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2247 | |||
2248 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2249 | |||
2250 | return 0; | ||
2251 | } | ||
2252 | |||
2253 | static int wm8904_resume(struct platform_device *pdev) | ||
2254 | { | ||
2255 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2256 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2257 | |||
2258 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2259 | |||
2260 | return 0; | ||
2261 | } | ||
2262 | #else | ||
2263 | #define wm8904_suspend NULL | ||
2264 | #define wm8904_resume NULL | ||
2265 | #endif | ||
2266 | |||
2267 | static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) | ||
2268 | { | ||
2269 | struct snd_soc_codec *codec = &wm8904->codec; | ||
2270 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
2271 | struct snd_kcontrol_new control = | ||
2272 | SOC_ENUM_EXT("EQ Mode", | ||
2273 | wm8904->retune_mobile_enum, | ||
2274 | wm8904_get_retune_mobile_enum, | ||
2275 | wm8904_put_retune_mobile_enum); | ||
2276 | int ret, i, j; | ||
2277 | const char **t; | ||
2278 | |||
2279 | /* We need an array of texts for the enum API but the number | ||
2280 | * of texts is likely to be less than the number of | ||
2281 | * configurations due to the sample rate dependency of the | ||
2282 | * configurations. */ | ||
2283 | wm8904->num_retune_mobile_texts = 0; | ||
2284 | wm8904->retune_mobile_texts = NULL; | ||
2285 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
2286 | for (j = 0; j < wm8904->num_retune_mobile_texts; j++) { | ||
2287 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
2288 | wm8904->retune_mobile_texts[j]) == 0) | ||
2289 | break; | ||
2290 | } | ||
2291 | |||
2292 | if (j != wm8904->num_retune_mobile_texts) | ||
2293 | continue; | ||
2294 | |||
2295 | /* Expand the array... */ | ||
2296 | t = krealloc(wm8904->retune_mobile_texts, | ||
2297 | sizeof(char *) * | ||
2298 | (wm8904->num_retune_mobile_texts + 1), | ||
2299 | GFP_KERNEL); | ||
2300 | if (t == NULL) | ||
2301 | continue; | ||
2302 | |||
2303 | /* ...store the new entry... */ | ||
2304 | t[wm8904->num_retune_mobile_texts] = | ||
2305 | pdata->retune_mobile_cfgs[i].name; | ||
2306 | |||
2307 | /* ...and remember the new version. */ | ||
2308 | wm8904->num_retune_mobile_texts++; | ||
2309 | wm8904->retune_mobile_texts = t; | ||
2310 | } | ||
2311 | |||
2312 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | ||
2313 | wm8904->num_retune_mobile_texts); | ||
2314 | |||
2315 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; | ||
2316 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; | ||
2317 | |||
2318 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | ||
2319 | if (ret != 0) | ||
2320 | dev_err(wm8904->codec.dev, | ||
2321 | "Failed to add ReTune Mobile control: %d\n", ret); | ||
2322 | } | ||
2323 | |||
2324 | static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | ||
2325 | { | ||
2326 | struct snd_soc_codec *codec = &wm8904->codec; | ||
2327 | struct wm8904_pdata *pdata = wm8904->pdata; | ||
2328 | int ret, i; | ||
2329 | |||
2330 | if (!pdata) { | ||
2331 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | ||
2332 | ARRAY_SIZE(wm8904_eq_controls)); | ||
2333 | return; | ||
2334 | } | ||
2335 | |||
2336 | dev_dbg(codec->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); | ||
2337 | |||
2338 | if (pdata->num_drc_cfgs) { | ||
2339 | struct snd_kcontrol_new control = | ||
2340 | SOC_ENUM_EXT("DRC Mode", wm8904->drc_enum, | ||
2341 | wm8904_get_drc_enum, wm8904_put_drc_enum); | ||
2342 | |||
2343 | /* We need an array of texts for the enum API */ | ||
2344 | wm8904->drc_texts = kmalloc(sizeof(char *) | ||
2345 | * pdata->num_drc_cfgs, GFP_KERNEL); | ||
2346 | if (!wm8904->drc_texts) { | ||
2347 | dev_err(wm8904->codec.dev, | ||
2348 | "Failed to allocate %d DRC config texts\n", | ||
2349 | pdata->num_drc_cfgs); | ||
2350 | return; | ||
2351 | } | ||
2352 | |||
2353 | for (i = 0; i < pdata->num_drc_cfgs; i++) | ||
2354 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; | ||
2355 | |||
2356 | wm8904->drc_enum.max = pdata->num_drc_cfgs; | ||
2357 | wm8904->drc_enum.texts = wm8904->drc_texts; | ||
2358 | |||
2359 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | ||
2360 | if (ret != 0) | ||
2361 | dev_err(wm8904->codec.dev, | ||
2362 | "Failed to add DRC mode control: %d\n", ret); | ||
2363 | |||
2364 | wm8904_set_drc(codec); | ||
2365 | } | ||
2366 | |||
2367 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | ||
2368 | pdata->num_retune_mobile_cfgs); | ||
2369 | |||
2370 | if (pdata->num_retune_mobile_cfgs) | ||
2371 | wm8904_handle_retune_mobile_pdata(wm8904); | ||
2372 | else | ||
2373 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | ||
2374 | ARRAY_SIZE(wm8904_eq_controls)); | ||
2375 | } | ||
2376 | |||
2377 | static int wm8904_probe(struct platform_device *pdev) | ||
2378 | { | ||
2379 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2380 | struct snd_soc_codec *codec; | ||
2381 | int ret = 0; | ||
2382 | |||
2383 | if (wm8904_codec == NULL) { | ||
2384 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
2385 | return -ENODEV; | ||
2386 | } | ||
2387 | |||
2388 | socdev->card->codec = wm8904_codec; | ||
2389 | codec = wm8904_codec; | ||
2390 | |||
2391 | /* register pcms */ | ||
2392 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
2393 | if (ret < 0) { | ||
2394 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
2395 | goto pcm_err; | ||
2396 | } | ||
2397 | |||
2398 | wm8904_handle_pdata(codec->private_data); | ||
2399 | |||
2400 | wm8904_add_widgets(codec); | ||
2401 | |||
2402 | return ret; | ||
2403 | |||
2404 | pcm_err: | ||
2405 | return ret; | ||
2406 | } | ||
2407 | |||
2408 | static int wm8904_remove(struct platform_device *pdev) | ||
2409 | { | ||
2410 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2411 | |||
2412 | snd_soc_free_pcms(socdev); | ||
2413 | snd_soc_dapm_free(socdev); | ||
2414 | |||
2415 | return 0; | ||
2416 | } | ||
2417 | |||
2418 | struct snd_soc_codec_device soc_codec_dev_wm8904 = { | ||
2419 | .probe = wm8904_probe, | ||
2420 | .remove = wm8904_remove, | ||
2421 | .suspend = wm8904_suspend, | ||
2422 | .resume = wm8904_resume, | ||
2423 | }; | ||
2424 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904); | ||
2425 | |||
2426 | static int wm8904_register(struct wm8904_priv *wm8904, | ||
2427 | enum snd_soc_control_type control) | ||
2428 | { | ||
2429 | int ret; | ||
2430 | struct snd_soc_codec *codec = &wm8904->codec; | ||
2431 | int i; | ||
2432 | |||
2433 | if (wm8904_codec) { | ||
2434 | dev_err(codec->dev, "Another WM8904 is registered\n"); | ||
2435 | return -EINVAL; | ||
2436 | } | ||
2437 | |||
2438 | mutex_init(&codec->mutex); | ||
2439 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
2440 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
2441 | |||
2442 | codec->private_data = wm8904; | ||
2443 | codec->name = "WM8904"; | ||
2444 | codec->owner = THIS_MODULE; | ||
2445 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2446 | codec->set_bias_level = wm8904_set_bias_level; | ||
2447 | codec->dai = &wm8904_dai; | ||
2448 | codec->num_dai = 1; | ||
2449 | codec->reg_cache_size = WM8904_MAX_REGISTER; | ||
2450 | codec->reg_cache = &wm8904->reg_cache; | ||
2451 | codec->volatile_register = wm8904_volatile_register; | ||
2452 | codec->cache_sync = 1; | ||
2453 | codec->idle_bias_off = 1; | ||
2454 | |||
2455 | switch (wm8904->devtype) { | ||
2456 | case WM8904: | ||
2457 | break; | ||
2458 | case WM8912: | ||
2459 | memset(&wm8904_dai.capture, 0, sizeof(wm8904_dai.capture)); | ||
2460 | break; | ||
2461 | default: | ||
2462 | dev_err(codec->dev, "Unknown device type %d\n", | ||
2463 | wm8904->devtype); | ||
2464 | return -EINVAL; | ||
2465 | } | ||
2466 | |||
2467 | memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); | ||
2468 | |||
2469 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
2470 | if (ret != 0) { | ||
2471 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2472 | goto err; | ||
2473 | } | ||
2474 | |||
2475 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | ||
2476 | wm8904->supplies[i].supply = wm8904_supply_names[i]; | ||
2477 | |||
2478 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies), | ||
2479 | wm8904->supplies); | ||
2480 | if (ret != 0) { | ||
2481 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
2482 | goto err; | ||
2483 | } | ||
2484 | |||
2485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | ||
2486 | wm8904->supplies); | ||
2487 | if (ret != 0) { | ||
2488 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
2489 | goto err_get; | ||
2490 | } | ||
2491 | |||
2492 | ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID); | ||
2493 | if (ret < 0) { | ||
2494 | dev_err(codec->dev, "Failed to read ID register\n"); | ||
2495 | goto err_enable; | ||
2496 | } | ||
2497 | if (ret != wm8904_reg[WM8904_SW_RESET_AND_ID]) { | ||
2498 | dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret); | ||
2499 | ret = -EINVAL; | ||
2500 | goto err_enable; | ||
2501 | } | ||
2502 | |||
2503 | ret = snd_soc_read(codec, WM8904_REVISION); | ||
2504 | if (ret < 0) { | ||
2505 | dev_err(codec->dev, "Failed to read device revision: %d\n", | ||
2506 | ret); | ||
2507 | goto err_enable; | ||
2508 | } | ||
2509 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | ||
2510 | |||
2511 | ret = wm8904_reset(codec); | ||
2512 | if (ret < 0) { | ||
2513 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
2514 | goto err_enable; | ||
2515 | } | ||
2516 | |||
2517 | wm8904_dai.dev = codec->dev; | ||
2518 | |||
2519 | /* Change some default settings - latch VU and enable ZC */ | ||
2520 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; | ||
2521 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; | ||
2522 | wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; | ||
2523 | wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; | ||
2524 | wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | | ||
2525 | WM8904_HPOUTLZC; | ||
2526 | wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | | ||
2527 | WM8904_HPOUTRZC; | ||
2528 | wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | | ||
2529 | WM8904_LINEOUTLZC; | ||
2530 | wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | | ||
2531 | WM8904_LINEOUTRZC; | ||
2532 | wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; | ||
2533 | |||
2534 | /* Set Class W by default - this will be managed by the Class | ||
2535 | * G widget at runtime where bypass paths are available. | ||
2536 | */ | ||
2537 | wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; | ||
2538 | |||
2539 | /* Use normal bias source */ | ||
2540 | wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; | ||
2541 | |||
2542 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2543 | |||
2544 | /* Bias level configuration will have done an extra enable */ | ||
2545 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2546 | |||
2547 | wm8904_codec = codec; | ||
2548 | |||
2549 | ret = snd_soc_register_codec(codec); | ||
2550 | if (ret != 0) { | ||
2551 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2552 | return ret; | ||
2553 | } | ||
2554 | |||
2555 | ret = snd_soc_register_dai(&wm8904_dai); | ||
2556 | if (ret != 0) { | ||
2557 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
2558 | snd_soc_unregister_codec(codec); | ||
2559 | return ret; | ||
2560 | } | ||
2561 | |||
2562 | return 0; | ||
2563 | |||
2564 | err_enable: | ||
2565 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2566 | err_get: | ||
2567 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2568 | err: | ||
2569 | kfree(wm8904); | ||
2570 | return ret; | ||
2571 | } | ||
2572 | |||
2573 | static void wm8904_unregister(struct wm8904_priv *wm8904) | ||
2574 | { | ||
2575 | wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); | ||
2576 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2577 | snd_soc_unregister_dai(&wm8904_dai); | ||
2578 | snd_soc_unregister_codec(&wm8904->codec); | ||
2579 | kfree(wm8904); | ||
2580 | wm8904_codec = NULL; | ||
2581 | } | ||
2582 | |||
2583 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
2584 | static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | ||
2585 | const struct i2c_device_id *id) | ||
2586 | { | ||
2587 | struct wm8904_priv *wm8904; | ||
2588 | struct snd_soc_codec *codec; | ||
2589 | |||
2590 | wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); | ||
2591 | if (wm8904 == NULL) | ||
2592 | return -ENOMEM; | ||
2593 | |||
2594 | codec = &wm8904->codec; | ||
2595 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
2596 | |||
2597 | wm8904->devtype = id->driver_data; | ||
2598 | |||
2599 | i2c_set_clientdata(i2c, wm8904); | ||
2600 | codec->control_data = i2c; | ||
2601 | wm8904->pdata = i2c->dev.platform_data; | ||
2602 | |||
2603 | codec->dev = &i2c->dev; | ||
2604 | |||
2605 | return wm8904_register(wm8904, SND_SOC_I2C); | ||
2606 | } | ||
2607 | |||
2608 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) | ||
2609 | { | ||
2610 | struct wm8904_priv *wm8904 = i2c_get_clientdata(client); | ||
2611 | wm8904_unregister(wm8904); | ||
2612 | return 0; | ||
2613 | } | ||
2614 | |||
2615 | static const struct i2c_device_id wm8904_i2c_id[] = { | ||
2616 | { "wm8904", WM8904 }, | ||
2617 | { "wm8912", WM8912 }, | ||
2618 | { } | ||
2619 | }; | ||
2620 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | ||
2621 | |||
2622 | static struct i2c_driver wm8904_i2c_driver = { | ||
2623 | .driver = { | ||
2624 | .name = "WM8904", | ||
2625 | .owner = THIS_MODULE, | ||
2626 | }, | ||
2627 | .probe = wm8904_i2c_probe, | ||
2628 | .remove = __devexit_p(wm8904_i2c_remove), | ||
2629 | .id_table = wm8904_i2c_id, | ||
2630 | }; | ||
2631 | #endif | ||
2632 | |||
2633 | static int __init wm8904_modinit(void) | ||
2634 | { | ||
2635 | int ret; | ||
2636 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
2637 | ret = i2c_add_driver(&wm8904_i2c_driver); | ||
2638 | if (ret != 0) { | ||
2639 | printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", | ||
2640 | ret); | ||
2641 | } | ||
2642 | #endif | ||
2643 | return 0; | ||
2644 | } | ||
2645 | module_init(wm8904_modinit); | ||
2646 | |||
2647 | static void __exit wm8904_exit(void) | ||
2648 | { | ||
2649 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
2650 | i2c_del_driver(&wm8904_i2c_driver); | ||
2651 | #endif | ||
2652 | } | ||
2653 | module_exit(wm8904_exit); | ||
2654 | |||
2655 | MODULE_DESCRIPTION("ASoC WM8904 driver"); | ||
2656 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
2657 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h new file mode 100644 index 000000000000..b68886df34e4 --- /dev/null +++ b/sound/soc/codecs/wm8904.h | |||
@@ -0,0 +1,1681 @@ | |||
1 | /* | ||
2 | * wm8904.h -- WM8904 ASoC driver | ||
3 | * | ||
4 | * Copyright 2009 Wolfson Microelectronics, plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@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 _WM8904_H | ||
14 | #define _WM8904_H | ||
15 | |||
16 | #define WM8904_CLK_MCLK 1 | ||
17 | #define WM8904_CLK_FLL 2 | ||
18 | |||
19 | #define WM8904_FLL_MCLK 1 | ||
20 | #define WM8904_FLL_BCLK 2 | ||
21 | #define WM8904_FLL_LRCLK 3 | ||
22 | #define WM8904_FLL_FREE_RUNNING 4 | ||
23 | |||
24 | extern struct snd_soc_dai wm8904_dai; | ||
25 | extern struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
26 | |||
27 | /* | ||
28 | * Register values. | ||
29 | */ | ||
30 | #define WM8904_SW_RESET_AND_ID 0x00 | ||
31 | #define WM8904_REVISION 0x01 | ||
32 | #define WM8904_BIAS_CONTROL_0 0x04 | ||
33 | #define WM8904_VMID_CONTROL_0 0x05 | ||
34 | #define WM8904_MIC_BIAS_CONTROL_0 0x06 | ||
35 | #define WM8904_MIC_BIAS_CONTROL_1 0x07 | ||
36 | #define WM8904_ANALOGUE_DAC_0 0x08 | ||
37 | #define WM8904_MIC_FILTER_CONTROL 0x09 | ||
38 | #define WM8904_ANALOGUE_ADC_0 0x0A | ||
39 | #define WM8904_POWER_MANAGEMENT_0 0x0C | ||
40 | #define WM8904_POWER_MANAGEMENT_2 0x0E | ||
41 | #define WM8904_POWER_MANAGEMENT_3 0x0F | ||
42 | #define WM8904_POWER_MANAGEMENT_6 0x12 | ||
43 | #define WM8904_CLOCK_RATES_0 0x14 | ||
44 | #define WM8904_CLOCK_RATES_1 0x15 | ||
45 | #define WM8904_CLOCK_RATES_2 0x16 | ||
46 | #define WM8904_AUDIO_INTERFACE_0 0x18 | ||
47 | #define WM8904_AUDIO_INTERFACE_1 0x19 | ||
48 | #define WM8904_AUDIO_INTERFACE_2 0x1A | ||
49 | #define WM8904_AUDIO_INTERFACE_3 0x1B | ||
50 | #define WM8904_DAC_DIGITAL_VOLUME_LEFT 0x1E | ||
51 | #define WM8904_DAC_DIGITAL_VOLUME_RIGHT 0x1F | ||
52 | #define WM8904_DAC_DIGITAL_0 0x20 | ||
53 | #define WM8904_DAC_DIGITAL_1 0x21 | ||
54 | #define WM8904_ADC_DIGITAL_VOLUME_LEFT 0x24 | ||
55 | #define WM8904_ADC_DIGITAL_VOLUME_RIGHT 0x25 | ||
56 | #define WM8904_ADC_DIGITAL_0 0x26 | ||
57 | #define WM8904_DIGITAL_MICROPHONE_0 0x27 | ||
58 | #define WM8904_DRC_0 0x28 | ||
59 | #define WM8904_DRC_1 0x29 | ||
60 | #define WM8904_DRC_2 0x2A | ||
61 | #define WM8904_DRC_3 0x2B | ||
62 | #define WM8904_ANALOGUE_LEFT_INPUT_0 0x2C | ||
63 | #define WM8904_ANALOGUE_RIGHT_INPUT_0 0x2D | ||
64 | #define WM8904_ANALOGUE_LEFT_INPUT_1 0x2E | ||
65 | #define WM8904_ANALOGUE_RIGHT_INPUT_1 0x2F | ||
66 | #define WM8904_ANALOGUE_OUT1_LEFT 0x39 | ||
67 | #define WM8904_ANALOGUE_OUT1_RIGHT 0x3A | ||
68 | #define WM8904_ANALOGUE_OUT2_LEFT 0x3B | ||
69 | #define WM8904_ANALOGUE_OUT2_RIGHT 0x3C | ||
70 | #define WM8904_ANALOGUE_OUT12_ZC 0x3D | ||
71 | #define WM8904_DC_SERVO_0 0x43 | ||
72 | #define WM8904_DC_SERVO_1 0x44 | ||
73 | #define WM8904_DC_SERVO_2 0x45 | ||
74 | #define WM8904_DC_SERVO_4 0x47 | ||
75 | #define WM8904_DC_SERVO_5 0x48 | ||
76 | #define WM8904_DC_SERVO_6 0x49 | ||
77 | #define WM8904_DC_SERVO_7 0x4A | ||
78 | #define WM8904_DC_SERVO_8 0x4B | ||
79 | #define WM8904_DC_SERVO_9 0x4C | ||
80 | #define WM8904_DC_SERVO_READBACK_0 0x4D | ||
81 | #define WM8904_ANALOGUE_HP_0 0x5A | ||
82 | #define WM8904_ANALOGUE_LINEOUT_0 0x5E | ||
83 | #define WM8904_CHARGE_PUMP_0 0x62 | ||
84 | #define WM8904_CLASS_W_0 0x68 | ||
85 | #define WM8904_WRITE_SEQUENCER_0 0x6C | ||
86 | #define WM8904_WRITE_SEQUENCER_1 0x6D | ||
87 | #define WM8904_WRITE_SEQUENCER_2 0x6E | ||
88 | #define WM8904_WRITE_SEQUENCER_3 0x6F | ||
89 | #define WM8904_WRITE_SEQUENCER_4 0x70 | ||
90 | #define WM8904_FLL_CONTROL_1 0x74 | ||
91 | #define WM8904_FLL_CONTROL_2 0x75 | ||
92 | #define WM8904_FLL_CONTROL_3 0x76 | ||
93 | #define WM8904_FLL_CONTROL_4 0x77 | ||
94 | #define WM8904_FLL_CONTROL_5 0x78 | ||
95 | #define WM8904_GPIO_CONTROL_1 0x79 | ||
96 | #define WM8904_GPIO_CONTROL_2 0x7A | ||
97 | #define WM8904_GPIO_CONTROL_3 0x7B | ||
98 | #define WM8904_GPIO_CONTROL_4 0x7C | ||
99 | #define WM8904_DIGITAL_PULLS 0x7E | ||
100 | #define WM8904_INTERRUPT_STATUS 0x7F | ||
101 | #define WM8904_INTERRUPT_STATUS_MASK 0x80 | ||
102 | #define WM8904_INTERRUPT_POLARITY 0x81 | ||
103 | #define WM8904_INTERRUPT_DEBOUNCE 0x82 | ||
104 | #define WM8904_EQ1 0x86 | ||
105 | #define WM8904_EQ2 0x87 | ||
106 | #define WM8904_EQ3 0x88 | ||
107 | #define WM8904_EQ4 0x89 | ||
108 | #define WM8904_EQ5 0x8A | ||
109 | #define WM8904_EQ6 0x8B | ||
110 | #define WM8904_EQ7 0x8C | ||
111 | #define WM8904_EQ8 0x8D | ||
112 | #define WM8904_EQ9 0x8E | ||
113 | #define WM8904_EQ10 0x8F | ||
114 | #define WM8904_EQ11 0x90 | ||
115 | #define WM8904_EQ12 0x91 | ||
116 | #define WM8904_EQ13 0x92 | ||
117 | #define WM8904_EQ14 0x93 | ||
118 | #define WM8904_EQ15 0x94 | ||
119 | #define WM8904_EQ16 0x95 | ||
120 | #define WM8904_EQ17 0x96 | ||
121 | #define WM8904_EQ18 0x97 | ||
122 | #define WM8904_EQ19 0x98 | ||
123 | #define WM8904_EQ20 0x99 | ||
124 | #define WM8904_EQ21 0x9A | ||
125 | #define WM8904_EQ22 0x9B | ||
126 | #define WM8904_EQ23 0x9C | ||
127 | #define WM8904_EQ24 0x9D | ||
128 | #define WM8904_CONTROL_INTERFACE_TEST_1 0xA1 | ||
129 | #define WM8904_ANALOGUE_OUTPUT_BIAS_0 0xCC | ||
130 | #define WM8904_FLL_NCO_TEST_0 0xF7 | ||
131 | #define WM8904_FLL_NCO_TEST_1 0xF8 | ||
132 | |||
133 | #define WM8904_REGISTER_COUNT 101 | ||
134 | #define WM8904_MAX_REGISTER 0xF8 | ||
135 | |||
136 | /* | ||
137 | * Field Definitions. | ||
138 | */ | ||
139 | |||
140 | /* | ||
141 | * R0 (0x00) - SW Reset and ID | ||
142 | */ | ||
143 | #define WM8904_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ | ||
144 | #define WM8904_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ | ||
145 | #define WM8904_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ | ||
146 | |||
147 | /* | ||
148 | * R1 (0x01) - Revision | ||
149 | */ | ||
150 | #define WM8904_REVISION_MASK 0x000F /* REVISION - [3:0] */ | ||
151 | #define WM8904_REVISION_SHIFT 0 /* REVISION - [3:0] */ | ||
152 | #define WM8904_REVISION_WIDTH 16 /* REVISION - [3:0] */ | ||
153 | |||
154 | /* | ||
155 | * R4 (0x04) - Bias Control 0 | ||
156 | */ | ||
157 | #define WM8904_POBCTRL 0x0010 /* POBCTRL */ | ||
158 | #define WM8904_POBCTRL_MASK 0x0010 /* POBCTRL */ | ||
159 | #define WM8904_POBCTRL_SHIFT 4 /* POBCTRL */ | ||
160 | #define WM8904_POBCTRL_WIDTH 1 /* POBCTRL */ | ||
161 | #define WM8904_ISEL_MASK 0x000C /* ISEL - [3:2] */ | ||
162 | #define WM8904_ISEL_SHIFT 2 /* ISEL - [3:2] */ | ||
163 | #define WM8904_ISEL_WIDTH 2 /* ISEL - [3:2] */ | ||
164 | #define WM8904_STARTUP_BIAS_ENA 0x0002 /* STARTUP_BIAS_ENA */ | ||
165 | #define WM8904_STARTUP_BIAS_ENA_MASK 0x0002 /* STARTUP_BIAS_ENA */ | ||
166 | #define WM8904_STARTUP_BIAS_ENA_SHIFT 1 /* STARTUP_BIAS_ENA */ | ||
167 | #define WM8904_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ | ||
168 | #define WM8904_BIAS_ENA 0x0001 /* BIAS_ENA */ | ||
169 | #define WM8904_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ | ||
170 | #define WM8904_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ | ||
171 | #define WM8904_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ | ||
172 | |||
173 | /* | ||
174 | * R5 (0x05) - VMID Control 0 | ||
175 | */ | ||
176 | #define WM8904_VMID_BUF_ENA 0x0040 /* VMID_BUF_ENA */ | ||
177 | #define WM8904_VMID_BUF_ENA_MASK 0x0040 /* VMID_BUF_ENA */ | ||
178 | #define WM8904_VMID_BUF_ENA_SHIFT 6 /* VMID_BUF_ENA */ | ||
179 | #define WM8904_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ | ||
180 | #define WM8904_VMID_RES_MASK 0x0006 /* VMID_RES - [2:1] */ | ||
181 | #define WM8904_VMID_RES_SHIFT 1 /* VMID_RES - [2:1] */ | ||
182 | #define WM8904_VMID_RES_WIDTH 2 /* VMID_RES - [2:1] */ | ||
183 | #define WM8904_VMID_ENA 0x0001 /* VMID_ENA */ | ||
184 | #define WM8904_VMID_ENA_MASK 0x0001 /* VMID_ENA */ | ||
185 | #define WM8904_VMID_ENA_SHIFT 0 /* VMID_ENA */ | ||
186 | #define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */ | ||
187 | |||
188 | /* | ||
189 | * R6 (0x06) - Mic Bias Control 0 | ||
190 | */ | ||
191 | #define WM8904_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */ | ||
192 | #define WM8904_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */ | ||
193 | #define WM8904_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */ | ||
194 | #define WM8904_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */ | ||
195 | #define WM8904_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */ | ||
196 | #define WM8904_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */ | ||
197 | #define WM8904_MICDET_ENA 0x0002 /* MICDET_ENA */ | ||
198 | #define WM8904_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */ | ||
199 | #define WM8904_MICDET_ENA_SHIFT 1 /* MICDET_ENA */ | ||
200 | #define WM8904_MICDET_ENA_WIDTH 1 /* MICDET_ENA */ | ||
201 | #define WM8904_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */ | ||
202 | #define WM8904_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */ | ||
203 | #define WM8904_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */ | ||
204 | #define WM8904_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */ | ||
205 | |||
206 | /* | ||
207 | * R7 (0x07) - Mic Bias Control 1 | ||
208 | */ | ||
209 | #define WM8904_MIC_DET_FILTER_ENA 0x8000 /* MIC_DET_FILTER_ENA */ | ||
210 | #define WM8904_MIC_DET_FILTER_ENA_MASK 0x8000 /* MIC_DET_FILTER_ENA */ | ||
211 | #define WM8904_MIC_DET_FILTER_ENA_SHIFT 15 /* MIC_DET_FILTER_ENA */ | ||
212 | #define WM8904_MIC_DET_FILTER_ENA_WIDTH 1 /* MIC_DET_FILTER_ENA */ | ||
213 | #define WM8904_MIC_SHORT_FILTER_ENA 0x4000 /* MIC_SHORT_FILTER_ENA */ | ||
214 | #define WM8904_MIC_SHORT_FILTER_ENA_MASK 0x4000 /* MIC_SHORT_FILTER_ENA */ | ||
215 | #define WM8904_MIC_SHORT_FILTER_ENA_SHIFT 14 /* MIC_SHORT_FILTER_ENA */ | ||
216 | #define WM8904_MIC_SHORT_FILTER_ENA_WIDTH 1 /* MIC_SHORT_FILTER_ENA */ | ||
217 | #define WM8904_MICBIAS_SEL_MASK 0x0007 /* MICBIAS_SEL - [2:0] */ | ||
218 | #define WM8904_MICBIAS_SEL_SHIFT 0 /* MICBIAS_SEL - [2:0] */ | ||
219 | #define WM8904_MICBIAS_SEL_WIDTH 3 /* MICBIAS_SEL - [2:0] */ | ||
220 | |||
221 | /* | ||
222 | * R8 (0x08) - Analogue DAC 0 | ||
223 | */ | ||
224 | #define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */ | ||
225 | #define WM8904_DAC_BIAS_SEL_SHIFT 3 /* DAC_BIAS_SEL - [4:3] */ | ||
226 | #define WM8904_DAC_BIAS_SEL_WIDTH 2 /* DAC_BIAS_SEL - [4:3] */ | ||
227 | #define WM8904_DAC_VMID_BIAS_SEL_MASK 0x0006 /* DAC_VMID_BIAS_SEL - [2:1] */ | ||
228 | #define WM8904_DAC_VMID_BIAS_SEL_SHIFT 1 /* DAC_VMID_BIAS_SEL - [2:1] */ | ||
229 | #define WM8904_DAC_VMID_BIAS_SEL_WIDTH 2 /* DAC_VMID_BIAS_SEL - [2:1] */ | ||
230 | |||
231 | /* | ||
232 | * R9 (0x09) - mic Filter Control | ||
233 | */ | ||
234 | #define WM8904_MIC_DET_SET_THRESHOLD_MASK 0xF000 /* MIC_DET_SET_THRESHOLD - [15:12] */ | ||
235 | #define WM8904_MIC_DET_SET_THRESHOLD_SHIFT 12 /* MIC_DET_SET_THRESHOLD - [15:12] */ | ||
236 | #define WM8904_MIC_DET_SET_THRESHOLD_WIDTH 4 /* MIC_DET_SET_THRESHOLD - [15:12] */ | ||
237 | #define WM8904_MIC_DET_RESET_THRESHOLD_MASK 0x0F00 /* MIC_DET_RESET_THRESHOLD - [11:8] */ | ||
238 | #define WM8904_MIC_DET_RESET_THRESHOLD_SHIFT 8 /* MIC_DET_RESET_THRESHOLD - [11:8] */ | ||
239 | #define WM8904_MIC_DET_RESET_THRESHOLD_WIDTH 4 /* MIC_DET_RESET_THRESHOLD - [11:8] */ | ||
240 | #define WM8904_MIC_SHORT_SET_THRESHOLD_MASK 0x00F0 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ | ||
241 | #define WM8904_MIC_SHORT_SET_THRESHOLD_SHIFT 4 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ | ||
242 | #define WM8904_MIC_SHORT_SET_THRESHOLD_WIDTH 4 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ | ||
243 | #define WM8904_MIC_SHORT_RESET_THRESHOLD_MASK 0x000F /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ | ||
244 | #define WM8904_MIC_SHORT_RESET_THRESHOLD_SHIFT 0 /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ | ||
245 | #define WM8904_MIC_SHORT_RESET_THRESHOLD_WIDTH 4 /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ | ||
246 | |||
247 | /* | ||
248 | * R10 (0x0A) - Analogue ADC 0 | ||
249 | */ | ||
250 | #define WM8904_ADC_OSR128 0x0001 /* ADC_OSR128 */ | ||
251 | #define WM8904_ADC_OSR128_MASK 0x0001 /* ADC_OSR128 */ | ||
252 | #define WM8904_ADC_OSR128_SHIFT 0 /* ADC_OSR128 */ | ||
253 | #define WM8904_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ | ||
254 | |||
255 | /* | ||
256 | * R12 (0x0C) - Power Management 0 | ||
257 | */ | ||
258 | #define WM8904_INL_ENA 0x0002 /* INL_ENA */ | ||
259 | #define WM8904_INL_ENA_MASK 0x0002 /* INL_ENA */ | ||
260 | #define WM8904_INL_ENA_SHIFT 1 /* INL_ENA */ | ||
261 | #define WM8904_INL_ENA_WIDTH 1 /* INL_ENA */ | ||
262 | #define WM8904_INR_ENA 0x0001 /* INR_ENA */ | ||
263 | #define WM8904_INR_ENA_MASK 0x0001 /* INR_ENA */ | ||
264 | #define WM8904_INR_ENA_SHIFT 0 /* INR_ENA */ | ||
265 | #define WM8904_INR_ENA_WIDTH 1 /* INR_ENA */ | ||
266 | |||
267 | /* | ||
268 | * R14 (0x0E) - Power Management 2 | ||
269 | */ | ||
270 | #define WM8904_HPL_PGA_ENA 0x0002 /* HPL_PGA_ENA */ | ||
271 | #define WM8904_HPL_PGA_ENA_MASK 0x0002 /* HPL_PGA_ENA */ | ||
272 | #define WM8904_HPL_PGA_ENA_SHIFT 1 /* HPL_PGA_ENA */ | ||
273 | #define WM8904_HPL_PGA_ENA_WIDTH 1 /* HPL_PGA_ENA */ | ||
274 | #define WM8904_HPR_PGA_ENA 0x0001 /* HPR_PGA_ENA */ | ||
275 | #define WM8904_HPR_PGA_ENA_MASK 0x0001 /* HPR_PGA_ENA */ | ||
276 | #define WM8904_HPR_PGA_ENA_SHIFT 0 /* HPR_PGA_ENA */ | ||
277 | #define WM8904_HPR_PGA_ENA_WIDTH 1 /* HPR_PGA_ENA */ | ||
278 | |||
279 | /* | ||
280 | * R15 (0x0F) - Power Management 3 | ||
281 | */ | ||
282 | #define WM8904_LINEOUTL_PGA_ENA 0x0002 /* LINEOUTL_PGA_ENA */ | ||
283 | #define WM8904_LINEOUTL_PGA_ENA_MASK 0x0002 /* LINEOUTL_PGA_ENA */ | ||
284 | #define WM8904_LINEOUTL_PGA_ENA_SHIFT 1 /* LINEOUTL_PGA_ENA */ | ||
285 | #define WM8904_LINEOUTL_PGA_ENA_WIDTH 1 /* LINEOUTL_PGA_ENA */ | ||
286 | #define WM8904_LINEOUTR_PGA_ENA 0x0001 /* LINEOUTR_PGA_ENA */ | ||
287 | #define WM8904_LINEOUTR_PGA_ENA_MASK 0x0001 /* LINEOUTR_PGA_ENA */ | ||
288 | #define WM8904_LINEOUTR_PGA_ENA_SHIFT 0 /* LINEOUTR_PGA_ENA */ | ||
289 | #define WM8904_LINEOUTR_PGA_ENA_WIDTH 1 /* LINEOUTR_PGA_ENA */ | ||
290 | |||
291 | /* | ||
292 | * R18 (0x12) - Power Management 6 | ||
293 | */ | ||
294 | #define WM8904_DACL_ENA 0x0008 /* DACL_ENA */ | ||
295 | #define WM8904_DACL_ENA_MASK 0x0008 /* DACL_ENA */ | ||
296 | #define WM8904_DACL_ENA_SHIFT 3 /* DACL_ENA */ | ||
297 | #define WM8904_DACL_ENA_WIDTH 1 /* DACL_ENA */ | ||
298 | #define WM8904_DACR_ENA 0x0004 /* DACR_ENA */ | ||
299 | #define WM8904_DACR_ENA_MASK 0x0004 /* DACR_ENA */ | ||
300 | #define WM8904_DACR_ENA_SHIFT 2 /* DACR_ENA */ | ||
301 | #define WM8904_DACR_ENA_WIDTH 1 /* DACR_ENA */ | ||
302 | #define WM8904_ADCL_ENA 0x0002 /* ADCL_ENA */ | ||
303 | #define WM8904_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ | ||
304 | #define WM8904_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ | ||
305 | #define WM8904_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ | ||
306 | #define WM8904_ADCR_ENA 0x0001 /* ADCR_ENA */ | ||
307 | #define WM8904_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ | ||
308 | #define WM8904_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ | ||
309 | #define WM8904_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ | ||
310 | |||
311 | /* | ||
312 | * R20 (0x14) - Clock Rates 0 | ||
313 | */ | ||
314 | #define WM8904_TOCLK_RATE_DIV16 0x4000 /* TOCLK_RATE_DIV16 */ | ||
315 | #define WM8904_TOCLK_RATE_DIV16_MASK 0x4000 /* TOCLK_RATE_DIV16 */ | ||
316 | #define WM8904_TOCLK_RATE_DIV16_SHIFT 14 /* TOCLK_RATE_DIV16 */ | ||
317 | #define WM8904_TOCLK_RATE_DIV16_WIDTH 1 /* TOCLK_RATE_DIV16 */ | ||
318 | #define WM8904_TOCLK_RATE_X4 0x2000 /* TOCLK_RATE_X4 */ | ||
319 | #define WM8904_TOCLK_RATE_X4_MASK 0x2000 /* TOCLK_RATE_X4 */ | ||
320 | #define WM8904_TOCLK_RATE_X4_SHIFT 13 /* TOCLK_RATE_X4 */ | ||
321 | #define WM8904_TOCLK_RATE_X4_WIDTH 1 /* TOCLK_RATE_X4 */ | ||
322 | #define WM8904_SR_MODE 0x1000 /* SR_MODE */ | ||
323 | #define WM8904_SR_MODE_MASK 0x1000 /* SR_MODE */ | ||
324 | #define WM8904_SR_MODE_SHIFT 12 /* SR_MODE */ | ||
325 | #define WM8904_SR_MODE_WIDTH 1 /* SR_MODE */ | ||
326 | #define WM8904_MCLK_DIV 0x0001 /* MCLK_DIV */ | ||
327 | #define WM8904_MCLK_DIV_MASK 0x0001 /* MCLK_DIV */ | ||
328 | #define WM8904_MCLK_DIV_SHIFT 0 /* MCLK_DIV */ | ||
329 | #define WM8904_MCLK_DIV_WIDTH 1 /* MCLK_DIV */ | ||
330 | |||
331 | /* | ||
332 | * R21 (0x15) - Clock Rates 1 | ||
333 | */ | ||
334 | #define WM8904_CLK_SYS_RATE_MASK 0x3C00 /* CLK_SYS_RATE - [13:10] */ | ||
335 | #define WM8904_CLK_SYS_RATE_SHIFT 10 /* CLK_SYS_RATE - [13:10] */ | ||
336 | #define WM8904_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [13:10] */ | ||
337 | #define WM8904_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ | ||
338 | #define WM8904_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ | ||
339 | #define WM8904_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ | ||
340 | |||
341 | /* | ||
342 | * R22 (0x16) - Clock Rates 2 | ||
343 | */ | ||
344 | #define WM8904_MCLK_INV 0x8000 /* MCLK_INV */ | ||
345 | #define WM8904_MCLK_INV_MASK 0x8000 /* MCLK_INV */ | ||
346 | #define WM8904_MCLK_INV_SHIFT 15 /* MCLK_INV */ | ||
347 | #define WM8904_MCLK_INV_WIDTH 1 /* MCLK_INV */ | ||
348 | #define WM8904_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ | ||
349 | #define WM8904_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */ | ||
350 | #define WM8904_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */ | ||
351 | #define WM8904_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ | ||
352 | #define WM8904_TOCLK_RATE 0x1000 /* TOCLK_RATE */ | ||
353 | #define WM8904_TOCLK_RATE_MASK 0x1000 /* TOCLK_RATE */ | ||
354 | #define WM8904_TOCLK_RATE_SHIFT 12 /* TOCLK_RATE */ | ||
355 | #define WM8904_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ | ||
356 | #define WM8904_OPCLK_ENA 0x0008 /* OPCLK_ENA */ | ||
357 | #define WM8904_OPCLK_ENA_MASK 0x0008 /* OPCLK_ENA */ | ||
358 | #define WM8904_OPCLK_ENA_SHIFT 3 /* OPCLK_ENA */ | ||
359 | #define WM8904_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ | ||
360 | #define WM8904_CLK_SYS_ENA 0x0004 /* CLK_SYS_ENA */ | ||
361 | #define WM8904_CLK_SYS_ENA_MASK 0x0004 /* CLK_SYS_ENA */ | ||
362 | #define WM8904_CLK_SYS_ENA_SHIFT 2 /* CLK_SYS_ENA */ | ||
363 | #define WM8904_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ | ||
364 | #define WM8904_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */ | ||
365 | #define WM8904_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */ | ||
366 | #define WM8904_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */ | ||
367 | #define WM8904_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ | ||
368 | #define WM8904_TOCLK_ENA 0x0001 /* TOCLK_ENA */ | ||
369 | #define WM8904_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */ | ||
370 | #define WM8904_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */ | ||
371 | #define WM8904_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ | ||
372 | |||
373 | /* | ||
374 | * R24 (0x18) - Audio Interface 0 | ||
375 | */ | ||
376 | #define WM8904_DACL_DATINV 0x1000 /* DACL_DATINV */ | ||
377 | #define WM8904_DACL_DATINV_MASK 0x1000 /* DACL_DATINV */ | ||
378 | #define WM8904_DACL_DATINV_SHIFT 12 /* DACL_DATINV */ | ||
379 | #define WM8904_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ | ||
380 | #define WM8904_DACR_DATINV 0x0800 /* DACR_DATINV */ | ||
381 | #define WM8904_DACR_DATINV_MASK 0x0800 /* DACR_DATINV */ | ||
382 | #define WM8904_DACR_DATINV_SHIFT 11 /* DACR_DATINV */ | ||
383 | #define WM8904_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ | ||
384 | #define WM8904_DAC_BOOST_MASK 0x0600 /* DAC_BOOST - [10:9] */ | ||
385 | #define WM8904_DAC_BOOST_SHIFT 9 /* DAC_BOOST - [10:9] */ | ||
386 | #define WM8904_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [10:9] */ | ||
387 | #define WM8904_LOOPBACK 0x0100 /* LOOPBACK */ | ||
388 | #define WM8904_LOOPBACK_MASK 0x0100 /* LOOPBACK */ | ||
389 | #define WM8904_LOOPBACK_SHIFT 8 /* LOOPBACK */ | ||
390 | #define WM8904_LOOPBACK_WIDTH 1 /* LOOPBACK */ | ||
391 | #define WM8904_AIFADCL_SRC 0x0080 /* AIFADCL_SRC */ | ||
392 | #define WM8904_AIFADCL_SRC_MASK 0x0080 /* AIFADCL_SRC */ | ||
393 | #define WM8904_AIFADCL_SRC_SHIFT 7 /* AIFADCL_SRC */ | ||
394 | #define WM8904_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ | ||
395 | #define WM8904_AIFADCR_SRC 0x0040 /* AIFADCR_SRC */ | ||
396 | #define WM8904_AIFADCR_SRC_MASK 0x0040 /* AIFADCR_SRC */ | ||
397 | #define WM8904_AIFADCR_SRC_SHIFT 6 /* AIFADCR_SRC */ | ||
398 | #define WM8904_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ | ||
399 | #define WM8904_AIFDACL_SRC 0x0020 /* AIFDACL_SRC */ | ||
400 | #define WM8904_AIFDACL_SRC_MASK 0x0020 /* AIFDACL_SRC */ | ||
401 | #define WM8904_AIFDACL_SRC_SHIFT 5 /* AIFDACL_SRC */ | ||
402 | #define WM8904_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ | ||
403 | #define WM8904_AIFDACR_SRC 0x0010 /* AIFDACR_SRC */ | ||
404 | #define WM8904_AIFDACR_SRC_MASK 0x0010 /* AIFDACR_SRC */ | ||
405 | #define WM8904_AIFDACR_SRC_SHIFT 4 /* AIFDACR_SRC */ | ||
406 | #define WM8904_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ | ||
407 | #define WM8904_ADC_COMP 0x0008 /* ADC_COMP */ | ||
408 | #define WM8904_ADC_COMP_MASK 0x0008 /* ADC_COMP */ | ||
409 | #define WM8904_ADC_COMP_SHIFT 3 /* ADC_COMP */ | ||
410 | #define WM8904_ADC_COMP_WIDTH 1 /* ADC_COMP */ | ||
411 | #define WM8904_ADC_COMPMODE 0x0004 /* ADC_COMPMODE */ | ||
412 | #define WM8904_ADC_COMPMODE_MASK 0x0004 /* ADC_COMPMODE */ | ||
413 | #define WM8904_ADC_COMPMODE_SHIFT 2 /* ADC_COMPMODE */ | ||
414 | #define WM8904_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ | ||
415 | #define WM8904_DAC_COMP 0x0002 /* DAC_COMP */ | ||
416 | #define WM8904_DAC_COMP_MASK 0x0002 /* DAC_COMP */ | ||
417 | #define WM8904_DAC_COMP_SHIFT 1 /* DAC_COMP */ | ||
418 | #define WM8904_DAC_COMP_WIDTH 1 /* DAC_COMP */ | ||
419 | #define WM8904_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */ | ||
420 | #define WM8904_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */ | ||
421 | #define WM8904_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */ | ||
422 | #define WM8904_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ | ||
423 | |||
424 | /* | ||
425 | * R25 (0x19) - Audio Interface 1 | ||
426 | */ | ||
427 | #define WM8904_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ | ||
428 | #define WM8904_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ | ||
429 | #define WM8904_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ | ||
430 | #define WM8904_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ | ||
431 | #define WM8904_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ | ||
432 | #define WM8904_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ | ||
433 | #define WM8904_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ | ||
434 | #define WM8904_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ | ||
435 | #define WM8904_AIFADC_TDM 0x0800 /* AIFADC_TDM */ | ||
436 | #define WM8904_AIFADC_TDM_MASK 0x0800 /* AIFADC_TDM */ | ||
437 | #define WM8904_AIFADC_TDM_SHIFT 11 /* AIFADC_TDM */ | ||
438 | #define WM8904_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ | ||
439 | #define WM8904_AIFADC_TDM_CHAN 0x0400 /* AIFADC_TDM_CHAN */ | ||
440 | #define WM8904_AIFADC_TDM_CHAN_MASK 0x0400 /* AIFADC_TDM_CHAN */ | ||
441 | #define WM8904_AIFADC_TDM_CHAN_SHIFT 10 /* AIFADC_TDM_CHAN */ | ||
442 | #define WM8904_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ | ||
443 | #define WM8904_AIF_TRIS 0x0100 /* AIF_TRIS */ | ||
444 | #define WM8904_AIF_TRIS_MASK 0x0100 /* AIF_TRIS */ | ||
445 | #define WM8904_AIF_TRIS_SHIFT 8 /* AIF_TRIS */ | ||
446 | #define WM8904_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ | ||
447 | #define WM8904_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */ | ||
448 | #define WM8904_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */ | ||
449 | #define WM8904_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */ | ||
450 | #define WM8904_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ | ||
451 | #define WM8904_BCLK_DIR 0x0040 /* BCLK_DIR */ | ||
452 | #define WM8904_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */ | ||
453 | #define WM8904_BCLK_DIR_SHIFT 6 /* BCLK_DIR */ | ||
454 | #define WM8904_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ | ||
455 | #define WM8904_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */ | ||
456 | #define WM8904_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */ | ||
457 | #define WM8904_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */ | ||
458 | #define WM8904_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ | ||
459 | #define WM8904_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */ | ||
460 | #define WM8904_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */ | ||
461 | #define WM8904_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */ | ||
462 | #define WM8904_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */ | ||
463 | #define WM8904_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */ | ||
464 | #define WM8904_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */ | ||
465 | |||
466 | /* | ||
467 | * R26 (0x1A) - Audio Interface 2 | ||
468 | */ | ||
469 | #define WM8904_OPCLK_DIV_MASK 0x0F00 /* OPCLK_DIV - [11:8] */ | ||
470 | #define WM8904_OPCLK_DIV_SHIFT 8 /* OPCLK_DIV - [11:8] */ | ||
471 | #define WM8904_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [11:8] */ | ||
472 | #define WM8904_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */ | ||
473 | #define WM8904_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */ | ||
474 | #define WM8904_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */ | ||
475 | |||
476 | /* | ||
477 | * R27 (0x1B) - Audio Interface 3 | ||
478 | */ | ||
479 | #define WM8904_LRCLK_DIR 0x0800 /* LRCLK_DIR */ | ||
480 | #define WM8904_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */ | ||
481 | #define WM8904_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */ | ||
482 | #define WM8904_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ | ||
483 | #define WM8904_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ | ||
484 | #define WM8904_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ | ||
485 | #define WM8904_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ | ||
486 | |||
487 | /* | ||
488 | * R30 (0x1E) - DAC Digital Volume Left | ||
489 | */ | ||
490 | #define WM8904_DAC_VU 0x0100 /* DAC_VU */ | ||
491 | #define WM8904_DAC_VU_MASK 0x0100 /* DAC_VU */ | ||
492 | #define WM8904_DAC_VU_SHIFT 8 /* DAC_VU */ | ||
493 | #define WM8904_DAC_VU_WIDTH 1 /* DAC_VU */ | ||
494 | #define WM8904_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ | ||
495 | #define WM8904_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ | ||
496 | #define WM8904_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ | ||
497 | |||
498 | /* | ||
499 | * R31 (0x1F) - DAC Digital Volume Right | ||
500 | */ | ||
501 | #define WM8904_DAC_VU 0x0100 /* DAC_VU */ | ||
502 | #define WM8904_DAC_VU_MASK 0x0100 /* DAC_VU */ | ||
503 | #define WM8904_DAC_VU_SHIFT 8 /* DAC_VU */ | ||
504 | #define WM8904_DAC_VU_WIDTH 1 /* DAC_VU */ | ||
505 | #define WM8904_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ | ||
506 | #define WM8904_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ | ||
507 | #define WM8904_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ | ||
508 | |||
509 | /* | ||
510 | * R32 (0x20) - DAC Digital 0 | ||
511 | */ | ||
512 | #define WM8904_ADCL_DAC_SVOL_MASK 0x0F00 /* ADCL_DAC_SVOL - [11:8] */ | ||
513 | #define WM8904_ADCL_DAC_SVOL_SHIFT 8 /* ADCL_DAC_SVOL - [11:8] */ | ||
514 | #define WM8904_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [11:8] */ | ||
515 | #define WM8904_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ | ||
516 | #define WM8904_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ | ||
517 | #define WM8904_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ | ||
518 | #define WM8904_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ | ||
519 | #define WM8904_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ | ||
520 | #define WM8904_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ | ||
521 | #define WM8904_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ | ||
522 | #define WM8904_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ | ||
523 | #define WM8904_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ | ||
524 | |||
525 | /* | ||
526 | * R33 (0x21) - DAC Digital 1 | ||
527 | */ | ||
528 | #define WM8904_DAC_MONO 0x1000 /* DAC_MONO */ | ||
529 | #define WM8904_DAC_MONO_MASK 0x1000 /* DAC_MONO */ | ||
530 | #define WM8904_DAC_MONO_SHIFT 12 /* DAC_MONO */ | ||
531 | #define WM8904_DAC_MONO_WIDTH 1 /* DAC_MONO */ | ||
532 | #define WM8904_DAC_SB_FILT 0x0800 /* DAC_SB_FILT */ | ||
533 | #define WM8904_DAC_SB_FILT_MASK 0x0800 /* DAC_SB_FILT */ | ||
534 | #define WM8904_DAC_SB_FILT_SHIFT 11 /* DAC_SB_FILT */ | ||
535 | #define WM8904_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ | ||
536 | #define WM8904_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */ | ||
537 | #define WM8904_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */ | ||
538 | #define WM8904_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */ | ||
539 | #define WM8904_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ | ||
540 | #define WM8904_DAC_UNMUTE_RAMP 0x0200 /* DAC_UNMUTE_RAMP */ | ||
541 | #define WM8904_DAC_UNMUTE_RAMP_MASK 0x0200 /* DAC_UNMUTE_RAMP */ | ||
542 | #define WM8904_DAC_UNMUTE_RAMP_SHIFT 9 /* DAC_UNMUTE_RAMP */ | ||
543 | #define WM8904_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ | ||
544 | #define WM8904_DAC_OSR128 0x0040 /* DAC_OSR128 */ | ||
545 | #define WM8904_DAC_OSR128_MASK 0x0040 /* DAC_OSR128 */ | ||
546 | #define WM8904_DAC_OSR128_SHIFT 6 /* DAC_OSR128 */ | ||
547 | #define WM8904_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ | ||
548 | #define WM8904_DAC_MUTE 0x0008 /* DAC_MUTE */ | ||
549 | #define WM8904_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ | ||
550 | #define WM8904_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ | ||
551 | #define WM8904_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ | ||
552 | #define WM8904_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ | ||
553 | #define WM8904_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ | ||
554 | #define WM8904_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ | ||
555 | |||
556 | /* | ||
557 | * R36 (0x24) - ADC Digital Volume Left | ||
558 | */ | ||
559 | #define WM8904_ADC_VU 0x0100 /* ADC_VU */ | ||
560 | #define WM8904_ADC_VU_MASK 0x0100 /* ADC_VU */ | ||
561 | #define WM8904_ADC_VU_SHIFT 8 /* ADC_VU */ | ||
562 | #define WM8904_ADC_VU_WIDTH 1 /* ADC_VU */ | ||
563 | #define WM8904_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ | ||
564 | #define WM8904_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ | ||
565 | #define WM8904_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ | ||
566 | |||
567 | /* | ||
568 | * R37 (0x25) - ADC Digital Volume Right | ||
569 | */ | ||
570 | #define WM8904_ADC_VU 0x0100 /* ADC_VU */ | ||
571 | #define WM8904_ADC_VU_MASK 0x0100 /* ADC_VU */ | ||
572 | #define WM8904_ADC_VU_SHIFT 8 /* ADC_VU */ | ||
573 | #define WM8904_ADC_VU_WIDTH 1 /* ADC_VU */ | ||
574 | #define WM8904_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ | ||
575 | #define WM8904_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ | ||
576 | #define WM8904_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ | ||
577 | |||
578 | /* | ||
579 | * R38 (0x26) - ADC Digital 0 | ||
580 | */ | ||
581 | #define WM8904_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ | ||
582 | #define WM8904_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ | ||
583 | #define WM8904_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ | ||
584 | #define WM8904_ADC_HPF 0x0010 /* ADC_HPF */ | ||
585 | #define WM8904_ADC_HPF_MASK 0x0010 /* ADC_HPF */ | ||
586 | #define WM8904_ADC_HPF_SHIFT 4 /* ADC_HPF */ | ||
587 | #define WM8904_ADC_HPF_WIDTH 1 /* ADC_HPF */ | ||
588 | #define WM8904_ADCL_DATINV 0x0002 /* ADCL_DATINV */ | ||
589 | #define WM8904_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ | ||
590 | #define WM8904_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ | ||
591 | #define WM8904_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ | ||
592 | #define WM8904_ADCR_DATINV 0x0001 /* ADCR_DATINV */ | ||
593 | #define WM8904_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ | ||
594 | #define WM8904_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ | ||
595 | #define WM8904_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ | ||
596 | |||
597 | /* | ||
598 | * R39 (0x27) - Digital Microphone 0 | ||
599 | */ | ||
600 | #define WM8904_DMIC_ENA 0x1000 /* DMIC_ENA */ | ||
601 | #define WM8904_DMIC_ENA_MASK 0x1000 /* DMIC_ENA */ | ||
602 | #define WM8904_DMIC_ENA_SHIFT 12 /* DMIC_ENA */ | ||
603 | #define WM8904_DMIC_ENA_WIDTH 1 /* DMIC_ENA */ | ||
604 | #define WM8904_DMIC_SRC 0x0800 /* DMIC_SRC */ | ||
605 | #define WM8904_DMIC_SRC_MASK 0x0800 /* DMIC_SRC */ | ||
606 | #define WM8904_DMIC_SRC_SHIFT 11 /* DMIC_SRC */ | ||
607 | #define WM8904_DMIC_SRC_WIDTH 1 /* DMIC_SRC */ | ||
608 | |||
609 | /* | ||
610 | * R40 (0x28) - DRC 0 | ||
611 | */ | ||
612 | #define WM8904_DRC_ENA 0x8000 /* DRC_ENA */ | ||
613 | #define WM8904_DRC_ENA_MASK 0x8000 /* DRC_ENA */ | ||
614 | #define WM8904_DRC_ENA_SHIFT 15 /* DRC_ENA */ | ||
615 | #define WM8904_DRC_ENA_WIDTH 1 /* DRC_ENA */ | ||
616 | #define WM8904_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */ | ||
617 | #define WM8904_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */ | ||
618 | #define WM8904_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */ | ||
619 | #define WM8904_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */ | ||
620 | #define WM8904_DRC_GS_HYST_LVL_MASK 0x1800 /* DRC_GS_HYST_LVL - [12:11] */ | ||
621 | #define WM8904_DRC_GS_HYST_LVL_SHIFT 11 /* DRC_GS_HYST_LVL - [12:11] */ | ||
622 | #define WM8904_DRC_GS_HYST_LVL_WIDTH 2 /* DRC_GS_HYST_LVL - [12:11] */ | ||
623 | #define WM8904_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */ | ||
624 | #define WM8904_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */ | ||
625 | #define WM8904_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */ | ||
626 | #define WM8904_DRC_FF_DELAY 0x0020 /* DRC_FF_DELAY */ | ||
627 | #define WM8904_DRC_FF_DELAY_MASK 0x0020 /* DRC_FF_DELAY */ | ||
628 | #define WM8904_DRC_FF_DELAY_SHIFT 5 /* DRC_FF_DELAY */ | ||
629 | #define WM8904_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ | ||
630 | #define WM8904_DRC_GS_ENA 0x0008 /* DRC_GS_ENA */ | ||
631 | #define WM8904_DRC_GS_ENA_MASK 0x0008 /* DRC_GS_ENA */ | ||
632 | #define WM8904_DRC_GS_ENA_SHIFT 3 /* DRC_GS_ENA */ | ||
633 | #define WM8904_DRC_GS_ENA_WIDTH 1 /* DRC_GS_ENA */ | ||
634 | #define WM8904_DRC_QR 0x0004 /* DRC_QR */ | ||
635 | #define WM8904_DRC_QR_MASK 0x0004 /* DRC_QR */ | ||
636 | #define WM8904_DRC_QR_SHIFT 2 /* DRC_QR */ | ||
637 | #define WM8904_DRC_QR_WIDTH 1 /* DRC_QR */ | ||
638 | #define WM8904_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */ | ||
639 | #define WM8904_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */ | ||
640 | #define WM8904_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */ | ||
641 | #define WM8904_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ | ||
642 | #define WM8904_DRC_GS_HYST 0x0001 /* DRC_GS_HYST */ | ||
643 | #define WM8904_DRC_GS_HYST_MASK 0x0001 /* DRC_GS_HYST */ | ||
644 | #define WM8904_DRC_GS_HYST_SHIFT 0 /* DRC_GS_HYST */ | ||
645 | #define WM8904_DRC_GS_HYST_WIDTH 1 /* DRC_GS_HYST */ | ||
646 | |||
647 | /* | ||
648 | * R41 (0x29) - DRC 1 | ||
649 | */ | ||
650 | #define WM8904_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */ | ||
651 | #define WM8904_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */ | ||
652 | #define WM8904_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */ | ||
653 | #define WM8904_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */ | ||
654 | #define WM8904_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */ | ||
655 | #define WM8904_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */ | ||
656 | #define WM8904_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */ | ||
657 | #define WM8904_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */ | ||
658 | #define WM8904_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */ | ||
659 | #define WM8904_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */ | ||
660 | #define WM8904_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */ | ||
661 | #define WM8904_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */ | ||
662 | #define WM8904_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ | ||
663 | #define WM8904_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ | ||
664 | #define WM8904_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ | ||
665 | #define WM8904_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ | ||
666 | #define WM8904_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ | ||
667 | #define WM8904_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ | ||
668 | |||
669 | /* | ||
670 | * R42 (0x2A) - DRC 2 | ||
671 | */ | ||
672 | #define WM8904_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ | ||
673 | #define WM8904_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ | ||
674 | #define WM8904_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ | ||
675 | #define WM8904_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ | ||
676 | #define WM8904_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ | ||
677 | #define WM8904_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ | ||
678 | |||
679 | /* | ||
680 | * R43 (0x2B) - DRC 3 | ||
681 | */ | ||
682 | #define WM8904_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ | ||
683 | #define WM8904_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ | ||
684 | #define WM8904_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ | ||
685 | #define WM8904_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ | ||
686 | #define WM8904_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ | ||
687 | #define WM8904_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ | ||
688 | |||
689 | /* | ||
690 | * R44 (0x2C) - Analogue Left Input 0 | ||
691 | */ | ||
692 | #define WM8904_LINMUTE 0x0080 /* LINMUTE */ | ||
693 | #define WM8904_LINMUTE_MASK 0x0080 /* LINMUTE */ | ||
694 | #define WM8904_LINMUTE_SHIFT 7 /* LINMUTE */ | ||
695 | #define WM8904_LINMUTE_WIDTH 1 /* LINMUTE */ | ||
696 | #define WM8904_LIN_VOL_MASK 0x001F /* LIN_VOL - [4:0] */ | ||
697 | #define WM8904_LIN_VOL_SHIFT 0 /* LIN_VOL - [4:0] */ | ||
698 | #define WM8904_LIN_VOL_WIDTH 5 /* LIN_VOL - [4:0] */ | ||
699 | |||
700 | /* | ||
701 | * R45 (0x2D) - Analogue Right Input 0 | ||
702 | */ | ||
703 | #define WM8904_RINMUTE 0x0080 /* RINMUTE */ | ||
704 | #define WM8904_RINMUTE_MASK 0x0080 /* RINMUTE */ | ||
705 | #define WM8904_RINMUTE_SHIFT 7 /* RINMUTE */ | ||
706 | #define WM8904_RINMUTE_WIDTH 1 /* RINMUTE */ | ||
707 | #define WM8904_RIN_VOL_MASK 0x001F /* RIN_VOL - [4:0] */ | ||
708 | #define WM8904_RIN_VOL_SHIFT 0 /* RIN_VOL - [4:0] */ | ||
709 | #define WM8904_RIN_VOL_WIDTH 5 /* RIN_VOL - [4:0] */ | ||
710 | |||
711 | /* | ||
712 | * R46 (0x2E) - Analogue Left Input 1 | ||
713 | */ | ||
714 | #define WM8904_INL_CM_ENA 0x0040 /* INL_CM_ENA */ | ||
715 | #define WM8904_INL_CM_ENA_MASK 0x0040 /* INL_CM_ENA */ | ||
716 | #define WM8904_INL_CM_ENA_SHIFT 6 /* INL_CM_ENA */ | ||
717 | #define WM8904_INL_CM_ENA_WIDTH 1 /* INL_CM_ENA */ | ||
718 | #define WM8904_L_IP_SEL_N_MASK 0x0030 /* L_IP_SEL_N - [5:4] */ | ||
719 | #define WM8904_L_IP_SEL_N_SHIFT 4 /* L_IP_SEL_N - [5:4] */ | ||
720 | #define WM8904_L_IP_SEL_N_WIDTH 2 /* L_IP_SEL_N - [5:4] */ | ||
721 | #define WM8904_L_IP_SEL_P_MASK 0x000C /* L_IP_SEL_P - [3:2] */ | ||
722 | #define WM8904_L_IP_SEL_P_SHIFT 2 /* L_IP_SEL_P - [3:2] */ | ||
723 | #define WM8904_L_IP_SEL_P_WIDTH 2 /* L_IP_SEL_P - [3:2] */ | ||
724 | #define WM8904_L_MODE_MASK 0x0003 /* L_MODE - [1:0] */ | ||
725 | #define WM8904_L_MODE_SHIFT 0 /* L_MODE - [1:0] */ | ||
726 | #define WM8904_L_MODE_WIDTH 2 /* L_MODE - [1:0] */ | ||
727 | |||
728 | /* | ||
729 | * R47 (0x2F) - Analogue Right Input 1 | ||
730 | */ | ||
731 | #define WM8904_INR_CM_ENA 0x0040 /* INR_CM_ENA */ | ||
732 | #define WM8904_INR_CM_ENA_MASK 0x0040 /* INR_CM_ENA */ | ||
733 | #define WM8904_INR_CM_ENA_SHIFT 6 /* INR_CM_ENA */ | ||
734 | #define WM8904_INR_CM_ENA_WIDTH 1 /* INR_CM_ENA */ | ||
735 | #define WM8904_R_IP_SEL_N_MASK 0x0030 /* R_IP_SEL_N - [5:4] */ | ||
736 | #define WM8904_R_IP_SEL_N_SHIFT 4 /* R_IP_SEL_N - [5:4] */ | ||
737 | #define WM8904_R_IP_SEL_N_WIDTH 2 /* R_IP_SEL_N - [5:4] */ | ||
738 | #define WM8904_R_IP_SEL_P_MASK 0x000C /* R_IP_SEL_P - [3:2] */ | ||
739 | #define WM8904_R_IP_SEL_P_SHIFT 2 /* R_IP_SEL_P - [3:2] */ | ||
740 | #define WM8904_R_IP_SEL_P_WIDTH 2 /* R_IP_SEL_P - [3:2] */ | ||
741 | #define WM8904_R_MODE_MASK 0x0003 /* R_MODE - [1:0] */ | ||
742 | #define WM8904_R_MODE_SHIFT 0 /* R_MODE - [1:0] */ | ||
743 | #define WM8904_R_MODE_WIDTH 2 /* R_MODE - [1:0] */ | ||
744 | |||
745 | /* | ||
746 | * R57 (0x39) - Analogue OUT1 Left | ||
747 | */ | ||
748 | #define WM8904_HPOUTL_MUTE 0x0100 /* HPOUTL_MUTE */ | ||
749 | #define WM8904_HPOUTL_MUTE_MASK 0x0100 /* HPOUTL_MUTE */ | ||
750 | #define WM8904_HPOUTL_MUTE_SHIFT 8 /* HPOUTL_MUTE */ | ||
751 | #define WM8904_HPOUTL_MUTE_WIDTH 1 /* HPOUTL_MUTE */ | ||
752 | #define WM8904_HPOUT_VU 0x0080 /* HPOUT_VU */ | ||
753 | #define WM8904_HPOUT_VU_MASK 0x0080 /* HPOUT_VU */ | ||
754 | #define WM8904_HPOUT_VU_SHIFT 7 /* HPOUT_VU */ | ||
755 | #define WM8904_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ | ||
756 | #define WM8904_HPOUTLZC 0x0040 /* HPOUTLZC */ | ||
757 | #define WM8904_HPOUTLZC_MASK 0x0040 /* HPOUTLZC */ | ||
758 | #define WM8904_HPOUTLZC_SHIFT 6 /* HPOUTLZC */ | ||
759 | #define WM8904_HPOUTLZC_WIDTH 1 /* HPOUTLZC */ | ||
760 | #define WM8904_HPOUTL_VOL_MASK 0x003F /* HPOUTL_VOL - [5:0] */ | ||
761 | #define WM8904_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [5:0] */ | ||
762 | #define WM8904_HPOUTL_VOL_WIDTH 6 /* HPOUTL_VOL - [5:0] */ | ||
763 | |||
764 | /* | ||
765 | * R58 (0x3A) - Analogue OUT1 Right | ||
766 | */ | ||
767 | #define WM8904_HPOUTR_MUTE 0x0100 /* HPOUTR_MUTE */ | ||
768 | #define WM8904_HPOUTR_MUTE_MASK 0x0100 /* HPOUTR_MUTE */ | ||
769 | #define WM8904_HPOUTR_MUTE_SHIFT 8 /* HPOUTR_MUTE */ | ||
770 | #define WM8904_HPOUTR_MUTE_WIDTH 1 /* HPOUTR_MUTE */ | ||
771 | #define WM8904_HPOUT_VU 0x0080 /* HPOUT_VU */ | ||
772 | #define WM8904_HPOUT_VU_MASK 0x0080 /* HPOUT_VU */ | ||
773 | #define WM8904_HPOUT_VU_SHIFT 7 /* HPOUT_VU */ | ||
774 | #define WM8904_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ | ||
775 | #define WM8904_HPOUTRZC 0x0040 /* HPOUTRZC */ | ||
776 | #define WM8904_HPOUTRZC_MASK 0x0040 /* HPOUTRZC */ | ||
777 | #define WM8904_HPOUTRZC_SHIFT 6 /* HPOUTRZC */ | ||
778 | #define WM8904_HPOUTRZC_WIDTH 1 /* HPOUTRZC */ | ||
779 | #define WM8904_HPOUTR_VOL_MASK 0x003F /* HPOUTR_VOL - [5:0] */ | ||
780 | #define WM8904_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [5:0] */ | ||
781 | #define WM8904_HPOUTR_VOL_WIDTH 6 /* HPOUTR_VOL - [5:0] */ | ||
782 | |||
783 | /* | ||
784 | * R59 (0x3B) - Analogue OUT2 Left | ||
785 | */ | ||
786 | #define WM8904_LINEOUTL_MUTE 0x0100 /* LINEOUTL_MUTE */ | ||
787 | #define WM8904_LINEOUTL_MUTE_MASK 0x0100 /* LINEOUTL_MUTE */ | ||
788 | #define WM8904_LINEOUTL_MUTE_SHIFT 8 /* LINEOUTL_MUTE */ | ||
789 | #define WM8904_LINEOUTL_MUTE_WIDTH 1 /* LINEOUTL_MUTE */ | ||
790 | #define WM8904_LINEOUT_VU 0x0080 /* LINEOUT_VU */ | ||
791 | #define WM8904_LINEOUT_VU_MASK 0x0080 /* LINEOUT_VU */ | ||
792 | #define WM8904_LINEOUT_VU_SHIFT 7 /* LINEOUT_VU */ | ||
793 | #define WM8904_LINEOUT_VU_WIDTH 1 /* LINEOUT_VU */ | ||
794 | #define WM8904_LINEOUTLZC 0x0040 /* LINEOUTLZC */ | ||
795 | #define WM8904_LINEOUTLZC_MASK 0x0040 /* LINEOUTLZC */ | ||
796 | #define WM8904_LINEOUTLZC_SHIFT 6 /* LINEOUTLZC */ | ||
797 | #define WM8904_LINEOUTLZC_WIDTH 1 /* LINEOUTLZC */ | ||
798 | #define WM8904_LINEOUTL_VOL_MASK 0x003F /* LINEOUTL_VOL - [5:0] */ | ||
799 | #define WM8904_LINEOUTL_VOL_SHIFT 0 /* LINEOUTL_VOL - [5:0] */ | ||
800 | #define WM8904_LINEOUTL_VOL_WIDTH 6 /* LINEOUTL_VOL - [5:0] */ | ||
801 | |||
802 | /* | ||
803 | * R60 (0x3C) - Analogue OUT2 Right | ||
804 | */ | ||
805 | #define WM8904_LINEOUTR_MUTE 0x0100 /* LINEOUTR_MUTE */ | ||
806 | #define WM8904_LINEOUTR_MUTE_MASK 0x0100 /* LINEOUTR_MUTE */ | ||
807 | #define WM8904_LINEOUTR_MUTE_SHIFT 8 /* LINEOUTR_MUTE */ | ||
808 | #define WM8904_LINEOUTR_MUTE_WIDTH 1 /* LINEOUTR_MUTE */ | ||
809 | #define WM8904_LINEOUT_VU 0x0080 /* LINEOUT_VU */ | ||
810 | #define WM8904_LINEOUT_VU_MASK 0x0080 /* LINEOUT_VU */ | ||
811 | #define WM8904_LINEOUT_VU_SHIFT 7 /* LINEOUT_VU */ | ||
812 | #define WM8904_LINEOUT_VU_WIDTH 1 /* LINEOUT_VU */ | ||
813 | #define WM8904_LINEOUTRZC 0x0040 /* LINEOUTRZC */ | ||
814 | #define WM8904_LINEOUTRZC_MASK 0x0040 /* LINEOUTRZC */ | ||
815 | #define WM8904_LINEOUTRZC_SHIFT 6 /* LINEOUTRZC */ | ||
816 | #define WM8904_LINEOUTRZC_WIDTH 1 /* LINEOUTRZC */ | ||
817 | #define WM8904_LINEOUTR_VOL_MASK 0x003F /* LINEOUTR_VOL - [5:0] */ | ||
818 | #define WM8904_LINEOUTR_VOL_SHIFT 0 /* LINEOUTR_VOL - [5:0] */ | ||
819 | #define WM8904_LINEOUTR_VOL_WIDTH 6 /* LINEOUTR_VOL - [5:0] */ | ||
820 | |||
821 | /* | ||
822 | * R61 (0x3D) - Analogue OUT12 ZC | ||
823 | */ | ||
824 | #define WM8904_HPL_BYP_ENA 0x0008 /* HPL_BYP_ENA */ | ||
825 | #define WM8904_HPL_BYP_ENA_MASK 0x0008 /* HPL_BYP_ENA */ | ||
826 | #define WM8904_HPL_BYP_ENA_SHIFT 3 /* HPL_BYP_ENA */ | ||
827 | #define WM8904_HPL_BYP_ENA_WIDTH 1 /* HPL_BYP_ENA */ | ||
828 | #define WM8904_HPR_BYP_ENA 0x0004 /* HPR_BYP_ENA */ | ||
829 | #define WM8904_HPR_BYP_ENA_MASK 0x0004 /* HPR_BYP_ENA */ | ||
830 | #define WM8904_HPR_BYP_ENA_SHIFT 2 /* HPR_BYP_ENA */ | ||
831 | #define WM8904_HPR_BYP_ENA_WIDTH 1 /* HPR_BYP_ENA */ | ||
832 | #define WM8904_LINEOUTL_BYP_ENA 0x0002 /* LINEOUTL_BYP_ENA */ | ||
833 | #define WM8904_LINEOUTL_BYP_ENA_MASK 0x0002 /* LINEOUTL_BYP_ENA */ | ||
834 | #define WM8904_LINEOUTL_BYP_ENA_SHIFT 1 /* LINEOUTL_BYP_ENA */ | ||
835 | #define WM8904_LINEOUTL_BYP_ENA_WIDTH 1 /* LINEOUTL_BYP_ENA */ | ||
836 | #define WM8904_LINEOUTR_BYP_ENA 0x0001 /* LINEOUTR_BYP_ENA */ | ||
837 | #define WM8904_LINEOUTR_BYP_ENA_MASK 0x0001 /* LINEOUTR_BYP_ENA */ | ||
838 | #define WM8904_LINEOUTR_BYP_ENA_SHIFT 0 /* LINEOUTR_BYP_ENA */ | ||
839 | #define WM8904_LINEOUTR_BYP_ENA_WIDTH 1 /* LINEOUTR_BYP_ENA */ | ||
840 | |||
841 | /* | ||
842 | * R67 (0x43) - DC Servo 0 | ||
843 | */ | ||
844 | #define WM8904_DCS_ENA_CHAN_3 0x0008 /* DCS_ENA_CHAN_3 */ | ||
845 | #define WM8904_DCS_ENA_CHAN_3_MASK 0x0008 /* DCS_ENA_CHAN_3 */ | ||
846 | #define WM8904_DCS_ENA_CHAN_3_SHIFT 3 /* DCS_ENA_CHAN_3 */ | ||
847 | #define WM8904_DCS_ENA_CHAN_3_WIDTH 1 /* DCS_ENA_CHAN_3 */ | ||
848 | #define WM8904_DCS_ENA_CHAN_2 0x0004 /* DCS_ENA_CHAN_2 */ | ||
849 | #define WM8904_DCS_ENA_CHAN_2_MASK 0x0004 /* DCS_ENA_CHAN_2 */ | ||
850 | #define WM8904_DCS_ENA_CHAN_2_SHIFT 2 /* DCS_ENA_CHAN_2 */ | ||
851 | #define WM8904_DCS_ENA_CHAN_2_WIDTH 1 /* DCS_ENA_CHAN_2 */ | ||
852 | #define WM8904_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ | ||
853 | #define WM8904_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ | ||
854 | #define WM8904_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ | ||
855 | #define WM8904_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ | ||
856 | #define WM8904_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ | ||
857 | #define WM8904_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ | ||
858 | #define WM8904_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ | ||
859 | #define WM8904_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ | ||
860 | |||
861 | /* | ||
862 | * R68 (0x44) - DC Servo 1 | ||
863 | */ | ||
864 | #define WM8904_DCS_TRIG_SINGLE_3 0x8000 /* DCS_TRIG_SINGLE_3 */ | ||
865 | #define WM8904_DCS_TRIG_SINGLE_3_MASK 0x8000 /* DCS_TRIG_SINGLE_3 */ | ||
866 | #define WM8904_DCS_TRIG_SINGLE_3_SHIFT 15 /* DCS_TRIG_SINGLE_3 */ | ||
867 | #define WM8904_DCS_TRIG_SINGLE_3_WIDTH 1 /* DCS_TRIG_SINGLE_3 */ | ||
868 | #define WM8904_DCS_TRIG_SINGLE_2 0x4000 /* DCS_TRIG_SINGLE_2 */ | ||
869 | #define WM8904_DCS_TRIG_SINGLE_2_MASK 0x4000 /* DCS_TRIG_SINGLE_2 */ | ||
870 | #define WM8904_DCS_TRIG_SINGLE_2_SHIFT 14 /* DCS_TRIG_SINGLE_2 */ | ||
871 | #define WM8904_DCS_TRIG_SINGLE_2_WIDTH 1 /* DCS_TRIG_SINGLE_2 */ | ||
872 | #define WM8904_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ | ||
873 | #define WM8904_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ | ||
874 | #define WM8904_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ | ||
875 | #define WM8904_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ | ||
876 | #define WM8904_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ | ||
877 | #define WM8904_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ | ||
878 | #define WM8904_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ | ||
879 | #define WM8904_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ | ||
880 | #define WM8904_DCS_TRIG_SERIES_3 0x0800 /* DCS_TRIG_SERIES_3 */ | ||
881 | #define WM8904_DCS_TRIG_SERIES_3_MASK 0x0800 /* DCS_TRIG_SERIES_3 */ | ||
882 | #define WM8904_DCS_TRIG_SERIES_3_SHIFT 11 /* DCS_TRIG_SERIES_3 */ | ||
883 | #define WM8904_DCS_TRIG_SERIES_3_WIDTH 1 /* DCS_TRIG_SERIES_3 */ | ||
884 | #define WM8904_DCS_TRIG_SERIES_2 0x0400 /* DCS_TRIG_SERIES_2 */ | ||
885 | #define WM8904_DCS_TRIG_SERIES_2_MASK 0x0400 /* DCS_TRIG_SERIES_2 */ | ||
886 | #define WM8904_DCS_TRIG_SERIES_2_SHIFT 10 /* DCS_TRIG_SERIES_2 */ | ||
887 | #define WM8904_DCS_TRIG_SERIES_2_WIDTH 1 /* DCS_TRIG_SERIES_2 */ | ||
888 | #define WM8904_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ | ||
889 | #define WM8904_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ | ||
890 | #define WM8904_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ | ||
891 | #define WM8904_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ | ||
892 | #define WM8904_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ | ||
893 | #define WM8904_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ | ||
894 | #define WM8904_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ | ||
895 | #define WM8904_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ | ||
896 | #define WM8904_DCS_TRIG_STARTUP_3 0x0080 /* DCS_TRIG_STARTUP_3 */ | ||
897 | #define WM8904_DCS_TRIG_STARTUP_3_MASK 0x0080 /* DCS_TRIG_STARTUP_3 */ | ||
898 | #define WM8904_DCS_TRIG_STARTUP_3_SHIFT 7 /* DCS_TRIG_STARTUP_3 */ | ||
899 | #define WM8904_DCS_TRIG_STARTUP_3_WIDTH 1 /* DCS_TRIG_STARTUP_3 */ | ||
900 | #define WM8904_DCS_TRIG_STARTUP_2 0x0040 /* DCS_TRIG_STARTUP_2 */ | ||
901 | #define WM8904_DCS_TRIG_STARTUP_2_MASK 0x0040 /* DCS_TRIG_STARTUP_2 */ | ||
902 | #define WM8904_DCS_TRIG_STARTUP_2_SHIFT 6 /* DCS_TRIG_STARTUP_2 */ | ||
903 | #define WM8904_DCS_TRIG_STARTUP_2_WIDTH 1 /* DCS_TRIG_STARTUP_2 */ | ||
904 | #define WM8904_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ | ||
905 | #define WM8904_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ | ||
906 | #define WM8904_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ | ||
907 | #define WM8904_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ | ||
908 | #define WM8904_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ | ||
909 | #define WM8904_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ | ||
910 | #define WM8904_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ | ||
911 | #define WM8904_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ | ||
912 | #define WM8904_DCS_TRIG_DAC_WR_3 0x0008 /* DCS_TRIG_DAC_WR_3 */ | ||
913 | #define WM8904_DCS_TRIG_DAC_WR_3_MASK 0x0008 /* DCS_TRIG_DAC_WR_3 */ | ||
914 | #define WM8904_DCS_TRIG_DAC_WR_3_SHIFT 3 /* DCS_TRIG_DAC_WR_3 */ | ||
915 | #define WM8904_DCS_TRIG_DAC_WR_3_WIDTH 1 /* DCS_TRIG_DAC_WR_3 */ | ||
916 | #define WM8904_DCS_TRIG_DAC_WR_2 0x0004 /* DCS_TRIG_DAC_WR_2 */ | ||
917 | #define WM8904_DCS_TRIG_DAC_WR_2_MASK 0x0004 /* DCS_TRIG_DAC_WR_2 */ | ||
918 | #define WM8904_DCS_TRIG_DAC_WR_2_SHIFT 2 /* DCS_TRIG_DAC_WR_2 */ | ||
919 | #define WM8904_DCS_TRIG_DAC_WR_2_WIDTH 1 /* DCS_TRIG_DAC_WR_2 */ | ||
920 | #define WM8904_DCS_TRIG_DAC_WR_1 0x0002 /* DCS_TRIG_DAC_WR_1 */ | ||
921 | #define WM8904_DCS_TRIG_DAC_WR_1_MASK 0x0002 /* DCS_TRIG_DAC_WR_1 */ | ||
922 | #define WM8904_DCS_TRIG_DAC_WR_1_SHIFT 1 /* DCS_TRIG_DAC_WR_1 */ | ||
923 | #define WM8904_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ | ||
924 | #define WM8904_DCS_TRIG_DAC_WR_0 0x0001 /* DCS_TRIG_DAC_WR_0 */ | ||
925 | #define WM8904_DCS_TRIG_DAC_WR_0_MASK 0x0001 /* DCS_TRIG_DAC_WR_0 */ | ||
926 | #define WM8904_DCS_TRIG_DAC_WR_0_SHIFT 0 /* DCS_TRIG_DAC_WR_0 */ | ||
927 | #define WM8904_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ | ||
928 | |||
929 | /* | ||
930 | * R69 (0x45) - DC Servo 2 | ||
931 | */ | ||
932 | #define WM8904_DCS_TIMER_PERIOD_23_MASK 0x0F00 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
933 | #define WM8904_DCS_TIMER_PERIOD_23_SHIFT 8 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
934 | #define WM8904_DCS_TIMER_PERIOD_23_WIDTH 4 /* DCS_TIMER_PERIOD_23 - [11:8] */ | ||
935 | #define WM8904_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
936 | #define WM8904_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
937 | #define WM8904_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ | ||
938 | |||
939 | /* | ||
940 | * R71 (0x47) - DC Servo 4 | ||
941 | */ | ||
942 | #define WM8904_DCS_SERIES_NO_23_MASK 0x007F /* DCS_SERIES_NO_23 - [6:0] */ | ||
943 | #define WM8904_DCS_SERIES_NO_23_SHIFT 0 /* DCS_SERIES_NO_23 - [6:0] */ | ||
944 | #define WM8904_DCS_SERIES_NO_23_WIDTH 7 /* DCS_SERIES_NO_23 - [6:0] */ | ||
945 | |||
946 | /* | ||
947 | * R72 (0x48) - DC Servo 5 | ||
948 | */ | ||
949 | #define WM8904_DCS_SERIES_NO_01_MASK 0x007F /* DCS_SERIES_NO_01 - [6:0] */ | ||
950 | #define WM8904_DCS_SERIES_NO_01_SHIFT 0 /* DCS_SERIES_NO_01 - [6:0] */ | ||
951 | #define WM8904_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [6:0] */ | ||
952 | |||
953 | /* | ||
954 | * R73 (0x49) - DC Servo 6 | ||
955 | */ | ||
956 | #define WM8904_DCS_DAC_WR_VAL_3_MASK 0x00FF /* DCS_DAC_WR_VAL_3 - [7:0] */ | ||
957 | #define WM8904_DCS_DAC_WR_VAL_3_SHIFT 0 /* DCS_DAC_WR_VAL_3 - [7:0] */ | ||
958 | #define WM8904_DCS_DAC_WR_VAL_3_WIDTH 8 /* DCS_DAC_WR_VAL_3 - [7:0] */ | ||
959 | |||
960 | /* | ||
961 | * R74 (0x4A) - DC Servo 7 | ||
962 | */ | ||
963 | #define WM8904_DCS_DAC_WR_VAL_2_MASK 0x00FF /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
964 | #define WM8904_DCS_DAC_WR_VAL_2_SHIFT 0 /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
965 | #define WM8904_DCS_DAC_WR_VAL_2_WIDTH 8 /* DCS_DAC_WR_VAL_2 - [7:0] */ | ||
966 | |||
967 | /* | ||
968 | * R75 (0x4B) - DC Servo 8 | ||
969 | */ | ||
970 | #define WM8904_DCS_DAC_WR_VAL_1_MASK 0x00FF /* DCS_DAC_WR_VAL_1 - [7:0] */ | ||
971 | #define WM8904_DCS_DAC_WR_VAL_1_SHIFT 0 /* DCS_DAC_WR_VAL_1 - [7:0] */ | ||
972 | #define WM8904_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [7:0] */ | ||
973 | |||
974 | /* | ||
975 | * R76 (0x4C) - DC Servo 9 | ||
976 | */ | ||
977 | #define WM8904_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
978 | #define WM8904_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
979 | #define WM8904_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ | ||
980 | |||
981 | /* | ||
982 | * R77 (0x4D) - DC Servo Readback 0 | ||
983 | */ | ||
984 | #define WM8904_DCS_CAL_COMPLETE_MASK 0x0F00 /* DCS_CAL_COMPLETE - [11:8] */ | ||
985 | #define WM8904_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [11:8] */ | ||
986 | #define WM8904_DCS_CAL_COMPLETE_WIDTH 4 /* DCS_CAL_COMPLETE - [11:8] */ | ||
987 | #define WM8904_DCS_DAC_WR_COMPLETE_MASK 0x00F0 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
988 | #define WM8904_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
989 | #define WM8904_DCS_DAC_WR_COMPLETE_WIDTH 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ | ||
990 | #define WM8904_DCS_STARTUP_COMPLETE_MASK 0x000F /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
991 | #define WM8904_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
992 | #define WM8904_DCS_STARTUP_COMPLETE_WIDTH 4 /* DCS_STARTUP_COMPLETE - [3:0] */ | ||
993 | |||
994 | /* | ||
995 | * R90 (0x5A) - Analogue HP 0 | ||
996 | */ | ||
997 | #define WM8904_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ | ||
998 | #define WM8904_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ | ||
999 | #define WM8904_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ | ||
1000 | #define WM8904_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ | ||
1001 | #define WM8904_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ | ||
1002 | #define WM8904_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ | ||
1003 | #define WM8904_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ | ||
1004 | #define WM8904_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ | ||
1005 | #define WM8904_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ | ||
1006 | #define WM8904_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ | ||
1007 | #define WM8904_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ | ||
1008 | #define WM8904_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ | ||
1009 | #define WM8904_HPL_ENA 0x0010 /* HPL_ENA */ | ||
1010 | #define WM8904_HPL_ENA_MASK 0x0010 /* HPL_ENA */ | ||
1011 | #define WM8904_HPL_ENA_SHIFT 4 /* HPL_ENA */ | ||
1012 | #define WM8904_HPL_ENA_WIDTH 1 /* HPL_ENA */ | ||
1013 | #define WM8904_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ | ||
1014 | #define WM8904_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ | ||
1015 | #define WM8904_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ | ||
1016 | #define WM8904_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ | ||
1017 | #define WM8904_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ | ||
1018 | #define WM8904_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ | ||
1019 | #define WM8904_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ | ||
1020 | #define WM8904_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ | ||
1021 | #define WM8904_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ | ||
1022 | #define WM8904_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ | ||
1023 | #define WM8904_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ | ||
1024 | #define WM8904_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ | ||
1025 | #define WM8904_HPR_ENA 0x0001 /* HPR_ENA */ | ||
1026 | #define WM8904_HPR_ENA_MASK 0x0001 /* HPR_ENA */ | ||
1027 | #define WM8904_HPR_ENA_SHIFT 0 /* HPR_ENA */ | ||
1028 | #define WM8904_HPR_ENA_WIDTH 1 /* HPR_ENA */ | ||
1029 | |||
1030 | /* | ||
1031 | * R94 (0x5E) - Analogue Lineout 0 | ||
1032 | */ | ||
1033 | #define WM8904_LINEOUTL_RMV_SHORT 0x0080 /* LINEOUTL_RMV_SHORT */ | ||
1034 | #define WM8904_LINEOUTL_RMV_SHORT_MASK 0x0080 /* LINEOUTL_RMV_SHORT */ | ||
1035 | #define WM8904_LINEOUTL_RMV_SHORT_SHIFT 7 /* LINEOUTL_RMV_SHORT */ | ||
1036 | #define WM8904_LINEOUTL_RMV_SHORT_WIDTH 1 /* LINEOUTL_RMV_SHORT */ | ||
1037 | #define WM8904_LINEOUTL_ENA_OUTP 0x0040 /* LINEOUTL_ENA_OUTP */ | ||
1038 | #define WM8904_LINEOUTL_ENA_OUTP_MASK 0x0040 /* LINEOUTL_ENA_OUTP */ | ||
1039 | #define WM8904_LINEOUTL_ENA_OUTP_SHIFT 6 /* LINEOUTL_ENA_OUTP */ | ||
1040 | #define WM8904_LINEOUTL_ENA_OUTP_WIDTH 1 /* LINEOUTL_ENA_OUTP */ | ||
1041 | #define WM8904_LINEOUTL_ENA_DLY 0x0020 /* LINEOUTL_ENA_DLY */ | ||
1042 | #define WM8904_LINEOUTL_ENA_DLY_MASK 0x0020 /* LINEOUTL_ENA_DLY */ | ||
1043 | #define WM8904_LINEOUTL_ENA_DLY_SHIFT 5 /* LINEOUTL_ENA_DLY */ | ||
1044 | #define WM8904_LINEOUTL_ENA_DLY_WIDTH 1 /* LINEOUTL_ENA_DLY */ | ||
1045 | #define WM8904_LINEOUTL_ENA 0x0010 /* LINEOUTL_ENA */ | ||
1046 | #define WM8904_LINEOUTL_ENA_MASK 0x0010 /* LINEOUTL_ENA */ | ||
1047 | #define WM8904_LINEOUTL_ENA_SHIFT 4 /* LINEOUTL_ENA */ | ||
1048 | #define WM8904_LINEOUTL_ENA_WIDTH 1 /* LINEOUTL_ENA */ | ||
1049 | #define WM8904_LINEOUTR_RMV_SHORT 0x0008 /* LINEOUTR_RMV_SHORT */ | ||
1050 | #define WM8904_LINEOUTR_RMV_SHORT_MASK 0x0008 /* LINEOUTR_RMV_SHORT */ | ||
1051 | #define WM8904_LINEOUTR_RMV_SHORT_SHIFT 3 /* LINEOUTR_RMV_SHORT */ | ||
1052 | #define WM8904_LINEOUTR_RMV_SHORT_WIDTH 1 /* LINEOUTR_RMV_SHORT */ | ||
1053 | #define WM8904_LINEOUTR_ENA_OUTP 0x0004 /* LINEOUTR_ENA_OUTP */ | ||
1054 | #define WM8904_LINEOUTR_ENA_OUTP_MASK 0x0004 /* LINEOUTR_ENA_OUTP */ | ||
1055 | #define WM8904_LINEOUTR_ENA_OUTP_SHIFT 2 /* LINEOUTR_ENA_OUTP */ | ||
1056 | #define WM8904_LINEOUTR_ENA_OUTP_WIDTH 1 /* LINEOUTR_ENA_OUTP */ | ||
1057 | #define WM8904_LINEOUTR_ENA_DLY 0x0002 /* LINEOUTR_ENA_DLY */ | ||
1058 | #define WM8904_LINEOUTR_ENA_DLY_MASK 0x0002 /* LINEOUTR_ENA_DLY */ | ||
1059 | #define WM8904_LINEOUTR_ENA_DLY_SHIFT 1 /* LINEOUTR_ENA_DLY */ | ||
1060 | #define WM8904_LINEOUTR_ENA_DLY_WIDTH 1 /* LINEOUTR_ENA_DLY */ | ||
1061 | #define WM8904_LINEOUTR_ENA 0x0001 /* LINEOUTR_ENA */ | ||
1062 | #define WM8904_LINEOUTR_ENA_MASK 0x0001 /* LINEOUTR_ENA */ | ||
1063 | #define WM8904_LINEOUTR_ENA_SHIFT 0 /* LINEOUTR_ENA */ | ||
1064 | #define WM8904_LINEOUTR_ENA_WIDTH 1 /* LINEOUTR_ENA */ | ||
1065 | |||
1066 | /* | ||
1067 | * R98 (0x62) - Charge Pump 0 | ||
1068 | */ | ||
1069 | #define WM8904_CP_ENA 0x0001 /* CP_ENA */ | ||
1070 | #define WM8904_CP_ENA_MASK 0x0001 /* CP_ENA */ | ||
1071 | #define WM8904_CP_ENA_SHIFT 0 /* CP_ENA */ | ||
1072 | #define WM8904_CP_ENA_WIDTH 1 /* CP_ENA */ | ||
1073 | |||
1074 | /* | ||
1075 | * R104 (0x68) - Class W 0 | ||
1076 | */ | ||
1077 | #define WM8904_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */ | ||
1078 | #define WM8904_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */ | ||
1079 | #define WM8904_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */ | ||
1080 | #define WM8904_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */ | ||
1081 | |||
1082 | /* | ||
1083 | * R108 (0x6C) - Write Sequencer 0 | ||
1084 | */ | ||
1085 | #define WM8904_WSEQ_ENA 0x0100 /* WSEQ_ENA */ | ||
1086 | #define WM8904_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ | ||
1087 | #define WM8904_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ | ||
1088 | #define WM8904_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ | ||
1089 | #define WM8904_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ | ||
1090 | #define WM8904_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ | ||
1091 | #define WM8904_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ | ||
1092 | |||
1093 | /* | ||
1094 | * R109 (0x6D) - Write Sequencer 1 | ||
1095 | */ | ||
1096 | #define WM8904_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ | ||
1097 | #define WM8904_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ | ||
1098 | #define WM8904_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ | ||
1099 | #define WM8904_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ | ||
1100 | #define WM8904_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ | ||
1101 | #define WM8904_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ | ||
1102 | #define WM8904_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ | ||
1103 | #define WM8904_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ | ||
1104 | #define WM8904_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ | ||
1105 | |||
1106 | /* | ||
1107 | * R110 (0x6E) - Write Sequencer 2 | ||
1108 | */ | ||
1109 | #define WM8904_WSEQ_EOS 0x4000 /* WSEQ_EOS */ | ||
1110 | #define WM8904_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ | ||
1111 | #define WM8904_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ | ||
1112 | #define WM8904_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ | ||
1113 | #define WM8904_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ | ||
1114 | #define WM8904_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ | ||
1115 | #define WM8904_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ | ||
1116 | #define WM8904_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ | ||
1117 | #define WM8904_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ | ||
1118 | #define WM8904_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ | ||
1119 | |||
1120 | /* | ||
1121 | * R111 (0x6F) - Write Sequencer 3 | ||
1122 | */ | ||
1123 | #define WM8904_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ | ||
1124 | #define WM8904_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ | ||
1125 | #define WM8904_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ | ||
1126 | #define WM8904_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ | ||
1127 | #define WM8904_WSEQ_START 0x0100 /* WSEQ_START */ | ||
1128 | #define WM8904_WSEQ_START_MASK 0x0100 /* WSEQ_START */ | ||
1129 | #define WM8904_WSEQ_START_SHIFT 8 /* WSEQ_START */ | ||
1130 | #define WM8904_WSEQ_START_WIDTH 1 /* WSEQ_START */ | ||
1131 | #define WM8904_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ | ||
1132 | #define WM8904_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ | ||
1133 | #define WM8904_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ | ||
1134 | |||
1135 | /* | ||
1136 | * R112 (0x70) - Write Sequencer 4 | ||
1137 | */ | ||
1138 | #define WM8904_WSEQ_CURRENT_INDEX_MASK 0x03F0 /* WSEQ_CURRENT_INDEX - [9:4] */ | ||
1139 | #define WM8904_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [9:4] */ | ||
1140 | #define WM8904_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [9:4] */ | ||
1141 | #define WM8904_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ | ||
1142 | #define WM8904_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ | ||
1143 | #define WM8904_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ | ||
1144 | #define WM8904_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ | ||
1145 | |||
1146 | /* | ||
1147 | * R116 (0x74) - FLL Control 1 | ||
1148 | */ | ||
1149 | #define WM8904_FLL_FRACN_ENA 0x0004 /* FLL_FRACN_ENA */ | ||
1150 | #define WM8904_FLL_FRACN_ENA_MASK 0x0004 /* FLL_FRACN_ENA */ | ||
1151 | #define WM8904_FLL_FRACN_ENA_SHIFT 2 /* FLL_FRACN_ENA */ | ||
1152 | #define WM8904_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */ | ||
1153 | #define WM8904_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ | ||
1154 | #define WM8904_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ | ||
1155 | #define WM8904_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ | ||
1156 | #define WM8904_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ | ||
1157 | #define WM8904_FLL_ENA 0x0001 /* FLL_ENA */ | ||
1158 | #define WM8904_FLL_ENA_MASK 0x0001 /* FLL_ENA */ | ||
1159 | #define WM8904_FLL_ENA_SHIFT 0 /* FLL_ENA */ | ||
1160 | #define WM8904_FLL_ENA_WIDTH 1 /* FLL_ENA */ | ||
1161 | |||
1162 | /* | ||
1163 | * R117 (0x75) - FLL Control 2 | ||
1164 | */ | ||
1165 | #define WM8904_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */ | ||
1166 | #define WM8904_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */ | ||
1167 | #define WM8904_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */ | ||
1168 | #define WM8904_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ | ||
1169 | #define WM8904_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ | ||
1170 | #define WM8904_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ | ||
1171 | #define WM8904_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ | ||
1172 | #define WM8904_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ | ||
1173 | #define WM8904_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ | ||
1174 | |||
1175 | /* | ||
1176 | * R118 (0x76) - FLL Control 3 | ||
1177 | */ | ||
1178 | #define WM8904_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ | ||
1179 | #define WM8904_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ | ||
1180 | #define WM8904_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ | ||
1181 | |||
1182 | /* | ||
1183 | * R119 (0x77) - FLL Control 4 | ||
1184 | */ | ||
1185 | #define WM8904_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ | ||
1186 | #define WM8904_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ | ||
1187 | #define WM8904_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ | ||
1188 | #define WM8904_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ | ||
1189 | #define WM8904_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ | ||
1190 | #define WM8904_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ | ||
1191 | |||
1192 | /* | ||
1193 | * R120 (0x78) - FLL Control 5 | ||
1194 | */ | ||
1195 | #define WM8904_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ | ||
1196 | #define WM8904_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ | ||
1197 | #define WM8904_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ | ||
1198 | #define WM8904_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */ | ||
1199 | #define WM8904_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */ | ||
1200 | #define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */ | ||
1201 | |||
1202 | /* | ||
1203 | * R121 (0x79) - GPIO Control 1 | ||
1204 | */ | ||
1205 | #define WM8904_GPIO1_PU 0x0020 /* GPIO1_PU */ | ||
1206 | #define WM8904_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */ | ||
1207 | #define WM8904_GPIO1_PU_SHIFT 5 /* GPIO1_PU */ | ||
1208 | #define WM8904_GPIO1_PU_WIDTH 1 /* GPIO1_PU */ | ||
1209 | #define WM8904_GPIO1_PD 0x0010 /* GPIO1_PD */ | ||
1210 | #define WM8904_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */ | ||
1211 | #define WM8904_GPIO1_PD_SHIFT 4 /* GPIO1_PD */ | ||
1212 | #define WM8904_GPIO1_PD_WIDTH 1 /* GPIO1_PD */ | ||
1213 | #define WM8904_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ | ||
1214 | #define WM8904_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */ | ||
1215 | #define WM8904_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */ | ||
1216 | |||
1217 | /* | ||
1218 | * R122 (0x7A) - GPIO Control 2 | ||
1219 | */ | ||
1220 | #define WM8904_GPIO2_PU 0x0020 /* GPIO2_PU */ | ||
1221 | #define WM8904_GPIO2_PU_MASK 0x0020 /* GPIO2_PU */ | ||
1222 | #define WM8904_GPIO2_PU_SHIFT 5 /* GPIO2_PU */ | ||
1223 | #define WM8904_GPIO2_PU_WIDTH 1 /* GPIO2_PU */ | ||
1224 | #define WM8904_GPIO2_PD 0x0010 /* GPIO2_PD */ | ||
1225 | #define WM8904_GPIO2_PD_MASK 0x0010 /* GPIO2_PD */ | ||
1226 | #define WM8904_GPIO2_PD_SHIFT 4 /* GPIO2_PD */ | ||
1227 | #define WM8904_GPIO2_PD_WIDTH 1 /* GPIO2_PD */ | ||
1228 | #define WM8904_GPIO2_SEL_MASK 0x000F /* GPIO2_SEL - [3:0] */ | ||
1229 | #define WM8904_GPIO2_SEL_SHIFT 0 /* GPIO2_SEL - [3:0] */ | ||
1230 | #define WM8904_GPIO2_SEL_WIDTH 4 /* GPIO2_SEL - [3:0] */ | ||
1231 | |||
1232 | /* | ||
1233 | * R123 (0x7B) - GPIO Control 3 | ||
1234 | */ | ||
1235 | #define WM8904_GPIO3_PU 0x0020 /* GPIO3_PU */ | ||
1236 | #define WM8904_GPIO3_PU_MASK 0x0020 /* GPIO3_PU */ | ||
1237 | #define WM8904_GPIO3_PU_SHIFT 5 /* GPIO3_PU */ | ||
1238 | #define WM8904_GPIO3_PU_WIDTH 1 /* GPIO3_PU */ | ||
1239 | #define WM8904_GPIO3_PD 0x0010 /* GPIO3_PD */ | ||
1240 | #define WM8904_GPIO3_PD_MASK 0x0010 /* GPIO3_PD */ | ||
1241 | #define WM8904_GPIO3_PD_SHIFT 4 /* GPIO3_PD */ | ||
1242 | #define WM8904_GPIO3_PD_WIDTH 1 /* GPIO3_PD */ | ||
1243 | #define WM8904_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */ | ||
1244 | #define WM8904_GPIO3_SEL_SHIFT 0 /* GPIO3_SEL - [3:0] */ | ||
1245 | #define WM8904_GPIO3_SEL_WIDTH 4 /* GPIO3_SEL - [3:0] */ | ||
1246 | |||
1247 | /* | ||
1248 | * R124 (0x7C) - GPIO Control 4 | ||
1249 | */ | ||
1250 | #define WM8904_GPI7_ENA 0x0200 /* GPI7_ENA */ | ||
1251 | #define WM8904_GPI7_ENA_MASK 0x0200 /* GPI7_ENA */ | ||
1252 | #define WM8904_GPI7_ENA_SHIFT 9 /* GPI7_ENA */ | ||
1253 | #define WM8904_GPI7_ENA_WIDTH 1 /* GPI7_ENA */ | ||
1254 | #define WM8904_GPI8_ENA 0x0100 /* GPI8_ENA */ | ||
1255 | #define WM8904_GPI8_ENA_MASK 0x0100 /* GPI8_ENA */ | ||
1256 | #define WM8904_GPI8_ENA_SHIFT 8 /* GPI8_ENA */ | ||
1257 | #define WM8904_GPI8_ENA_WIDTH 1 /* GPI8_ENA */ | ||
1258 | #define WM8904_GPIO_BCLK_MODE_ENA 0x0080 /* GPIO_BCLK_MODE_ENA */ | ||
1259 | #define WM8904_GPIO_BCLK_MODE_ENA_MASK 0x0080 /* GPIO_BCLK_MODE_ENA */ | ||
1260 | #define WM8904_GPIO_BCLK_MODE_ENA_SHIFT 7 /* GPIO_BCLK_MODE_ENA */ | ||
1261 | #define WM8904_GPIO_BCLK_MODE_ENA_WIDTH 1 /* GPIO_BCLK_MODE_ENA */ | ||
1262 | #define WM8904_GPIO_BCLK_SEL_MASK 0x000F /* GPIO_BCLK_SEL - [3:0] */ | ||
1263 | #define WM8904_GPIO_BCLK_SEL_SHIFT 0 /* GPIO_BCLK_SEL - [3:0] */ | ||
1264 | #define WM8904_GPIO_BCLK_SEL_WIDTH 4 /* GPIO_BCLK_SEL - [3:0] */ | ||
1265 | |||
1266 | /* | ||
1267 | * R126 (0x7E) - Digital Pulls | ||
1268 | */ | ||
1269 | #define WM8904_MCLK_PU 0x0080 /* MCLK_PU */ | ||
1270 | #define WM8904_MCLK_PU_MASK 0x0080 /* MCLK_PU */ | ||
1271 | #define WM8904_MCLK_PU_SHIFT 7 /* MCLK_PU */ | ||
1272 | #define WM8904_MCLK_PU_WIDTH 1 /* MCLK_PU */ | ||
1273 | #define WM8904_MCLK_PD 0x0040 /* MCLK_PD */ | ||
1274 | #define WM8904_MCLK_PD_MASK 0x0040 /* MCLK_PD */ | ||
1275 | #define WM8904_MCLK_PD_SHIFT 6 /* MCLK_PD */ | ||
1276 | #define WM8904_MCLK_PD_WIDTH 1 /* MCLK_PD */ | ||
1277 | #define WM8904_DACDAT_PU 0x0020 /* DACDAT_PU */ | ||
1278 | #define WM8904_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */ | ||
1279 | #define WM8904_DACDAT_PU_SHIFT 5 /* DACDAT_PU */ | ||
1280 | #define WM8904_DACDAT_PU_WIDTH 1 /* DACDAT_PU */ | ||
1281 | #define WM8904_DACDAT_PD 0x0010 /* DACDAT_PD */ | ||
1282 | #define WM8904_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */ | ||
1283 | #define WM8904_DACDAT_PD_SHIFT 4 /* DACDAT_PD */ | ||
1284 | #define WM8904_DACDAT_PD_WIDTH 1 /* DACDAT_PD */ | ||
1285 | #define WM8904_LRCLK_PU 0x0008 /* LRCLK_PU */ | ||
1286 | #define WM8904_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */ | ||
1287 | #define WM8904_LRCLK_PU_SHIFT 3 /* LRCLK_PU */ | ||
1288 | #define WM8904_LRCLK_PU_WIDTH 1 /* LRCLK_PU */ | ||
1289 | #define WM8904_LRCLK_PD 0x0004 /* LRCLK_PD */ | ||
1290 | #define WM8904_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */ | ||
1291 | #define WM8904_LRCLK_PD_SHIFT 2 /* LRCLK_PD */ | ||
1292 | #define WM8904_LRCLK_PD_WIDTH 1 /* LRCLK_PD */ | ||
1293 | #define WM8904_BCLK_PU 0x0002 /* BCLK_PU */ | ||
1294 | #define WM8904_BCLK_PU_MASK 0x0002 /* BCLK_PU */ | ||
1295 | #define WM8904_BCLK_PU_SHIFT 1 /* BCLK_PU */ | ||
1296 | #define WM8904_BCLK_PU_WIDTH 1 /* BCLK_PU */ | ||
1297 | #define WM8904_BCLK_PD 0x0001 /* BCLK_PD */ | ||
1298 | #define WM8904_BCLK_PD_MASK 0x0001 /* BCLK_PD */ | ||
1299 | #define WM8904_BCLK_PD_SHIFT 0 /* BCLK_PD */ | ||
1300 | #define WM8904_BCLK_PD_WIDTH 1 /* BCLK_PD */ | ||
1301 | |||
1302 | /* | ||
1303 | * R127 (0x7F) - Interrupt Status | ||
1304 | */ | ||
1305 | #define WM8904_IRQ 0x0400 /* IRQ */ | ||
1306 | #define WM8904_IRQ_MASK 0x0400 /* IRQ */ | ||
1307 | #define WM8904_IRQ_SHIFT 10 /* IRQ */ | ||
1308 | #define WM8904_IRQ_WIDTH 1 /* IRQ */ | ||
1309 | #define WM8904_GPIO_BCLK_EINT 0x0200 /* GPIO_BCLK_EINT */ | ||
1310 | #define WM8904_GPIO_BCLK_EINT_MASK 0x0200 /* GPIO_BCLK_EINT */ | ||
1311 | #define WM8904_GPIO_BCLK_EINT_SHIFT 9 /* GPIO_BCLK_EINT */ | ||
1312 | #define WM8904_GPIO_BCLK_EINT_WIDTH 1 /* GPIO_BCLK_EINT */ | ||
1313 | #define WM8904_WSEQ_EINT 0x0100 /* WSEQ_EINT */ | ||
1314 | #define WM8904_WSEQ_EINT_MASK 0x0100 /* WSEQ_EINT */ | ||
1315 | #define WM8904_WSEQ_EINT_SHIFT 8 /* WSEQ_EINT */ | ||
1316 | #define WM8904_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */ | ||
1317 | #define WM8904_GPIO3_EINT 0x0080 /* GPIO3_EINT */ | ||
1318 | #define WM8904_GPIO3_EINT_MASK 0x0080 /* GPIO3_EINT */ | ||
1319 | #define WM8904_GPIO3_EINT_SHIFT 7 /* GPIO3_EINT */ | ||
1320 | #define WM8904_GPIO3_EINT_WIDTH 1 /* GPIO3_EINT */ | ||
1321 | #define WM8904_GPIO2_EINT 0x0040 /* GPIO2_EINT */ | ||
1322 | #define WM8904_GPIO2_EINT_MASK 0x0040 /* GPIO2_EINT */ | ||
1323 | #define WM8904_GPIO2_EINT_SHIFT 6 /* GPIO2_EINT */ | ||
1324 | #define WM8904_GPIO2_EINT_WIDTH 1 /* GPIO2_EINT */ | ||
1325 | #define WM8904_GPIO1_EINT 0x0020 /* GPIO1_EINT */ | ||
1326 | #define WM8904_GPIO1_EINT_MASK 0x0020 /* GPIO1_EINT */ | ||
1327 | #define WM8904_GPIO1_EINT_SHIFT 5 /* GPIO1_EINT */ | ||
1328 | #define WM8904_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */ | ||
1329 | #define WM8904_GPI8_EINT 0x0010 /* GPI8_EINT */ | ||
1330 | #define WM8904_GPI8_EINT_MASK 0x0010 /* GPI8_EINT */ | ||
1331 | #define WM8904_GPI8_EINT_SHIFT 4 /* GPI8_EINT */ | ||
1332 | #define WM8904_GPI8_EINT_WIDTH 1 /* GPI8_EINT */ | ||
1333 | #define WM8904_GPI7_EINT 0x0008 /* GPI7_EINT */ | ||
1334 | #define WM8904_GPI7_EINT_MASK 0x0008 /* GPI7_EINT */ | ||
1335 | #define WM8904_GPI7_EINT_SHIFT 3 /* GPI7_EINT */ | ||
1336 | #define WM8904_GPI7_EINT_WIDTH 1 /* GPI7_EINT */ | ||
1337 | #define WM8904_FLL_LOCK_EINT 0x0004 /* FLL_LOCK_EINT */ | ||
1338 | #define WM8904_FLL_LOCK_EINT_MASK 0x0004 /* FLL_LOCK_EINT */ | ||
1339 | #define WM8904_FLL_LOCK_EINT_SHIFT 2 /* FLL_LOCK_EINT */ | ||
1340 | #define WM8904_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ | ||
1341 | #define WM8904_MIC_SHRT_EINT 0x0002 /* MIC_SHRT_EINT */ | ||
1342 | #define WM8904_MIC_SHRT_EINT_MASK 0x0002 /* MIC_SHRT_EINT */ | ||
1343 | #define WM8904_MIC_SHRT_EINT_SHIFT 1 /* MIC_SHRT_EINT */ | ||
1344 | #define WM8904_MIC_SHRT_EINT_WIDTH 1 /* MIC_SHRT_EINT */ | ||
1345 | #define WM8904_MIC_DET_EINT 0x0001 /* MIC_DET_EINT */ | ||
1346 | #define WM8904_MIC_DET_EINT_MASK 0x0001 /* MIC_DET_EINT */ | ||
1347 | #define WM8904_MIC_DET_EINT_SHIFT 0 /* MIC_DET_EINT */ | ||
1348 | #define WM8904_MIC_DET_EINT_WIDTH 1 /* MIC_DET_EINT */ | ||
1349 | |||
1350 | /* | ||
1351 | * R128 (0x80) - Interrupt Status Mask | ||
1352 | */ | ||
1353 | #define WM8904_IM_GPIO_BCLK_EINT 0x0200 /* IM_GPIO_BCLK_EINT */ | ||
1354 | #define WM8904_IM_GPIO_BCLK_EINT_MASK 0x0200 /* IM_GPIO_BCLK_EINT */ | ||
1355 | #define WM8904_IM_GPIO_BCLK_EINT_SHIFT 9 /* IM_GPIO_BCLK_EINT */ | ||
1356 | #define WM8904_IM_GPIO_BCLK_EINT_WIDTH 1 /* IM_GPIO_BCLK_EINT */ | ||
1357 | #define WM8904_IM_WSEQ_EINT 0x0100 /* IM_WSEQ_EINT */ | ||
1358 | #define WM8904_IM_WSEQ_EINT_MASK 0x0100 /* IM_WSEQ_EINT */ | ||
1359 | #define WM8904_IM_WSEQ_EINT_SHIFT 8 /* IM_WSEQ_EINT */ | ||
1360 | #define WM8904_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */ | ||
1361 | #define WM8904_IM_GPIO3_EINT 0x0080 /* IM_GPIO3_EINT */ | ||
1362 | #define WM8904_IM_GPIO3_EINT_MASK 0x0080 /* IM_GPIO3_EINT */ | ||
1363 | #define WM8904_IM_GPIO3_EINT_SHIFT 7 /* IM_GPIO3_EINT */ | ||
1364 | #define WM8904_IM_GPIO3_EINT_WIDTH 1 /* IM_GPIO3_EINT */ | ||
1365 | #define WM8904_IM_GPIO2_EINT 0x0040 /* IM_GPIO2_EINT */ | ||
1366 | #define WM8904_IM_GPIO2_EINT_MASK 0x0040 /* IM_GPIO2_EINT */ | ||
1367 | #define WM8904_IM_GPIO2_EINT_SHIFT 6 /* IM_GPIO2_EINT */ | ||
1368 | #define WM8904_IM_GPIO2_EINT_WIDTH 1 /* IM_GPIO2_EINT */ | ||
1369 | #define WM8904_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */ | ||
1370 | #define WM8904_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */ | ||
1371 | #define WM8904_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */ | ||
1372 | #define WM8904_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */ | ||
1373 | #define WM8904_IM_GPI8_EINT 0x0010 /* IM_GPI8_EINT */ | ||
1374 | #define WM8904_IM_GPI8_EINT_MASK 0x0010 /* IM_GPI8_EINT */ | ||
1375 | #define WM8904_IM_GPI8_EINT_SHIFT 4 /* IM_GPI8_EINT */ | ||
1376 | #define WM8904_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */ | ||
1377 | #define WM8904_IM_GPI7_EINT 0x0008 /* IM_GPI7_EINT */ | ||
1378 | #define WM8904_IM_GPI7_EINT_MASK 0x0008 /* IM_GPI7_EINT */ | ||
1379 | #define WM8904_IM_GPI7_EINT_SHIFT 3 /* IM_GPI7_EINT */ | ||
1380 | #define WM8904_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */ | ||
1381 | #define WM8904_IM_FLL_LOCK_EINT 0x0004 /* IM_FLL_LOCK_EINT */ | ||
1382 | #define WM8904_IM_FLL_LOCK_EINT_MASK 0x0004 /* IM_FLL_LOCK_EINT */ | ||
1383 | #define WM8904_IM_FLL_LOCK_EINT_SHIFT 2 /* IM_FLL_LOCK_EINT */ | ||
1384 | #define WM8904_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ | ||
1385 | #define WM8904_IM_MIC_SHRT_EINT 0x0002 /* IM_MIC_SHRT_EINT */ | ||
1386 | #define WM8904_IM_MIC_SHRT_EINT_MASK 0x0002 /* IM_MIC_SHRT_EINT */ | ||
1387 | #define WM8904_IM_MIC_SHRT_EINT_SHIFT 1 /* IM_MIC_SHRT_EINT */ | ||
1388 | #define WM8904_IM_MIC_SHRT_EINT_WIDTH 1 /* IM_MIC_SHRT_EINT */ | ||
1389 | #define WM8904_IM_MIC_DET_EINT 0x0001 /* IM_MIC_DET_EINT */ | ||
1390 | #define WM8904_IM_MIC_DET_EINT_MASK 0x0001 /* IM_MIC_DET_EINT */ | ||
1391 | #define WM8904_IM_MIC_DET_EINT_SHIFT 0 /* IM_MIC_DET_EINT */ | ||
1392 | #define WM8904_IM_MIC_DET_EINT_WIDTH 1 /* IM_MIC_DET_EINT */ | ||
1393 | |||
1394 | /* | ||
1395 | * R129 (0x81) - Interrupt Polarity | ||
1396 | */ | ||
1397 | #define WM8904_GPIO_BCLK_EINT_POL 0x0200 /* GPIO_BCLK_EINT_POL */ | ||
1398 | #define WM8904_GPIO_BCLK_EINT_POL_MASK 0x0200 /* GPIO_BCLK_EINT_POL */ | ||
1399 | #define WM8904_GPIO_BCLK_EINT_POL_SHIFT 9 /* GPIO_BCLK_EINT_POL */ | ||
1400 | #define WM8904_GPIO_BCLK_EINT_POL_WIDTH 1 /* GPIO_BCLK_EINT_POL */ | ||
1401 | #define WM8904_WSEQ_EINT_POL 0x0100 /* WSEQ_EINT_POL */ | ||
1402 | #define WM8904_WSEQ_EINT_POL_MASK 0x0100 /* WSEQ_EINT_POL */ | ||
1403 | #define WM8904_WSEQ_EINT_POL_SHIFT 8 /* WSEQ_EINT_POL */ | ||
1404 | #define WM8904_WSEQ_EINT_POL_WIDTH 1 /* WSEQ_EINT_POL */ | ||
1405 | #define WM8904_GPIO3_EINT_POL 0x0080 /* GPIO3_EINT_POL */ | ||
1406 | #define WM8904_GPIO3_EINT_POL_MASK 0x0080 /* GPIO3_EINT_POL */ | ||
1407 | #define WM8904_GPIO3_EINT_POL_SHIFT 7 /* GPIO3_EINT_POL */ | ||
1408 | #define WM8904_GPIO3_EINT_POL_WIDTH 1 /* GPIO3_EINT_POL */ | ||
1409 | #define WM8904_GPIO2_EINT_POL 0x0040 /* GPIO2_EINT_POL */ | ||
1410 | #define WM8904_GPIO2_EINT_POL_MASK 0x0040 /* GPIO2_EINT_POL */ | ||
1411 | #define WM8904_GPIO2_EINT_POL_SHIFT 6 /* GPIO2_EINT_POL */ | ||
1412 | #define WM8904_GPIO2_EINT_POL_WIDTH 1 /* GPIO2_EINT_POL */ | ||
1413 | #define WM8904_GPIO1_EINT_POL 0x0020 /* GPIO1_EINT_POL */ | ||
1414 | #define WM8904_GPIO1_EINT_POL_MASK 0x0020 /* GPIO1_EINT_POL */ | ||
1415 | #define WM8904_GPIO1_EINT_POL_SHIFT 5 /* GPIO1_EINT_POL */ | ||
1416 | #define WM8904_GPIO1_EINT_POL_WIDTH 1 /* GPIO1_EINT_POL */ | ||
1417 | #define WM8904_GPI8_EINT_POL 0x0010 /* GPI8_EINT_POL */ | ||
1418 | #define WM8904_GPI8_EINT_POL_MASK 0x0010 /* GPI8_EINT_POL */ | ||
1419 | #define WM8904_GPI8_EINT_POL_SHIFT 4 /* GPI8_EINT_POL */ | ||
1420 | #define WM8904_GPI8_EINT_POL_WIDTH 1 /* GPI8_EINT_POL */ | ||
1421 | #define WM8904_GPI7_EINT_POL 0x0008 /* GPI7_EINT_POL */ | ||
1422 | #define WM8904_GPI7_EINT_POL_MASK 0x0008 /* GPI7_EINT_POL */ | ||
1423 | #define WM8904_GPI7_EINT_POL_SHIFT 3 /* GPI7_EINT_POL */ | ||
1424 | #define WM8904_GPI7_EINT_POL_WIDTH 1 /* GPI7_EINT_POL */ | ||
1425 | #define WM8904_FLL_LOCK_EINT_POL 0x0004 /* FLL_LOCK_EINT_POL */ | ||
1426 | #define WM8904_FLL_LOCK_EINT_POL_MASK 0x0004 /* FLL_LOCK_EINT_POL */ | ||
1427 | #define WM8904_FLL_LOCK_EINT_POL_SHIFT 2 /* FLL_LOCK_EINT_POL */ | ||
1428 | #define WM8904_FLL_LOCK_EINT_POL_WIDTH 1 /* FLL_LOCK_EINT_POL */ | ||
1429 | #define WM8904_MIC_SHRT_EINT_POL 0x0002 /* MIC_SHRT_EINT_POL */ | ||
1430 | #define WM8904_MIC_SHRT_EINT_POL_MASK 0x0002 /* MIC_SHRT_EINT_POL */ | ||
1431 | #define WM8904_MIC_SHRT_EINT_POL_SHIFT 1 /* MIC_SHRT_EINT_POL */ | ||
1432 | #define WM8904_MIC_SHRT_EINT_POL_WIDTH 1 /* MIC_SHRT_EINT_POL */ | ||
1433 | #define WM8904_MIC_DET_EINT_POL 0x0001 /* MIC_DET_EINT_POL */ | ||
1434 | #define WM8904_MIC_DET_EINT_POL_MASK 0x0001 /* MIC_DET_EINT_POL */ | ||
1435 | #define WM8904_MIC_DET_EINT_POL_SHIFT 0 /* MIC_DET_EINT_POL */ | ||
1436 | #define WM8904_MIC_DET_EINT_POL_WIDTH 1 /* MIC_DET_EINT_POL */ | ||
1437 | |||
1438 | /* | ||
1439 | * R130 (0x82) - Interrupt Debounce | ||
1440 | */ | ||
1441 | #define WM8904_GPIO_BCLK_EINT_DB 0x0200 /* GPIO_BCLK_EINT_DB */ | ||
1442 | #define WM8904_GPIO_BCLK_EINT_DB_MASK 0x0200 /* GPIO_BCLK_EINT_DB */ | ||
1443 | #define WM8904_GPIO_BCLK_EINT_DB_SHIFT 9 /* GPIO_BCLK_EINT_DB */ | ||
1444 | #define WM8904_GPIO_BCLK_EINT_DB_WIDTH 1 /* GPIO_BCLK_EINT_DB */ | ||
1445 | #define WM8904_WSEQ_EINT_DB 0x0100 /* WSEQ_EINT_DB */ | ||
1446 | #define WM8904_WSEQ_EINT_DB_MASK 0x0100 /* WSEQ_EINT_DB */ | ||
1447 | #define WM8904_WSEQ_EINT_DB_SHIFT 8 /* WSEQ_EINT_DB */ | ||
1448 | #define WM8904_WSEQ_EINT_DB_WIDTH 1 /* WSEQ_EINT_DB */ | ||
1449 | #define WM8904_GPIO3_EINT_DB 0x0080 /* GPIO3_EINT_DB */ | ||
1450 | #define WM8904_GPIO3_EINT_DB_MASK 0x0080 /* GPIO3_EINT_DB */ | ||
1451 | #define WM8904_GPIO3_EINT_DB_SHIFT 7 /* GPIO3_EINT_DB */ | ||
1452 | #define WM8904_GPIO3_EINT_DB_WIDTH 1 /* GPIO3_EINT_DB */ | ||
1453 | #define WM8904_GPIO2_EINT_DB 0x0040 /* GPIO2_EINT_DB */ | ||
1454 | #define WM8904_GPIO2_EINT_DB_MASK 0x0040 /* GPIO2_EINT_DB */ | ||
1455 | #define WM8904_GPIO2_EINT_DB_SHIFT 6 /* GPIO2_EINT_DB */ | ||
1456 | #define WM8904_GPIO2_EINT_DB_WIDTH 1 /* GPIO2_EINT_DB */ | ||
1457 | #define WM8904_GPIO1_EINT_DB 0x0020 /* GPIO1_EINT_DB */ | ||
1458 | #define WM8904_GPIO1_EINT_DB_MASK 0x0020 /* GPIO1_EINT_DB */ | ||
1459 | #define WM8904_GPIO1_EINT_DB_SHIFT 5 /* GPIO1_EINT_DB */ | ||
1460 | #define WM8904_GPIO1_EINT_DB_WIDTH 1 /* GPIO1_EINT_DB */ | ||
1461 | #define WM8904_GPI8_EINT_DB 0x0010 /* GPI8_EINT_DB */ | ||
1462 | #define WM8904_GPI8_EINT_DB_MASK 0x0010 /* GPI8_EINT_DB */ | ||
1463 | #define WM8904_GPI8_EINT_DB_SHIFT 4 /* GPI8_EINT_DB */ | ||
1464 | #define WM8904_GPI8_EINT_DB_WIDTH 1 /* GPI8_EINT_DB */ | ||
1465 | #define WM8904_GPI7_EINT_DB 0x0008 /* GPI7_EINT_DB */ | ||
1466 | #define WM8904_GPI7_EINT_DB_MASK 0x0008 /* GPI7_EINT_DB */ | ||
1467 | #define WM8904_GPI7_EINT_DB_SHIFT 3 /* GPI7_EINT_DB */ | ||
1468 | #define WM8904_GPI7_EINT_DB_WIDTH 1 /* GPI7_EINT_DB */ | ||
1469 | #define WM8904_FLL_LOCK_EINT_DB 0x0004 /* FLL_LOCK_EINT_DB */ | ||
1470 | #define WM8904_FLL_LOCK_EINT_DB_MASK 0x0004 /* FLL_LOCK_EINT_DB */ | ||
1471 | #define WM8904_FLL_LOCK_EINT_DB_SHIFT 2 /* FLL_LOCK_EINT_DB */ | ||
1472 | #define WM8904_FLL_LOCK_EINT_DB_WIDTH 1 /* FLL_LOCK_EINT_DB */ | ||
1473 | #define WM8904_MIC_SHRT_EINT_DB 0x0002 /* MIC_SHRT_EINT_DB */ | ||
1474 | #define WM8904_MIC_SHRT_EINT_DB_MASK 0x0002 /* MIC_SHRT_EINT_DB */ | ||
1475 | #define WM8904_MIC_SHRT_EINT_DB_SHIFT 1 /* MIC_SHRT_EINT_DB */ | ||
1476 | #define WM8904_MIC_SHRT_EINT_DB_WIDTH 1 /* MIC_SHRT_EINT_DB */ | ||
1477 | #define WM8904_MIC_DET_EINT_DB 0x0001 /* MIC_DET_EINT_DB */ | ||
1478 | #define WM8904_MIC_DET_EINT_DB_MASK 0x0001 /* MIC_DET_EINT_DB */ | ||
1479 | #define WM8904_MIC_DET_EINT_DB_SHIFT 0 /* MIC_DET_EINT_DB */ | ||
1480 | #define WM8904_MIC_DET_EINT_DB_WIDTH 1 /* MIC_DET_EINT_DB */ | ||
1481 | |||
1482 | /* | ||
1483 | * R134 (0x86) - EQ1 | ||
1484 | */ | ||
1485 | #define WM8904_EQ_ENA 0x0001 /* EQ_ENA */ | ||
1486 | #define WM8904_EQ_ENA_MASK 0x0001 /* EQ_ENA */ | ||
1487 | #define WM8904_EQ_ENA_SHIFT 0 /* EQ_ENA */ | ||
1488 | #define WM8904_EQ_ENA_WIDTH 1 /* EQ_ENA */ | ||
1489 | |||
1490 | /* | ||
1491 | * R135 (0x87) - EQ2 | ||
1492 | */ | ||
1493 | #define WM8904_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */ | ||
1494 | #define WM8904_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */ | ||
1495 | #define WM8904_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */ | ||
1496 | |||
1497 | /* | ||
1498 | * R136 (0x88) - EQ3 | ||
1499 | */ | ||
1500 | #define WM8904_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */ | ||
1501 | #define WM8904_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */ | ||
1502 | #define WM8904_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */ | ||
1503 | |||
1504 | /* | ||
1505 | * R137 (0x89) - EQ4 | ||
1506 | */ | ||
1507 | #define WM8904_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */ | ||
1508 | #define WM8904_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */ | ||
1509 | #define WM8904_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */ | ||
1510 | |||
1511 | /* | ||
1512 | * R138 (0x8A) - EQ5 | ||
1513 | */ | ||
1514 | #define WM8904_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */ | ||
1515 | #define WM8904_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */ | ||
1516 | #define WM8904_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */ | ||
1517 | |||
1518 | /* | ||
1519 | * R139 (0x8B) - EQ6 | ||
1520 | */ | ||
1521 | #define WM8904_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */ | ||
1522 | #define WM8904_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */ | ||
1523 | #define WM8904_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */ | ||
1524 | |||
1525 | /* | ||
1526 | * R140 (0x8C) - EQ7 | ||
1527 | */ | ||
1528 | #define WM8904_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ | ||
1529 | #define WM8904_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ | ||
1530 | #define WM8904_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ | ||
1531 | |||
1532 | /* | ||
1533 | * R141 (0x8D) - EQ8 | ||
1534 | */ | ||
1535 | #define WM8904_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ | ||
1536 | #define WM8904_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ | ||
1537 | #define WM8904_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ | ||
1538 | |||
1539 | /* | ||
1540 | * R142 (0x8E) - EQ9 | ||
1541 | */ | ||
1542 | #define WM8904_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ | ||
1543 | #define WM8904_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ | ||
1544 | #define WM8904_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ | ||
1545 | |||
1546 | /* | ||
1547 | * R143 (0x8F) - EQ10 | ||
1548 | */ | ||
1549 | #define WM8904_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ | ||
1550 | #define WM8904_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ | ||
1551 | #define WM8904_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ | ||
1552 | |||
1553 | /* | ||
1554 | * R144 (0x90) - EQ11 | ||
1555 | */ | ||
1556 | #define WM8904_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ | ||
1557 | #define WM8904_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ | ||
1558 | #define WM8904_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ | ||
1559 | |||
1560 | /* | ||
1561 | * R145 (0x91) - EQ12 | ||
1562 | */ | ||
1563 | #define WM8904_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ | ||
1564 | #define WM8904_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ | ||
1565 | #define WM8904_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ | ||
1566 | |||
1567 | /* | ||
1568 | * R146 (0x92) - EQ13 | ||
1569 | */ | ||
1570 | #define WM8904_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ | ||
1571 | #define WM8904_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ | ||
1572 | #define WM8904_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ | ||
1573 | |||
1574 | /* | ||
1575 | * R147 (0x93) - EQ14 | ||
1576 | */ | ||
1577 | #define WM8904_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ | ||
1578 | #define WM8904_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ | ||
1579 | #define WM8904_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ | ||
1580 | |||
1581 | /* | ||
1582 | * R148 (0x94) - EQ15 | ||
1583 | */ | ||
1584 | #define WM8904_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ | ||
1585 | #define WM8904_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ | ||
1586 | #define WM8904_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ | ||
1587 | |||
1588 | /* | ||
1589 | * R149 (0x95) - EQ16 | ||
1590 | */ | ||
1591 | #define WM8904_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ | ||
1592 | #define WM8904_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ | ||
1593 | #define WM8904_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ | ||
1594 | |||
1595 | /* | ||
1596 | * R150 (0x96) - EQ17 | ||
1597 | */ | ||
1598 | #define WM8904_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ | ||
1599 | #define WM8904_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ | ||
1600 | #define WM8904_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ | ||
1601 | |||
1602 | /* | ||
1603 | * R151 (0x97) - EQ18 | ||
1604 | */ | ||
1605 | #define WM8904_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ | ||
1606 | #define WM8904_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ | ||
1607 | #define WM8904_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ | ||
1608 | |||
1609 | /* | ||
1610 | * R152 (0x98) - EQ19 | ||
1611 | */ | ||
1612 | #define WM8904_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ | ||
1613 | #define WM8904_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ | ||
1614 | #define WM8904_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ | ||
1615 | |||
1616 | /* | ||
1617 | * R153 (0x99) - EQ20 | ||
1618 | */ | ||
1619 | #define WM8904_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ | ||
1620 | #define WM8904_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ | ||
1621 | #define WM8904_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ | ||
1622 | |||
1623 | /* | ||
1624 | * R154 (0x9A) - EQ21 | ||
1625 | */ | ||
1626 | #define WM8904_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ | ||
1627 | #define WM8904_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ | ||
1628 | #define WM8904_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ | ||
1629 | |||
1630 | /* | ||
1631 | * R155 (0x9B) - EQ22 | ||
1632 | */ | ||
1633 | #define WM8904_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ | ||
1634 | #define WM8904_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ | ||
1635 | #define WM8904_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ | ||
1636 | |||
1637 | /* | ||
1638 | * R156 (0x9C) - EQ23 | ||
1639 | */ | ||
1640 | #define WM8904_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ | ||
1641 | #define WM8904_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ | ||
1642 | #define WM8904_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ | ||
1643 | |||
1644 | /* | ||
1645 | * R157 (0x9D) - EQ24 | ||
1646 | */ | ||
1647 | #define WM8904_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ | ||
1648 | #define WM8904_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ | ||
1649 | #define WM8904_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ | ||
1650 | |||
1651 | /* | ||
1652 | * R161 (0xA1) - Control Interface Test 1 | ||
1653 | */ | ||
1654 | #define WM8904_USER_KEY 0x0002 /* USER_KEY */ | ||
1655 | #define WM8904_USER_KEY_MASK 0x0002 /* USER_KEY */ | ||
1656 | #define WM8904_USER_KEY_SHIFT 1 /* USER_KEY */ | ||
1657 | #define WM8904_USER_KEY_WIDTH 1 /* USER_KEY */ | ||
1658 | |||
1659 | /* | ||
1660 | * R204 (0xCC) - Analogue Output Bias 0 | ||
1661 | */ | ||
1662 | #define WM8904_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */ | ||
1663 | #define WM8904_PGA_BIAS_SHIFT 4 /* PGA_BIAS - [6:4] */ | ||
1664 | #define WM8904_PGA_BIAS_WIDTH 3 /* PGA_BIAS - [6:4] */ | ||
1665 | |||
1666 | /* | ||
1667 | * R247 (0xF7) - FLL NCO Test 0 | ||
1668 | */ | ||
1669 | #define WM8904_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */ | ||
1670 | #define WM8904_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */ | ||
1671 | #define WM8904_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */ | ||
1672 | #define WM8904_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ | ||
1673 | |||
1674 | /* | ||
1675 | * R248 (0xF8) - FLL NCO Test 1 | ||
1676 | */ | ||
1677 | #define WM8904_FLL_FRC_NCO_VAL_MASK 0x003F /* FLL_FRC_NCO_VAL - [5:0] */ | ||
1678 | #define WM8904_FLL_FRC_NCO_VAL_SHIFT 0 /* FLL_FRC_NCO_VAL - [5:0] */ | ||
1679 | #define WM8904_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [5:0] */ | ||
1680 | |||
1681 | #endif | ||
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 1ef2454c5205..0c04b476487f 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/spi/spi.h> | 32 | #include <linux/spi/spi.h> |
33 | #include <linux/slab.h> | ||
33 | #include <sound/core.h> | 34 | #include <sound/core.h> |
34 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
35 | #include <sound/pcm_params.h> | 36 | #include <sound/pcm_params.h> |
@@ -298,7 +299,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec) | |||
298 | ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 299 | ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
299 | if (ret) | 300 | if (ret) |
300 | goto error_ret; | 301 | goto error_ret; |
301 | ret = snd_soc_dapm_new_widgets(codec); | ||
302 | 302 | ||
303 | error_ret: | 303 | error_ret: |
304 | return ret; | 304 | return ret; |
@@ -379,23 +379,23 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, | |||
379 | iface |= (1 << 9); | 379 | iface |= (1 << 9); |
380 | 380 | ||
381 | switch (params_rate(params)) { | 381 | switch (params_rate(params)) { |
382 | case SNDRV_PCM_RATE_8000: | 382 | case 8000: |
383 | addcntrl |= (0x5 << 1); | 383 | addcntrl |= (0x5 << 1); |
384 | break; | 384 | break; |
385 | case SNDRV_PCM_RATE_11025: | 385 | case 11025: |
386 | addcntrl |= (0x4 << 1); | 386 | addcntrl |= (0x4 << 1); |
387 | break; | 387 | break; |
388 | case SNDRV_PCM_RATE_16000: | 388 | case 16000: |
389 | addcntrl |= (0x3 << 1); | 389 | addcntrl |= (0x3 << 1); |
390 | break; | 390 | break; |
391 | case SNDRV_PCM_RATE_22050: | 391 | case 22050: |
392 | addcntrl |= (0x2 << 1); | 392 | addcntrl |= (0x2 << 1); |
393 | break; | 393 | break; |
394 | case SNDRV_PCM_RATE_32000: | 394 | case 32000: |
395 | addcntrl |= (0x1 << 1); | 395 | addcntrl |= (0x1 << 1); |
396 | break; | 396 | break; |
397 | case SNDRV_PCM_RATE_44100: | 397 | case 44100: |
398 | case SNDRV_PCM_RATE_48000: | 398 | case 48000: |
399 | break; | 399 | break; |
400 | } | 400 | } |
401 | ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); | 401 | ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); |
@@ -536,8 +536,8 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
536 | } | 536 | } |
537 | 537 | ||
538 | /* Untested at the moment */ | 538 | /* Untested at the moment */ |
539 | static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, | 539 | static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
540 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 540 | int source, unsigned int freq_in, unsigned int freq_out) |
541 | { | 541 | { |
542 | struct snd_soc_codec *codec = codec_dai->codec; | 542 | struct snd_soc_codec *codec = codec_dai->codec; |
543 | u16 reg; | 543 | u16 reg; |
@@ -731,12 +731,6 @@ static int wm8940_probe(struct platform_device *pdev) | |||
731 | if (ret) | 731 | if (ret) |
732 | goto error_free_pcms; | 732 | goto error_free_pcms; |
733 | 733 | ||
734 | ret = snd_soc_init_card(socdev); | ||
735 | if (ret < 0) { | ||
736 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
737 | goto error_free_pcms; | ||
738 | } | ||
739 | |||
740 | return ret; | 734 | return ret; |
741 | 735 | ||
742 | error_free_pcms: | 736 | error_free_pcms: |
@@ -877,21 +871,6 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client) | |||
877 | return 0; | 871 | return 0; |
878 | } | 872 | } |
879 | 873 | ||
880 | #ifdef CONFIG_PM | ||
881 | static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
882 | { | ||
883 | return snd_soc_suspend_device(&client->dev); | ||
884 | } | ||
885 | |||
886 | static int wm8940_i2c_resume(struct i2c_client *client) | ||
887 | { | ||
888 | return snd_soc_resume_device(&client->dev); | ||
889 | } | ||
890 | #else | ||
891 | #define wm8940_i2c_suspend NULL | ||
892 | #define wm8940_i2c_resume NULL | ||
893 | #endif | ||
894 | |||
895 | static const struct i2c_device_id wm8940_i2c_id[] = { | 874 | static const struct i2c_device_id wm8940_i2c_id[] = { |
896 | { "wm8940", 0 }, | 875 | { "wm8940", 0 }, |
897 | { } | 876 | { } |
@@ -905,8 +884,6 @@ static struct i2c_driver wm8940_i2c_driver = { | |||
905 | }, | 884 | }, |
906 | .probe = wm8940_i2c_probe, | 885 | .probe = wm8940_i2c_probe, |
907 | .remove = __devexit_p(wm8940_i2c_remove), | 886 | .remove = __devexit_p(wm8940_i2c_remove), |
908 | .suspend = wm8940_i2c_suspend, | ||
909 | .resume = wm8940_i2c_resume, | ||
910 | .id_table = wm8940_i2c_id, | 887 | .id_table = wm8940_i2c_id, |
911 | }; | 888 | }; |
912 | 889 | ||
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c new file mode 100644 index 000000000000..c8d7a809af4d --- /dev/null +++ b/sound/soc/codecs/wm8955.c | |||
@@ -0,0 +1,1152 @@ | |||
1 | /* | ||
2 | * wm8955.c -- WM8955 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2009 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@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/platform_device.h> | ||
20 | #include <linux/regulator/consumer.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dapm.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/tlv.h> | ||
29 | #include <sound/wm8955.h> | ||
30 | |||
31 | #include "wm8955.h" | ||
32 | |||
33 | static struct snd_soc_codec *wm8955_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
35 | |||
36 | #define WM8955_NUM_SUPPLIES 4 | ||
37 | static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { | ||
38 | "DCVDD", | ||
39 | "DBVDD", | ||
40 | "HPVDD", | ||
41 | "AVDD", | ||
42 | }; | ||
43 | |||
44 | /* codec private data */ | ||
45 | struct wm8955_priv { | ||
46 | struct snd_soc_codec codec; | ||
47 | u16 reg_cache[WM8955_MAX_REGISTER + 1]; | ||
48 | |||
49 | unsigned int mclk_rate; | ||
50 | |||
51 | int deemph; | ||
52 | int fs; | ||
53 | |||
54 | struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; | ||
55 | |||
56 | struct wm8955_pdata *pdata; | ||
57 | }; | ||
58 | |||
59 | static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { | ||
60 | 0x0000, /* R0 */ | ||
61 | 0x0000, /* R1 */ | ||
62 | 0x0079, /* R2 - LOUT1 volume */ | ||
63 | 0x0079, /* R3 - ROUT1 volume */ | ||
64 | 0x0000, /* R4 */ | ||
65 | 0x0008, /* R5 - DAC Control */ | ||
66 | 0x0000, /* R6 */ | ||
67 | 0x000A, /* R7 - Audio Interface */ | ||
68 | 0x0000, /* R8 - Sample Rate */ | ||
69 | 0x0000, /* R9 */ | ||
70 | 0x00FF, /* R10 - Left DAC volume */ | ||
71 | 0x00FF, /* R11 - Right DAC volume */ | ||
72 | 0x000F, /* R12 - Bass control */ | ||
73 | 0x000F, /* R13 - Treble control */ | ||
74 | 0x0000, /* R14 */ | ||
75 | 0x0000, /* R15 - Reset */ | ||
76 | 0x0000, /* R16 */ | ||
77 | 0x0000, /* R17 */ | ||
78 | 0x0000, /* R18 */ | ||
79 | 0x0000, /* R19 */ | ||
80 | 0x0000, /* R20 */ | ||
81 | 0x0000, /* R21 */ | ||
82 | 0x0000, /* R22 */ | ||
83 | 0x00C1, /* R23 - Additional control (1) */ | ||
84 | 0x0000, /* R24 - Additional control (2) */ | ||
85 | 0x0000, /* R25 - Power Management (1) */ | ||
86 | 0x0000, /* R26 - Power Management (2) */ | ||
87 | 0x0000, /* R27 - Additional Control (3) */ | ||
88 | 0x0000, /* R28 */ | ||
89 | 0x0000, /* R29 */ | ||
90 | 0x0000, /* R30 */ | ||
91 | 0x0000, /* R31 */ | ||
92 | 0x0000, /* R32 */ | ||
93 | 0x0000, /* R33 */ | ||
94 | 0x0050, /* R34 - Left out Mix (1) */ | ||
95 | 0x0050, /* R35 - Left out Mix (2) */ | ||
96 | 0x0050, /* R36 - Right out Mix (1) */ | ||
97 | 0x0050, /* R37 - Right Out Mix (2) */ | ||
98 | 0x0050, /* R38 - Mono out Mix (1) */ | ||
99 | 0x0050, /* R39 - Mono out Mix (2) */ | ||
100 | 0x0079, /* R40 - LOUT2 volume */ | ||
101 | 0x0079, /* R41 - ROUT2 volume */ | ||
102 | 0x0079, /* R42 - MONOOUT volume */ | ||
103 | 0x0000, /* R43 - Clocking / PLL */ | ||
104 | 0x0103, /* R44 - PLL Control 1 */ | ||
105 | 0x0024, /* R45 - PLL Control 2 */ | ||
106 | 0x01BA, /* R46 - PLL Control 3 */ | ||
107 | 0x0000, /* R47 */ | ||
108 | 0x0000, /* R48 */ | ||
109 | 0x0000, /* R49 */ | ||
110 | 0x0000, /* R50 */ | ||
111 | 0x0000, /* R51 */ | ||
112 | 0x0000, /* R52 */ | ||
113 | 0x0000, /* R53 */ | ||
114 | 0x0000, /* R54 */ | ||
115 | 0x0000, /* R55 */ | ||
116 | 0x0000, /* R56 */ | ||
117 | 0x0000, /* R57 */ | ||
118 | 0x0000, /* R58 */ | ||
119 | 0x0000, /* R59 - PLL Control 4 */ | ||
120 | }; | ||
121 | |||
122 | static int wm8955_reset(struct snd_soc_codec *codec) | ||
123 | { | ||
124 | return snd_soc_write(codec, WM8955_RESET, 0); | ||
125 | } | ||
126 | |||
127 | struct pll_factors { | ||
128 | int n; | ||
129 | int k; | ||
130 | int outdiv; | ||
131 | }; | ||
132 | |||
133 | /* The size in bits of the FLL divide multiplied by 10 | ||
134 | * to allow rounding later */ | ||
135 | #define FIXED_FLL_SIZE ((1 << 22) * 10) | ||
136 | |||
137 | static int wm8995_pll_factors(struct device *dev, | ||
138 | int Fref, int Fout, struct pll_factors *pll) | ||
139 | { | ||
140 | u64 Kpart; | ||
141 | unsigned int K, Ndiv, Nmod, target; | ||
142 | |||
143 | dev_dbg(dev, "Fref=%u Fout=%u\n", Fref, Fout); | ||
144 | |||
145 | /* The oscilator should run at should be 90-100MHz, and | ||
146 | * there's a divide by 4 plus an optional divide by 2 in the | ||
147 | * output path to generate the system clock. The clock table | ||
148 | * is sortd so we should always generate a suitable target. */ | ||
149 | target = Fout * 4; | ||
150 | if (target < 90000000) { | ||
151 | pll->outdiv = 1; | ||
152 | target *= 2; | ||
153 | } else { | ||
154 | pll->outdiv = 0; | ||
155 | } | ||
156 | |||
157 | WARN_ON(target < 90000000 || target > 100000000); | ||
158 | |||
159 | dev_dbg(dev, "Fvco=%dHz\n", target); | ||
160 | |||
161 | /* Now, calculate N.K */ | ||
162 | Ndiv = target / Fref; | ||
163 | |||
164 | pll->n = Ndiv; | ||
165 | Nmod = target % Fref; | ||
166 | dev_dbg(dev, "Nmod=%d\n", Nmod); | ||
167 | |||
168 | /* Calculate fractional part - scale up so we can round. */ | ||
169 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
170 | |||
171 | do_div(Kpart, Fref); | ||
172 | |||
173 | K = Kpart & 0xFFFFFFFF; | ||
174 | |||
175 | if ((K % 10) >= 5) | ||
176 | K += 5; | ||
177 | |||
178 | /* Move down to proper range now rounding is done */ | ||
179 | pll->k = K / 10; | ||
180 | |||
181 | dev_dbg(dev, "N=%x K=%x OUTDIV=%x\n", pll->n, pll->k, pll->outdiv); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | /* Lookup table specifiying SRATE (table 25 in datasheet); some of the | ||
187 | * output frequencies have been rounded to the standard frequencies | ||
188 | * they are intended to match where the error is slight. */ | ||
189 | static struct { | ||
190 | int mclk; | ||
191 | int fs; | ||
192 | int usb; | ||
193 | int sr; | ||
194 | } clock_cfgs[] = { | ||
195 | { 18432000, 8000, 0, 3, }, | ||
196 | { 18432000, 12000, 0, 9, }, | ||
197 | { 18432000, 16000, 0, 11, }, | ||
198 | { 18432000, 24000, 0, 29, }, | ||
199 | { 18432000, 32000, 0, 13, }, | ||
200 | { 18432000, 48000, 0, 1, }, | ||
201 | { 18432000, 96000, 0, 15, }, | ||
202 | |||
203 | { 16934400, 8018, 0, 19, }, | ||
204 | { 16934400, 11025, 0, 25, }, | ||
205 | { 16934400, 22050, 0, 27, }, | ||
206 | { 16934400, 44100, 0, 17, }, | ||
207 | { 16934400, 88200, 0, 31, }, | ||
208 | |||
209 | { 12000000, 8000, 1, 2, }, | ||
210 | { 12000000, 11025, 1, 25, }, | ||
211 | { 12000000, 12000, 1, 8, }, | ||
212 | { 12000000, 16000, 1, 10, }, | ||
213 | { 12000000, 22050, 1, 27, }, | ||
214 | { 12000000, 24000, 1, 28, }, | ||
215 | { 12000000, 32000, 1, 12, }, | ||
216 | { 12000000, 44100, 1, 17, }, | ||
217 | { 12000000, 48000, 1, 0, }, | ||
218 | { 12000000, 88200, 1, 31, }, | ||
219 | { 12000000, 96000, 1, 14, }, | ||
220 | |||
221 | { 12288000, 8000, 0, 2, }, | ||
222 | { 12288000, 12000, 0, 8, }, | ||
223 | { 12288000, 16000, 0, 10, }, | ||
224 | { 12288000, 24000, 0, 28, }, | ||
225 | { 12288000, 32000, 0, 12, }, | ||
226 | { 12288000, 48000, 0, 0, }, | ||
227 | { 12288000, 96000, 0, 14, }, | ||
228 | |||
229 | { 12289600, 8018, 0, 18, }, | ||
230 | { 12289600, 11025, 0, 24, }, | ||
231 | { 12289600, 22050, 0, 26, }, | ||
232 | { 11289600, 44100, 0, 16, }, | ||
233 | { 11289600, 88200, 0, 31, }, | ||
234 | }; | ||
235 | |||
236 | static int wm8955_configure_clocking(struct snd_soc_codec *codec) | ||
237 | { | ||
238 | struct wm8955_priv *wm8955 = codec->private_data; | ||
239 | int i, ret, val; | ||
240 | int clocking = 0; | ||
241 | int srate = 0; | ||
242 | int sr = -1; | ||
243 | struct pll_factors pll; | ||
244 | |||
245 | /* If we're not running a sample rate currently just pick one */ | ||
246 | if (wm8955->fs == 0) | ||
247 | wm8955->fs = 8000; | ||
248 | |||
249 | /* Can we generate an exact output? */ | ||
250 | for (i = 0; i < ARRAY_SIZE(clock_cfgs); i++) { | ||
251 | if (wm8955->fs != clock_cfgs[i].fs) | ||
252 | continue; | ||
253 | sr = i; | ||
254 | |||
255 | if (wm8955->mclk_rate == clock_cfgs[i].mclk) | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | /* We should never get here with an unsupported sample rate */ | ||
260 | if (sr == -1) { | ||
261 | dev_err(codec->dev, "Sample rate %dHz unsupported\n", | ||
262 | wm8955->fs); | ||
263 | WARN_ON(sr == -1); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | if (i == ARRAY_SIZE(clock_cfgs)) { | ||
268 | /* If we can't generate the right clock from MCLK then | ||
269 | * we should configure the PLL to supply us with an | ||
270 | * appropriate clock. | ||
271 | */ | ||
272 | clocking |= WM8955_MCLKSEL; | ||
273 | |||
274 | /* Use the last divider configuration we saw for the | ||
275 | * sample rate. */ | ||
276 | ret = wm8995_pll_factors(codec->dev, wm8955->mclk_rate, | ||
277 | clock_cfgs[sr].mclk, &pll); | ||
278 | if (ret != 0) { | ||
279 | dev_err(codec->dev, | ||
280 | "Unable to generate %dHz from %dHz MCLK\n", | ||
281 | wm8955->fs, wm8955->mclk_rate); | ||
282 | return -EINVAL; | ||
283 | } | ||
284 | |||
285 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_1, | ||
286 | WM8955_N_MASK | WM8955_K_21_18_MASK, | ||
287 | (pll.n << WM8955_N_SHIFT) | | ||
288 | pll.k >> 18); | ||
289 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, | ||
290 | WM8955_K_17_9_MASK, | ||
291 | (pll.k >> 9) & WM8955_K_17_9_MASK); | ||
292 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, | ||
293 | WM8955_K_8_0_MASK, | ||
294 | pll.k & WM8955_K_8_0_MASK); | ||
295 | if (pll.k) | ||
296 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, | ||
297 | WM8955_KEN, WM8955_KEN); | ||
298 | else | ||
299 | snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, | ||
300 | WM8955_KEN, 0); | ||
301 | |||
302 | if (pll.outdiv) | ||
303 | val = WM8955_PLL_RB | WM8955_PLLOUTDIV2; | ||
304 | else | ||
305 | val = WM8955_PLL_RB; | ||
306 | |||
307 | /* Now start the PLL running */ | ||
308 | snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, | ||
309 | WM8955_PLL_RB | WM8955_PLLOUTDIV2, val); | ||
310 | snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, | ||
311 | WM8955_PLLEN, WM8955_PLLEN); | ||
312 | } | ||
313 | |||
314 | srate = clock_cfgs[sr].usb | (clock_cfgs[sr].sr << WM8955_SR_SHIFT); | ||
315 | |||
316 | snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, | ||
317 | WM8955_USB | WM8955_SR_MASK, srate); | ||
318 | snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, | ||
319 | WM8955_MCLKSEL, clocking); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int wm8955_sysclk(struct snd_soc_dapm_widget *w, | ||
325 | struct snd_kcontrol *kcontrol, int event) | ||
326 | { | ||
327 | struct snd_soc_codec *codec = w->codec; | ||
328 | int ret = 0; | ||
329 | |||
330 | /* Always disable the clocks - if we're doing reconfiguration this | ||
331 | * avoids misclocking. | ||
332 | */ | ||
333 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
334 | WM8955_DIGENB, 0); | ||
335 | snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, | ||
336 | WM8955_PLL_RB | WM8955_PLLEN, 0); | ||
337 | |||
338 | switch (event) { | ||
339 | case SND_SOC_DAPM_POST_PMD: | ||
340 | break; | ||
341 | case SND_SOC_DAPM_PRE_PMU: | ||
342 | ret = wm8955_configure_clocking(codec); | ||
343 | break; | ||
344 | default: | ||
345 | ret = -EINVAL; | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int deemph_settings[] = { 0, 32000, 44100, 48000 }; | ||
353 | |||
354 | static int wm8955_set_deemph(struct snd_soc_codec *codec) | ||
355 | { | ||
356 | struct wm8955_priv *wm8955 = codec->private_data; | ||
357 | int val, i, best; | ||
358 | |||
359 | /* If we're using deemphasis select the nearest available sample | ||
360 | * rate. | ||
361 | */ | ||
362 | if (wm8955->deemph) { | ||
363 | best = 1; | ||
364 | for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { | ||
365 | if (abs(deemph_settings[i] - wm8955->fs) < | ||
366 | abs(deemph_settings[best] - wm8955->fs)) | ||
367 | best = i; | ||
368 | } | ||
369 | |||
370 | val = best << WM8955_DEEMPH_SHIFT; | ||
371 | } else { | ||
372 | val = 0; | ||
373 | } | ||
374 | |||
375 | dev_dbg(codec->dev, "Set deemphasis %d\n", val); | ||
376 | |||
377 | return snd_soc_update_bits(codec, WM8955_DAC_CONTROL, | ||
378 | WM8955_DEEMPH_MASK, val); | ||
379 | } | ||
380 | |||
381 | static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, | ||
382 | struct snd_ctl_elem_value *ucontrol) | ||
383 | { | ||
384 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
385 | struct wm8955_priv *wm8955 = codec->private_data; | ||
386 | |||
387 | return wm8955->deemph; | ||
388 | } | ||
389 | |||
390 | static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, | ||
391 | struct snd_ctl_elem_value *ucontrol) | ||
392 | { | ||
393 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
394 | struct wm8955_priv *wm8955 = codec->private_data; | ||
395 | int deemph = ucontrol->value.enumerated.item[0]; | ||
396 | |||
397 | if (deemph > 1) | ||
398 | return -EINVAL; | ||
399 | |||
400 | wm8955->deemph = deemph; | ||
401 | |||
402 | return wm8955_set_deemph(codec); | ||
403 | } | ||
404 | |||
405 | static const char *bass_mode_text[] = { | ||
406 | "Linear", "Adaptive", | ||
407 | }; | ||
408 | |||
409 | static const struct soc_enum bass_mode = | ||
410 | SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); | ||
411 | |||
412 | static const char *bass_cutoff_text[] = { | ||
413 | "Low", "High" | ||
414 | }; | ||
415 | |||
416 | static const struct soc_enum bass_cutoff = | ||
417 | SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); | ||
418 | |||
419 | static const char *treble_cutoff_text[] = { | ||
420 | "High", "Low" | ||
421 | }; | ||
422 | |||
423 | static const struct soc_enum treble_cutoff = | ||
424 | SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); | ||
425 | |||
426 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | ||
427 | static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); | ||
428 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | ||
429 | static const DECLARE_TLV_DB_SCALE(mono_tlv, -2100, 300, 0); | ||
430 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | ||
431 | static const DECLARE_TLV_DB_SCALE(treble_tlv, -1200, 150, 1); | ||
432 | |||
433 | static const struct snd_kcontrol_new wm8955_snd_controls[] = { | ||
434 | SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8955_LEFT_DAC_VOLUME, | ||
435 | WM8955_RIGHT_DAC_VOLUME, 0, 255, 0, digital_tlv), | ||
436 | SOC_SINGLE_TLV("Playback Attenuation Volume", WM8955_DAC_CONTROL, 7, 1, 1, | ||
437 | atten_tlv), | ||
438 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, | ||
439 | wm8955_get_deemph, wm8955_put_deemph), | ||
440 | |||
441 | SOC_ENUM("Bass Mode", bass_mode), | ||
442 | SOC_ENUM("Bass Cutoff", bass_cutoff), | ||
443 | SOC_SINGLE("Bass Volume", WM8955_BASS_CONTROL, 0, 15, 1), | ||
444 | |||
445 | SOC_ENUM("Treble Cutoff", treble_cutoff), | ||
446 | SOC_SINGLE_TLV("Treble Volume", WM8955_TREBLE_CONTROL, 0, 14, 1, treble_tlv), | ||
447 | |||
448 | SOC_SINGLE_TLV("Left Bypass Volume", WM8955_LEFT_OUT_MIX_1, 4, 7, 1, | ||
449 | bypass_tlv), | ||
450 | SOC_SINGLE_TLV("Left Mono Volume", WM8955_LEFT_OUT_MIX_2, 4, 7, 1, | ||
451 | bypass_tlv), | ||
452 | |||
453 | SOC_SINGLE_TLV("Right Mono Volume", WM8955_RIGHT_OUT_MIX_1, 4, 7, 1, | ||
454 | bypass_tlv), | ||
455 | SOC_SINGLE_TLV("Right Bypass Volume", WM8955_RIGHT_OUT_MIX_2, 4, 7, 1, | ||
456 | bypass_tlv), | ||
457 | |||
458 | /* Not a stereo pair so they line up with the DAPM switches */ | ||
459 | SOC_SINGLE_TLV("Mono Left Bypass Volume", WM8955_MONO_OUT_MIX_1, 4, 7, 1, | ||
460 | mono_tlv), | ||
461 | SOC_SINGLE_TLV("Mono Right Bypass Volume", WM8955_MONO_OUT_MIX_2, 4, 7, 1, | ||
462 | mono_tlv), | ||
463 | |||
464 | SOC_DOUBLE_R_TLV("Headphone Volume", WM8955_LOUT1_VOLUME, | ||
465 | WM8955_ROUT1_VOLUME, 0, 127, 0, out_tlv), | ||
466 | SOC_DOUBLE_R("Headphone ZC Switch", WM8955_LOUT1_VOLUME, | ||
467 | WM8955_ROUT1_VOLUME, 7, 1, 0), | ||
468 | |||
469 | SOC_DOUBLE_R_TLV("Speaker Volume", WM8955_LOUT2_VOLUME, | ||
470 | WM8955_ROUT2_VOLUME, 0, 127, 0, out_tlv), | ||
471 | SOC_DOUBLE_R("Speaker ZC Switch", WM8955_LOUT2_VOLUME, | ||
472 | WM8955_ROUT2_VOLUME, 7, 1, 0), | ||
473 | |||
474 | SOC_SINGLE_TLV("Mono Volume", WM8955_MONOOUT_VOLUME, 0, 127, 0, out_tlv), | ||
475 | SOC_SINGLE("Mono ZC Switch", WM8955_MONOOUT_VOLUME, 7, 1, 0), | ||
476 | }; | ||
477 | |||
478 | static const struct snd_kcontrol_new lmixer[] = { | ||
479 | SOC_DAPM_SINGLE("Playback Switch", WM8955_LEFT_OUT_MIX_1, 8, 1, 0), | ||
480 | SOC_DAPM_SINGLE("Bypass Switch", WM8955_LEFT_OUT_MIX_1, 7, 1, 0), | ||
481 | SOC_DAPM_SINGLE("Right Playback Switch", WM8955_LEFT_OUT_MIX_2, 8, 1, 0), | ||
482 | SOC_DAPM_SINGLE("Mono Switch", WM8955_LEFT_OUT_MIX_2, 7, 1, 0), | ||
483 | }; | ||
484 | |||
485 | static const struct snd_kcontrol_new rmixer[] = { | ||
486 | SOC_DAPM_SINGLE("Left Playback Switch", WM8955_RIGHT_OUT_MIX_1, 8, 1, 0), | ||
487 | SOC_DAPM_SINGLE("Mono Switch", WM8955_RIGHT_OUT_MIX_1, 7, 1, 0), | ||
488 | SOC_DAPM_SINGLE("Playback Switch", WM8955_RIGHT_OUT_MIX_2, 8, 1, 0), | ||
489 | SOC_DAPM_SINGLE("Bypass Switch", WM8955_RIGHT_OUT_MIX_2, 7, 1, 0), | ||
490 | }; | ||
491 | |||
492 | static const struct snd_kcontrol_new mmixer[] = { | ||
493 | SOC_DAPM_SINGLE("Left Playback Switch", WM8955_MONO_OUT_MIX_1, 8, 1, 0), | ||
494 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8955_MONO_OUT_MIX_1, 7, 1, 0), | ||
495 | SOC_DAPM_SINGLE("Right Playback Switch", WM8955_MONO_OUT_MIX_2, 8, 1, 0), | ||
496 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8955_MONO_OUT_MIX_2, 7, 1, 0), | ||
497 | }; | ||
498 | |||
499 | static const struct snd_soc_dapm_widget wm8955_dapm_widgets[] = { | ||
500 | SND_SOC_DAPM_INPUT("MONOIN-"), | ||
501 | SND_SOC_DAPM_INPUT("MONOIN+"), | ||
502 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
503 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
504 | |||
505 | SND_SOC_DAPM_PGA("Mono Input", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
506 | |||
507 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM8955_POWER_MANAGEMENT_1, 0, 1, wm8955_sysclk, | ||
508 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
509 | SND_SOC_DAPM_SUPPLY("TSDEN", WM8955_ADDITIONAL_CONTROL_1, 8, 0, NULL, 0), | ||
510 | |||
511 | SND_SOC_DAPM_DAC("DACL", "Playback", WM8955_POWER_MANAGEMENT_2, 8, 0), | ||
512 | SND_SOC_DAPM_DAC("DACR", "Playback", WM8955_POWER_MANAGEMENT_2, 7, 0), | ||
513 | |||
514 | SND_SOC_DAPM_PGA("LOUT1 PGA", WM8955_POWER_MANAGEMENT_2, 6, 0, NULL, 0), | ||
515 | SND_SOC_DAPM_PGA("ROUT1 PGA", WM8955_POWER_MANAGEMENT_2, 5, 0, NULL, 0), | ||
516 | SND_SOC_DAPM_PGA("LOUT2 PGA", WM8955_POWER_MANAGEMENT_2, 4, 0, NULL, 0), | ||
517 | SND_SOC_DAPM_PGA("ROUT2 PGA", WM8955_POWER_MANAGEMENT_2, 3, 0, NULL, 0), | ||
518 | SND_SOC_DAPM_PGA("MOUT PGA", WM8955_POWER_MANAGEMENT_2, 2, 0, NULL, 0), | ||
519 | SND_SOC_DAPM_PGA("OUT3 PGA", WM8955_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | ||
520 | |||
521 | /* The names are chosen to make the control names nice */ | ||
522 | SND_SOC_DAPM_MIXER("Left", SND_SOC_NOPM, 0, 0, | ||
523 | lmixer, ARRAY_SIZE(lmixer)), | ||
524 | SND_SOC_DAPM_MIXER("Right", SND_SOC_NOPM, 0, 0, | ||
525 | rmixer, ARRAY_SIZE(rmixer)), | ||
526 | SND_SOC_DAPM_MIXER("Mono", SND_SOC_NOPM, 0, 0, | ||
527 | mmixer, ARRAY_SIZE(mmixer)), | ||
528 | |||
529 | SND_SOC_DAPM_OUTPUT("LOUT1"), | ||
530 | SND_SOC_DAPM_OUTPUT("ROUT1"), | ||
531 | SND_SOC_DAPM_OUTPUT("LOUT2"), | ||
532 | SND_SOC_DAPM_OUTPUT("ROUT2"), | ||
533 | SND_SOC_DAPM_OUTPUT("MONOOUT"), | ||
534 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
535 | }; | ||
536 | |||
537 | static const struct snd_soc_dapm_route wm8955_intercon[] = { | ||
538 | { "DACL", NULL, "SYSCLK" }, | ||
539 | { "DACR", NULL, "SYSCLK" }, | ||
540 | |||
541 | { "Mono Input", NULL, "MONOIN-" }, | ||
542 | { "Mono Input", NULL, "MONOIN+" }, | ||
543 | |||
544 | { "Left", "Playback Switch", "DACL" }, | ||
545 | { "Left", "Right Playback Switch", "DACR" }, | ||
546 | { "Left", "Bypass Switch", "LINEINL" }, | ||
547 | { "Left", "Mono Switch", "Mono Input" }, | ||
548 | |||
549 | { "Right", "Playback Switch", "DACR" }, | ||
550 | { "Right", "Left Playback Switch", "DACL" }, | ||
551 | { "Right", "Bypass Switch", "LINEINR" }, | ||
552 | { "Right", "Mono Switch", "Mono Input" }, | ||
553 | |||
554 | { "Mono", "Left Playback Switch", "DACL" }, | ||
555 | { "Mono", "Right Playback Switch", "DACR" }, | ||
556 | { "Mono", "Left Bypass Switch", "LINEINL" }, | ||
557 | { "Mono", "Right Bypass Switch", "LINEINR" }, | ||
558 | |||
559 | { "LOUT1 PGA", NULL, "Left" }, | ||
560 | { "LOUT1", NULL, "TSDEN" }, | ||
561 | { "LOUT1", NULL, "LOUT1 PGA" }, | ||
562 | |||
563 | { "ROUT1 PGA", NULL, "Right" }, | ||
564 | { "ROUT1", NULL, "TSDEN" }, | ||
565 | { "ROUT1", NULL, "ROUT1 PGA" }, | ||
566 | |||
567 | { "LOUT2 PGA", NULL, "Left" }, | ||
568 | { "LOUT2", NULL, "TSDEN" }, | ||
569 | { "LOUT2", NULL, "LOUT2 PGA" }, | ||
570 | |||
571 | { "ROUT2 PGA", NULL, "Right" }, | ||
572 | { "ROUT2", NULL, "TSDEN" }, | ||
573 | { "ROUT2", NULL, "ROUT2 PGA" }, | ||
574 | |||
575 | { "MOUT PGA", NULL, "Mono" }, | ||
576 | { "MONOOUT", NULL, "MOUT PGA" }, | ||
577 | |||
578 | /* OUT3 not currently implemented */ | ||
579 | { "OUT3", NULL, "OUT3 PGA" }, | ||
580 | }; | ||
581 | |||
582 | static int wm8955_add_widgets(struct snd_soc_codec *codec) | ||
583 | { | ||
584 | snd_soc_add_controls(codec, wm8955_snd_controls, | ||
585 | ARRAY_SIZE(wm8955_snd_controls)); | ||
586 | |||
587 | snd_soc_dapm_new_controls(codec, wm8955_dapm_widgets, | ||
588 | ARRAY_SIZE(wm8955_dapm_widgets)); | ||
589 | |||
590 | snd_soc_dapm_add_routes(codec, wm8955_intercon, | ||
591 | ARRAY_SIZE(wm8955_intercon)); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int wm8955_hw_params(struct snd_pcm_substream *substream, | ||
597 | struct snd_pcm_hw_params *params, | ||
598 | struct snd_soc_dai *dai) | ||
599 | { | ||
600 | struct snd_soc_codec *codec = dai->codec; | ||
601 | struct wm8955_priv *wm8955 = codec->private_data; | ||
602 | int ret; | ||
603 | int wl; | ||
604 | |||
605 | switch (params_format(params)) { | ||
606 | case SNDRV_PCM_FORMAT_S16_LE: | ||
607 | wl = 0; | ||
608 | break; | ||
609 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
610 | wl = 0x4; | ||
611 | break; | ||
612 | case SNDRV_PCM_FORMAT_S24_LE: | ||
613 | wl = 0x8; | ||
614 | break; | ||
615 | case SNDRV_PCM_FORMAT_S32_LE: | ||
616 | wl = 0xc; | ||
617 | break; | ||
618 | default: | ||
619 | return -EINVAL; | ||
620 | } | ||
621 | snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, | ||
622 | WM8955_WL_MASK, wl); | ||
623 | |||
624 | wm8955->fs = params_rate(params); | ||
625 | wm8955_set_deemph(codec); | ||
626 | |||
627 | /* If the chip is clocked then disable the clocks and force a | ||
628 | * reconfiguration, otherwise DAPM will power up the | ||
629 | * clocks for us later. */ | ||
630 | ret = snd_soc_read(codec, WM8955_POWER_MANAGEMENT_1); | ||
631 | if (ret < 0) | ||
632 | return ret; | ||
633 | if (ret & WM8955_DIGENB) { | ||
634 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
635 | WM8955_DIGENB, 0); | ||
636 | snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, | ||
637 | WM8955_PLL_RB | WM8955_PLLEN, 0); | ||
638 | |||
639 | wm8955_configure_clocking(codec); | ||
640 | } | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | |||
646 | static int wm8955_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
647 | unsigned int freq, int dir) | ||
648 | { | ||
649 | struct snd_soc_codec *codec = dai->codec; | ||
650 | struct wm8955_priv *priv = codec->private_data; | ||
651 | int div; | ||
652 | |||
653 | switch (clk_id) { | ||
654 | case WM8955_CLK_MCLK: | ||
655 | if (freq > 15000000) { | ||
656 | priv->mclk_rate = freq /= 2; | ||
657 | div = WM8955_MCLKDIV2; | ||
658 | } else { | ||
659 | priv->mclk_rate = freq; | ||
660 | div = 0; | ||
661 | } | ||
662 | |||
663 | snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, | ||
664 | WM8955_MCLKDIV2, div); | ||
665 | break; | ||
666 | |||
667 | default: | ||
668 | return -EINVAL; | ||
669 | } | ||
670 | |||
671 | dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
677 | { | ||
678 | struct snd_soc_codec *codec = dai->codec; | ||
679 | u16 aif = 0; | ||
680 | |||
681 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
682 | case SND_SOC_DAIFMT_CBS_CFS: | ||
683 | break; | ||
684 | case SND_SOC_DAIFMT_CBM_CFM: | ||
685 | aif |= WM8955_MS; | ||
686 | break; | ||
687 | default: | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
692 | case SND_SOC_DAIFMT_DSP_B: | ||
693 | aif |= WM8955_LRP; | ||
694 | case SND_SOC_DAIFMT_DSP_A: | ||
695 | aif |= 0x3; | ||
696 | break; | ||
697 | case SND_SOC_DAIFMT_I2S: | ||
698 | aif |= 0x2; | ||
699 | break; | ||
700 | case SND_SOC_DAIFMT_RIGHT_J: | ||
701 | break; | ||
702 | case SND_SOC_DAIFMT_LEFT_J: | ||
703 | aif |= 0x1; | ||
704 | break; | ||
705 | default: | ||
706 | return -EINVAL; | ||
707 | } | ||
708 | |||
709 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
710 | case SND_SOC_DAIFMT_DSP_A: | ||
711 | case SND_SOC_DAIFMT_DSP_B: | ||
712 | /* frame inversion not valid for DSP modes */ | ||
713 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
714 | case SND_SOC_DAIFMT_NB_NF: | ||
715 | break; | ||
716 | case SND_SOC_DAIFMT_IB_NF: | ||
717 | aif |= WM8955_BCLKINV; | ||
718 | break; | ||
719 | default: | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | break; | ||
723 | |||
724 | case SND_SOC_DAIFMT_I2S: | ||
725 | case SND_SOC_DAIFMT_RIGHT_J: | ||
726 | case SND_SOC_DAIFMT_LEFT_J: | ||
727 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
728 | case SND_SOC_DAIFMT_NB_NF: | ||
729 | break; | ||
730 | case SND_SOC_DAIFMT_IB_IF: | ||
731 | aif |= WM8955_BCLKINV | WM8955_LRP; | ||
732 | break; | ||
733 | case SND_SOC_DAIFMT_IB_NF: | ||
734 | aif |= WM8955_BCLKINV; | ||
735 | break; | ||
736 | case SND_SOC_DAIFMT_NB_IF: | ||
737 | aif |= WM8955_LRP; | ||
738 | break; | ||
739 | default: | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | break; | ||
743 | default: | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, | ||
748 | WM8955_MS | WM8955_FORMAT_MASK | WM8955_BCLKINV | | ||
749 | WM8955_LRP, aif); | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | |||
755 | static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute) | ||
756 | { | ||
757 | struct snd_soc_codec *codec = codec_dai->codec; | ||
758 | int val; | ||
759 | |||
760 | if (mute) | ||
761 | val = WM8955_DACMU; | ||
762 | else | ||
763 | val = 0; | ||
764 | |||
765 | snd_soc_update_bits(codec, WM8955_DAC_CONTROL, WM8955_DACMU, val); | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static int wm8955_set_bias_level(struct snd_soc_codec *codec, | ||
771 | enum snd_soc_bias_level level) | ||
772 | { | ||
773 | struct wm8955_priv *wm8955 = codec->private_data; | ||
774 | int ret, i; | ||
775 | |||
776 | switch (level) { | ||
777 | case SND_SOC_BIAS_ON: | ||
778 | break; | ||
779 | |||
780 | case SND_SOC_BIAS_PREPARE: | ||
781 | /* VMID resistance 2*50k */ | ||
782 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
783 | WM8955_VMIDSEL_MASK, | ||
784 | 0x1 << WM8955_VMIDSEL_SHIFT); | ||
785 | |||
786 | /* Default bias current */ | ||
787 | snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, | ||
788 | WM8955_VSEL_MASK, | ||
789 | 0x2 << WM8955_VSEL_SHIFT); | ||
790 | break; | ||
791 | |||
792 | case SND_SOC_BIAS_STANDBY: | ||
793 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
794 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), | ||
795 | wm8955->supplies); | ||
796 | if (ret != 0) { | ||
797 | dev_err(codec->dev, | ||
798 | "Failed to enable supplies: %d\n", | ||
799 | ret); | ||
800 | return ret; | ||
801 | } | ||
802 | |||
803 | /* Sync back cached values if they're | ||
804 | * different from the hardware default. | ||
805 | */ | ||
806 | for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { | ||
807 | if (i == WM8955_RESET) | ||
808 | continue; | ||
809 | |||
810 | if (wm8955->reg_cache[i] == wm8955_reg[i]) | ||
811 | continue; | ||
812 | |||
813 | snd_soc_write(codec, i, wm8955->reg_cache[i]); | ||
814 | } | ||
815 | |||
816 | /* Enable VREF and VMID */ | ||
817 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
818 | WM8955_VREF | | ||
819 | WM8955_VMIDSEL_MASK, | ||
820 | WM8955_VREF | | ||
821 | 0x3 << WM8955_VREF_SHIFT); | ||
822 | |||
823 | /* Let VMID ramp */ | ||
824 | msleep(500); | ||
825 | |||
826 | /* High resistance VROI to maintain outputs */ | ||
827 | snd_soc_update_bits(codec, | ||
828 | WM8955_ADDITIONAL_CONTROL_3, | ||
829 | WM8955_VROI, WM8955_VROI); | ||
830 | } | ||
831 | |||
832 | /* Maintain VMID with 2*250k */ | ||
833 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
834 | WM8955_VMIDSEL_MASK, | ||
835 | 0x2 << WM8955_VMIDSEL_SHIFT); | ||
836 | |||
837 | /* Minimum bias current */ | ||
838 | snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, | ||
839 | WM8955_VSEL_MASK, 0); | ||
840 | break; | ||
841 | |||
842 | case SND_SOC_BIAS_OFF: | ||
843 | /* Low resistance VROI to help discharge */ | ||
844 | snd_soc_update_bits(codec, | ||
845 | WM8955_ADDITIONAL_CONTROL_3, | ||
846 | WM8955_VROI, 0); | ||
847 | |||
848 | /* Turn off VMID and VREF */ | ||
849 | snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, | ||
850 | WM8955_VREF | | ||
851 | WM8955_VMIDSEL_MASK, 0); | ||
852 | |||
853 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), | ||
854 | wm8955->supplies); | ||
855 | break; | ||
856 | } | ||
857 | codec->bias_level = level; | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | #define WM8955_RATES SNDRV_PCM_RATE_8000_96000 | ||
862 | |||
863 | #define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
864 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
865 | |||
866 | static struct snd_soc_dai_ops wm8955_dai_ops = { | ||
867 | .set_sysclk = wm8955_set_sysclk, | ||
868 | .set_fmt = wm8955_set_fmt, | ||
869 | .hw_params = wm8955_hw_params, | ||
870 | .digital_mute = wm8955_digital_mute, | ||
871 | }; | ||
872 | |||
873 | struct snd_soc_dai wm8955_dai = { | ||
874 | .name = "WM8955", | ||
875 | .playback = { | ||
876 | .stream_name = "Playback", | ||
877 | .channels_min = 2, | ||
878 | .channels_max = 2, | ||
879 | .rates = WM8955_RATES, | ||
880 | .formats = WM8955_FORMATS, | ||
881 | }, | ||
882 | .ops = &wm8955_dai_ops, | ||
883 | }; | ||
884 | EXPORT_SYMBOL_GPL(wm8955_dai); | ||
885 | |||
886 | #ifdef CONFIG_PM | ||
887 | static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) | ||
888 | { | ||
889 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
890 | struct snd_soc_codec *codec = socdev->card->codec; | ||
891 | |||
892 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int wm8955_resume(struct platform_device *pdev) | ||
898 | { | ||
899 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
900 | struct snd_soc_codec *codec = socdev->card->codec; | ||
901 | |||
902 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
903 | |||
904 | return 0; | ||
905 | } | ||
906 | #else | ||
907 | #define wm8955_suspend NULL | ||
908 | #define wm8955_resume NULL | ||
909 | #endif | ||
910 | |||
911 | static int wm8955_probe(struct platform_device *pdev) | ||
912 | { | ||
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec; | ||
915 | int ret = 0; | ||
916 | |||
917 | if (wm8955_codec == NULL) { | ||
918 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | |||
922 | socdev->card->codec = wm8955_codec; | ||
923 | codec = wm8955_codec; | ||
924 | |||
925 | /* register pcms */ | ||
926 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
927 | if (ret < 0) { | ||
928 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
929 | goto pcm_err; | ||
930 | } | ||
931 | |||
932 | wm8955_add_widgets(codec); | ||
933 | |||
934 | return ret; | ||
935 | |||
936 | pcm_err: | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int wm8955_remove(struct platform_device *pdev) | ||
941 | { | ||
942 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
943 | |||
944 | snd_soc_free_pcms(socdev); | ||
945 | snd_soc_dapm_free(socdev); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | struct snd_soc_codec_device soc_codec_dev_wm8955 = { | ||
951 | .probe = wm8955_probe, | ||
952 | .remove = wm8955_remove, | ||
953 | .suspend = wm8955_suspend, | ||
954 | .resume = wm8955_resume, | ||
955 | }; | ||
956 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955); | ||
957 | |||
958 | static int wm8955_register(struct wm8955_priv *wm8955, | ||
959 | enum snd_soc_control_type control) | ||
960 | { | ||
961 | int ret; | ||
962 | struct snd_soc_codec *codec = &wm8955->codec; | ||
963 | int i; | ||
964 | |||
965 | if (wm8955_codec) { | ||
966 | dev_err(codec->dev, "Another WM8955 is registered\n"); | ||
967 | return -EINVAL; | ||
968 | } | ||
969 | |||
970 | mutex_init(&codec->mutex); | ||
971 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
972 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
973 | |||
974 | codec->private_data = wm8955; | ||
975 | codec->name = "WM8955"; | ||
976 | codec->owner = THIS_MODULE; | ||
977 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
978 | codec->set_bias_level = wm8955_set_bias_level; | ||
979 | codec->dai = &wm8955_dai; | ||
980 | codec->num_dai = 1; | ||
981 | codec->reg_cache_size = WM8955_MAX_REGISTER; | ||
982 | codec->reg_cache = &wm8955->reg_cache; | ||
983 | |||
984 | memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg)); | ||
985 | |||
986 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
987 | if (ret != 0) { | ||
988 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
989 | goto err; | ||
990 | } | ||
991 | |||
992 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) | ||
993 | wm8955->supplies[i].supply = wm8955_supply_names[i]; | ||
994 | |||
995 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies), | ||
996 | wm8955->supplies); | ||
997 | if (ret != 0) { | ||
998 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
999 | goto err; | ||
1000 | } | ||
1001 | |||
1002 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), | ||
1003 | wm8955->supplies); | ||
1004 | if (ret != 0) { | ||
1005 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1006 | goto err_get; | ||
1007 | } | ||
1008 | |||
1009 | ret = wm8955_reset(codec); | ||
1010 | if (ret < 0) { | ||
1011 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
1012 | goto err_enable; | ||
1013 | } | ||
1014 | |||
1015 | wm8955_dai.dev = codec->dev; | ||
1016 | |||
1017 | /* Change some default settings - latch VU and enable ZC */ | ||
1018 | wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; | ||
1019 | wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; | ||
1020 | wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; | ||
1021 | wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; | ||
1022 | wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; | ||
1023 | wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; | ||
1024 | wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; | ||
1025 | |||
1026 | /* Also enable adaptive bass boost by default */ | ||
1027 | wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; | ||
1028 | |||
1029 | /* Set platform data values */ | ||
1030 | if (wm8955->pdata) { | ||
1031 | if (wm8955->pdata->out2_speaker) | ||
1032 | wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] | ||
1033 | |= WM8955_ROUT2INV; | ||
1034 | |||
1035 | if (wm8955->pdata->monoin_diff) | ||
1036 | wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] | ||
1037 | |= WM8955_DMEN; | ||
1038 | } | ||
1039 | |||
1040 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1041 | |||
1042 | /* Bias level configuration will have done an extra enable */ | ||
1043 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | ||
1044 | |||
1045 | wm8955_codec = codec; | ||
1046 | |||
1047 | ret = snd_soc_register_codec(codec); | ||
1048 | if (ret != 0) { | ||
1049 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1050 | return ret; | ||
1051 | } | ||
1052 | |||
1053 | ret = snd_soc_register_dai(&wm8955_dai); | ||
1054 | if (ret != 0) { | ||
1055 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1056 | snd_soc_unregister_codec(codec); | ||
1057 | return ret; | ||
1058 | } | ||
1059 | |||
1060 | return 0; | ||
1061 | |||
1062 | err_enable: | ||
1063 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | ||
1064 | err_get: | ||
1065 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | ||
1066 | err: | ||
1067 | kfree(wm8955); | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | static void wm8955_unregister(struct wm8955_priv *wm8955) | ||
1072 | { | ||
1073 | wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); | ||
1074 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | ||
1075 | snd_soc_unregister_dai(&wm8955_dai); | ||
1076 | snd_soc_unregister_codec(&wm8955->codec); | ||
1077 | kfree(wm8955); | ||
1078 | wm8955_codec = NULL; | ||
1079 | } | ||
1080 | |||
1081 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1082 | static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, | ||
1083 | const struct i2c_device_id *id) | ||
1084 | { | ||
1085 | struct wm8955_priv *wm8955; | ||
1086 | struct snd_soc_codec *codec; | ||
1087 | |||
1088 | wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); | ||
1089 | if (wm8955 == NULL) | ||
1090 | return -ENOMEM; | ||
1091 | |||
1092 | codec = &wm8955->codec; | ||
1093 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1094 | |||
1095 | i2c_set_clientdata(i2c, wm8955); | ||
1096 | codec->control_data = i2c; | ||
1097 | wm8955->pdata = i2c->dev.platform_data; | ||
1098 | |||
1099 | codec->dev = &i2c->dev; | ||
1100 | |||
1101 | return wm8955_register(wm8955, SND_SOC_I2C); | ||
1102 | } | ||
1103 | |||
1104 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) | ||
1105 | { | ||
1106 | struct wm8955_priv *wm8955 = i2c_get_clientdata(client); | ||
1107 | wm8955_unregister(wm8955); | ||
1108 | return 0; | ||
1109 | } | ||
1110 | |||
1111 | static const struct i2c_device_id wm8955_i2c_id[] = { | ||
1112 | { "wm8955", 0 }, | ||
1113 | { } | ||
1114 | }; | ||
1115 | MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); | ||
1116 | |||
1117 | static struct i2c_driver wm8955_i2c_driver = { | ||
1118 | .driver = { | ||
1119 | .name = "wm8955", | ||
1120 | .owner = THIS_MODULE, | ||
1121 | }, | ||
1122 | .probe = wm8955_i2c_probe, | ||
1123 | .remove = __devexit_p(wm8955_i2c_remove), | ||
1124 | .id_table = wm8955_i2c_id, | ||
1125 | }; | ||
1126 | #endif | ||
1127 | |||
1128 | static int __init wm8955_modinit(void) | ||
1129 | { | ||
1130 | int ret; | ||
1131 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1132 | ret = i2c_add_driver(&wm8955_i2c_driver); | ||
1133 | if (ret != 0) { | ||
1134 | printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", | ||
1135 | ret); | ||
1136 | } | ||
1137 | #endif | ||
1138 | return 0; | ||
1139 | } | ||
1140 | module_init(wm8955_modinit); | ||
1141 | |||
1142 | static void __exit wm8955_exit(void) | ||
1143 | { | ||
1144 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1145 | i2c_del_driver(&wm8955_i2c_driver); | ||
1146 | #endif | ||
1147 | } | ||
1148 | module_exit(wm8955_exit); | ||
1149 | |||
1150 | MODULE_DESCRIPTION("ASoC WM8955 driver"); | ||
1151 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
1152 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h new file mode 100644 index 000000000000..ae349c8531f6 --- /dev/null +++ b/sound/soc/codecs/wm8955.h | |||
@@ -0,0 +1,489 @@ | |||
1 | /* | ||
2 | * wm8955.h -- WM8904 ASoC driver | ||
3 | * | ||
4 | * Copyright 2009 Wolfson Microelectronics, plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@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 _WM8955_H | ||
14 | #define _WM8955_H | ||
15 | |||
16 | #define WM8955_CLK_MCLK 1 | ||
17 | |||
18 | extern struct snd_soc_dai wm8955_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
20 | |||
21 | /* | ||
22 | * Register values. | ||
23 | */ | ||
24 | #define WM8955_LOUT1_VOLUME 0x02 | ||
25 | #define WM8955_ROUT1_VOLUME 0x03 | ||
26 | #define WM8955_DAC_CONTROL 0x05 | ||
27 | #define WM8955_AUDIO_INTERFACE 0x07 | ||
28 | #define WM8955_SAMPLE_RATE 0x08 | ||
29 | #define WM8955_LEFT_DAC_VOLUME 0x0A | ||
30 | #define WM8955_RIGHT_DAC_VOLUME 0x0B | ||
31 | #define WM8955_BASS_CONTROL 0x0C | ||
32 | #define WM8955_TREBLE_CONTROL 0x0D | ||
33 | #define WM8955_RESET 0x0F | ||
34 | #define WM8955_ADDITIONAL_CONTROL_1 0x17 | ||
35 | #define WM8955_ADDITIONAL_CONTROL_2 0x18 | ||
36 | #define WM8955_POWER_MANAGEMENT_1 0x19 | ||
37 | #define WM8955_POWER_MANAGEMENT_2 0x1A | ||
38 | #define WM8955_ADDITIONAL_CONTROL_3 0x1B | ||
39 | #define WM8955_LEFT_OUT_MIX_1 0x22 | ||
40 | #define WM8955_LEFT_OUT_MIX_2 0x23 | ||
41 | #define WM8955_RIGHT_OUT_MIX_1 0x24 | ||
42 | #define WM8955_RIGHT_OUT_MIX_2 0x25 | ||
43 | #define WM8955_MONO_OUT_MIX_1 0x26 | ||
44 | #define WM8955_MONO_OUT_MIX_2 0x27 | ||
45 | #define WM8955_LOUT2_VOLUME 0x28 | ||
46 | #define WM8955_ROUT2_VOLUME 0x29 | ||
47 | #define WM8955_MONOOUT_VOLUME 0x2A | ||
48 | #define WM8955_CLOCKING_PLL 0x2B | ||
49 | #define WM8955_PLL_CONTROL_1 0x2C | ||
50 | #define WM8955_PLL_CONTROL_2 0x2D | ||
51 | #define WM8955_PLL_CONTROL_3 0x2E | ||
52 | #define WM8955_PLL_CONTROL_4 0x3B | ||
53 | |||
54 | #define WM8955_REGISTER_COUNT 29 | ||
55 | #define WM8955_MAX_REGISTER 0x3B | ||
56 | |||
57 | /* | ||
58 | * Field Definitions. | ||
59 | */ | ||
60 | |||
61 | /* | ||
62 | * R2 (0x02) - LOUT1 volume | ||
63 | */ | ||
64 | #define WM8955_LO1VU 0x0100 /* LO1VU */ | ||
65 | #define WM8955_LO1VU_MASK 0x0100 /* LO1VU */ | ||
66 | #define WM8955_LO1VU_SHIFT 8 /* LO1VU */ | ||
67 | #define WM8955_LO1VU_WIDTH 1 /* LO1VU */ | ||
68 | #define WM8955_LO1ZC 0x0080 /* LO1ZC */ | ||
69 | #define WM8955_LO1ZC_MASK 0x0080 /* LO1ZC */ | ||
70 | #define WM8955_LO1ZC_SHIFT 7 /* LO1ZC */ | ||
71 | #define WM8955_LO1ZC_WIDTH 1 /* LO1ZC */ | ||
72 | #define WM8955_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */ | ||
73 | #define WM8955_LOUTVOL_SHIFT 0 /* LOUTVOL - [6:0] */ | ||
74 | #define WM8955_LOUTVOL_WIDTH 7 /* LOUTVOL - [6:0] */ | ||
75 | |||
76 | /* | ||
77 | * R3 (0x03) - ROUT1 volume | ||
78 | */ | ||
79 | #define WM8955_RO1VU 0x0100 /* RO1VU */ | ||
80 | #define WM8955_RO1VU_MASK 0x0100 /* RO1VU */ | ||
81 | #define WM8955_RO1VU_SHIFT 8 /* RO1VU */ | ||
82 | #define WM8955_RO1VU_WIDTH 1 /* RO1VU */ | ||
83 | #define WM8955_RO1ZC 0x0080 /* RO1ZC */ | ||
84 | #define WM8955_RO1ZC_MASK 0x0080 /* RO1ZC */ | ||
85 | #define WM8955_RO1ZC_SHIFT 7 /* RO1ZC */ | ||
86 | #define WM8955_RO1ZC_WIDTH 1 /* RO1ZC */ | ||
87 | #define WM8955_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */ | ||
88 | #define WM8955_ROUTVOL_SHIFT 0 /* ROUTVOL - [6:0] */ | ||
89 | #define WM8955_ROUTVOL_WIDTH 7 /* ROUTVOL - [6:0] */ | ||
90 | |||
91 | /* | ||
92 | * R5 (0x05) - DAC Control | ||
93 | */ | ||
94 | #define WM8955_DAT 0x0080 /* DAT */ | ||
95 | #define WM8955_DAT_MASK 0x0080 /* DAT */ | ||
96 | #define WM8955_DAT_SHIFT 7 /* DAT */ | ||
97 | #define WM8955_DAT_WIDTH 1 /* DAT */ | ||
98 | #define WM8955_DACMU 0x0008 /* DACMU */ | ||
99 | #define WM8955_DACMU_MASK 0x0008 /* DACMU */ | ||
100 | #define WM8955_DACMU_SHIFT 3 /* DACMU */ | ||
101 | #define WM8955_DACMU_WIDTH 1 /* DACMU */ | ||
102 | #define WM8955_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ | ||
103 | #define WM8955_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ | ||
104 | #define WM8955_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ | ||
105 | |||
106 | /* | ||
107 | * R7 (0x07) - Audio Interface | ||
108 | */ | ||
109 | #define WM8955_BCLKINV 0x0080 /* BCLKINV */ | ||
110 | #define WM8955_BCLKINV_MASK 0x0080 /* BCLKINV */ | ||
111 | #define WM8955_BCLKINV_SHIFT 7 /* BCLKINV */ | ||
112 | #define WM8955_BCLKINV_WIDTH 1 /* BCLKINV */ | ||
113 | #define WM8955_MS 0x0040 /* MS */ | ||
114 | #define WM8955_MS_MASK 0x0040 /* MS */ | ||
115 | #define WM8955_MS_SHIFT 6 /* MS */ | ||
116 | #define WM8955_MS_WIDTH 1 /* MS */ | ||
117 | #define WM8955_LRSWAP 0x0020 /* LRSWAP */ | ||
118 | #define WM8955_LRSWAP_MASK 0x0020 /* LRSWAP */ | ||
119 | #define WM8955_LRSWAP_SHIFT 5 /* LRSWAP */ | ||
120 | #define WM8955_LRSWAP_WIDTH 1 /* LRSWAP */ | ||
121 | #define WM8955_LRP 0x0010 /* LRP */ | ||
122 | #define WM8955_LRP_MASK 0x0010 /* LRP */ | ||
123 | #define WM8955_LRP_SHIFT 4 /* LRP */ | ||
124 | #define WM8955_LRP_WIDTH 1 /* LRP */ | ||
125 | #define WM8955_WL_MASK 0x000C /* WL - [3:2] */ | ||
126 | #define WM8955_WL_SHIFT 2 /* WL - [3:2] */ | ||
127 | #define WM8955_WL_WIDTH 2 /* WL - [3:2] */ | ||
128 | #define WM8955_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ | ||
129 | #define WM8955_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ | ||
130 | #define WM8955_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ | ||
131 | |||
132 | /* | ||
133 | * R8 (0x08) - Sample Rate | ||
134 | */ | ||
135 | #define WM8955_BCLKDIV2 0x0080 /* BCLKDIV2 */ | ||
136 | #define WM8955_BCLKDIV2_MASK 0x0080 /* BCLKDIV2 */ | ||
137 | #define WM8955_BCLKDIV2_SHIFT 7 /* BCLKDIV2 */ | ||
138 | #define WM8955_BCLKDIV2_WIDTH 1 /* BCLKDIV2 */ | ||
139 | #define WM8955_MCLKDIV2 0x0040 /* MCLKDIV2 */ | ||
140 | #define WM8955_MCLKDIV2_MASK 0x0040 /* MCLKDIV2 */ | ||
141 | #define WM8955_MCLKDIV2_SHIFT 6 /* MCLKDIV2 */ | ||
142 | #define WM8955_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */ | ||
143 | #define WM8955_SR_MASK 0x003E /* SR - [5:1] */ | ||
144 | #define WM8955_SR_SHIFT 1 /* SR - [5:1] */ | ||
145 | #define WM8955_SR_WIDTH 5 /* SR - [5:1] */ | ||
146 | #define WM8955_USB 0x0001 /* USB */ | ||
147 | #define WM8955_USB_MASK 0x0001 /* USB */ | ||
148 | #define WM8955_USB_SHIFT 0 /* USB */ | ||
149 | #define WM8955_USB_WIDTH 1 /* USB */ | ||
150 | |||
151 | /* | ||
152 | * R10 (0x0A) - Left DAC volume | ||
153 | */ | ||
154 | #define WM8955_LDVU 0x0100 /* LDVU */ | ||
155 | #define WM8955_LDVU_MASK 0x0100 /* LDVU */ | ||
156 | #define WM8955_LDVU_SHIFT 8 /* LDVU */ | ||
157 | #define WM8955_LDVU_WIDTH 1 /* LDVU */ | ||
158 | #define WM8955_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */ | ||
159 | #define WM8955_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */ | ||
160 | #define WM8955_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */ | ||
161 | |||
162 | /* | ||
163 | * R11 (0x0B) - Right DAC volume | ||
164 | */ | ||
165 | #define WM8955_RDVU 0x0100 /* RDVU */ | ||
166 | #define WM8955_RDVU_MASK 0x0100 /* RDVU */ | ||
167 | #define WM8955_RDVU_SHIFT 8 /* RDVU */ | ||
168 | #define WM8955_RDVU_WIDTH 1 /* RDVU */ | ||
169 | #define WM8955_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */ | ||
170 | #define WM8955_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */ | ||
171 | #define WM8955_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */ | ||
172 | |||
173 | /* | ||
174 | * R12 (0x0C) - Bass control | ||
175 | */ | ||
176 | #define WM8955_BB 0x0080 /* BB */ | ||
177 | #define WM8955_BB_MASK 0x0080 /* BB */ | ||
178 | #define WM8955_BB_SHIFT 7 /* BB */ | ||
179 | #define WM8955_BB_WIDTH 1 /* BB */ | ||
180 | #define WM8955_BC 0x0040 /* BC */ | ||
181 | #define WM8955_BC_MASK 0x0040 /* BC */ | ||
182 | #define WM8955_BC_SHIFT 6 /* BC */ | ||
183 | #define WM8955_BC_WIDTH 1 /* BC */ | ||
184 | #define WM8955_BASS_MASK 0x000F /* BASS - [3:0] */ | ||
185 | #define WM8955_BASS_SHIFT 0 /* BASS - [3:0] */ | ||
186 | #define WM8955_BASS_WIDTH 4 /* BASS - [3:0] */ | ||
187 | |||
188 | /* | ||
189 | * R13 (0x0D) - Treble control | ||
190 | */ | ||
191 | #define WM8955_TC 0x0040 /* TC */ | ||
192 | #define WM8955_TC_MASK 0x0040 /* TC */ | ||
193 | #define WM8955_TC_SHIFT 6 /* TC */ | ||
194 | #define WM8955_TC_WIDTH 1 /* TC */ | ||
195 | #define WM8955_TRBL_MASK 0x000F /* TRBL - [3:0] */ | ||
196 | #define WM8955_TRBL_SHIFT 0 /* TRBL - [3:0] */ | ||
197 | #define WM8955_TRBL_WIDTH 4 /* TRBL - [3:0] */ | ||
198 | |||
199 | /* | ||
200 | * R15 (0x0F) - Reset | ||
201 | */ | ||
202 | #define WM8955_RESET_MASK 0x01FF /* RESET - [8:0] */ | ||
203 | #define WM8955_RESET_SHIFT 0 /* RESET - [8:0] */ | ||
204 | #define WM8955_RESET_WIDTH 9 /* RESET - [8:0] */ | ||
205 | |||
206 | /* | ||
207 | * R23 (0x17) - Additional control (1) | ||
208 | */ | ||
209 | #define WM8955_TSDEN 0x0100 /* TSDEN */ | ||
210 | #define WM8955_TSDEN_MASK 0x0100 /* TSDEN */ | ||
211 | #define WM8955_TSDEN_SHIFT 8 /* TSDEN */ | ||
212 | #define WM8955_TSDEN_WIDTH 1 /* TSDEN */ | ||
213 | #define WM8955_VSEL_MASK 0x00C0 /* VSEL - [7:6] */ | ||
214 | #define WM8955_VSEL_SHIFT 6 /* VSEL - [7:6] */ | ||
215 | #define WM8955_VSEL_WIDTH 2 /* VSEL - [7:6] */ | ||
216 | #define WM8955_DMONOMIX_MASK 0x0030 /* DMONOMIX - [5:4] */ | ||
217 | #define WM8955_DMONOMIX_SHIFT 4 /* DMONOMIX - [5:4] */ | ||
218 | #define WM8955_DMONOMIX_WIDTH 2 /* DMONOMIX - [5:4] */ | ||
219 | #define WM8955_DACINV 0x0002 /* DACINV */ | ||
220 | #define WM8955_DACINV_MASK 0x0002 /* DACINV */ | ||
221 | #define WM8955_DACINV_SHIFT 1 /* DACINV */ | ||
222 | #define WM8955_DACINV_WIDTH 1 /* DACINV */ | ||
223 | #define WM8955_TOEN 0x0001 /* TOEN */ | ||
224 | #define WM8955_TOEN_MASK 0x0001 /* TOEN */ | ||
225 | #define WM8955_TOEN_SHIFT 0 /* TOEN */ | ||
226 | #define WM8955_TOEN_WIDTH 1 /* TOEN */ | ||
227 | |||
228 | /* | ||
229 | * R24 (0x18) - Additional control (2) | ||
230 | */ | ||
231 | #define WM8955_OUT3SW_MASK 0x0180 /* OUT3SW - [8:7] */ | ||
232 | #define WM8955_OUT3SW_SHIFT 7 /* OUT3SW - [8:7] */ | ||
233 | #define WM8955_OUT3SW_WIDTH 2 /* OUT3SW - [8:7] */ | ||
234 | #define WM8955_ROUT2INV 0x0010 /* ROUT2INV */ | ||
235 | #define WM8955_ROUT2INV_MASK 0x0010 /* ROUT2INV */ | ||
236 | #define WM8955_ROUT2INV_SHIFT 4 /* ROUT2INV */ | ||
237 | #define WM8955_ROUT2INV_WIDTH 1 /* ROUT2INV */ | ||
238 | #define WM8955_DACOSR 0x0001 /* DACOSR */ | ||
239 | #define WM8955_DACOSR_MASK 0x0001 /* DACOSR */ | ||
240 | #define WM8955_DACOSR_SHIFT 0 /* DACOSR */ | ||
241 | #define WM8955_DACOSR_WIDTH 1 /* DACOSR */ | ||
242 | |||
243 | /* | ||
244 | * R25 (0x19) - Power Management (1) | ||
245 | */ | ||
246 | #define WM8955_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */ | ||
247 | #define WM8955_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */ | ||
248 | #define WM8955_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */ | ||
249 | #define WM8955_VREF 0x0040 /* VREF */ | ||
250 | #define WM8955_VREF_MASK 0x0040 /* VREF */ | ||
251 | #define WM8955_VREF_SHIFT 6 /* VREF */ | ||
252 | #define WM8955_VREF_WIDTH 1 /* VREF */ | ||
253 | #define WM8955_DIGENB 0x0001 /* DIGENB */ | ||
254 | #define WM8955_DIGENB_MASK 0x0001 /* DIGENB */ | ||
255 | #define WM8955_DIGENB_SHIFT 0 /* DIGENB */ | ||
256 | #define WM8955_DIGENB_WIDTH 1 /* DIGENB */ | ||
257 | |||
258 | /* | ||
259 | * R26 (0x1A) - Power Management (2) | ||
260 | */ | ||
261 | #define WM8955_DACL 0x0100 /* DACL */ | ||
262 | #define WM8955_DACL_MASK 0x0100 /* DACL */ | ||
263 | #define WM8955_DACL_SHIFT 8 /* DACL */ | ||
264 | #define WM8955_DACL_WIDTH 1 /* DACL */ | ||
265 | #define WM8955_DACR 0x0080 /* DACR */ | ||
266 | #define WM8955_DACR_MASK 0x0080 /* DACR */ | ||
267 | #define WM8955_DACR_SHIFT 7 /* DACR */ | ||
268 | #define WM8955_DACR_WIDTH 1 /* DACR */ | ||
269 | #define WM8955_LOUT1 0x0040 /* LOUT1 */ | ||
270 | #define WM8955_LOUT1_MASK 0x0040 /* LOUT1 */ | ||
271 | #define WM8955_LOUT1_SHIFT 6 /* LOUT1 */ | ||
272 | #define WM8955_LOUT1_WIDTH 1 /* LOUT1 */ | ||
273 | #define WM8955_ROUT1 0x0020 /* ROUT1 */ | ||
274 | #define WM8955_ROUT1_MASK 0x0020 /* ROUT1 */ | ||
275 | #define WM8955_ROUT1_SHIFT 5 /* ROUT1 */ | ||
276 | #define WM8955_ROUT1_WIDTH 1 /* ROUT1 */ | ||
277 | #define WM8955_LOUT2 0x0010 /* LOUT2 */ | ||
278 | #define WM8955_LOUT2_MASK 0x0010 /* LOUT2 */ | ||
279 | #define WM8955_LOUT2_SHIFT 4 /* LOUT2 */ | ||
280 | #define WM8955_LOUT2_WIDTH 1 /* LOUT2 */ | ||
281 | #define WM8955_ROUT2 0x0008 /* ROUT2 */ | ||
282 | #define WM8955_ROUT2_MASK 0x0008 /* ROUT2 */ | ||
283 | #define WM8955_ROUT2_SHIFT 3 /* ROUT2 */ | ||
284 | #define WM8955_ROUT2_WIDTH 1 /* ROUT2 */ | ||
285 | #define WM8955_MONO 0x0004 /* MONO */ | ||
286 | #define WM8955_MONO_MASK 0x0004 /* MONO */ | ||
287 | #define WM8955_MONO_SHIFT 2 /* MONO */ | ||
288 | #define WM8955_MONO_WIDTH 1 /* MONO */ | ||
289 | #define WM8955_OUT3 0x0002 /* OUT3 */ | ||
290 | #define WM8955_OUT3_MASK 0x0002 /* OUT3 */ | ||
291 | #define WM8955_OUT3_SHIFT 1 /* OUT3 */ | ||
292 | #define WM8955_OUT3_WIDTH 1 /* OUT3 */ | ||
293 | |||
294 | /* | ||
295 | * R27 (0x1B) - Additional Control (3) | ||
296 | */ | ||
297 | #define WM8955_VROI 0x0040 /* VROI */ | ||
298 | #define WM8955_VROI_MASK 0x0040 /* VROI */ | ||
299 | #define WM8955_VROI_SHIFT 6 /* VROI */ | ||
300 | #define WM8955_VROI_WIDTH 1 /* VROI */ | ||
301 | |||
302 | /* | ||
303 | * R34 (0x22) - Left out Mix (1) | ||
304 | */ | ||
305 | #define WM8955_LD2LO 0x0100 /* LD2LO */ | ||
306 | #define WM8955_LD2LO_MASK 0x0100 /* LD2LO */ | ||
307 | #define WM8955_LD2LO_SHIFT 8 /* LD2LO */ | ||
308 | #define WM8955_LD2LO_WIDTH 1 /* LD2LO */ | ||
309 | #define WM8955_LI2LO 0x0080 /* LI2LO */ | ||
310 | #define WM8955_LI2LO_MASK 0x0080 /* LI2LO */ | ||
311 | #define WM8955_LI2LO_SHIFT 7 /* LI2LO */ | ||
312 | #define WM8955_LI2LO_WIDTH 1 /* LI2LO */ | ||
313 | #define WM8955_LI2LOVOL_MASK 0x0070 /* LI2LOVOL - [6:4] */ | ||
314 | #define WM8955_LI2LOVOL_SHIFT 4 /* LI2LOVOL - [6:4] */ | ||
315 | #define WM8955_LI2LOVOL_WIDTH 3 /* LI2LOVOL - [6:4] */ | ||
316 | |||
317 | /* | ||
318 | * R35 (0x23) - Left out Mix (2) | ||
319 | */ | ||
320 | #define WM8955_RD2LO 0x0100 /* RD2LO */ | ||
321 | #define WM8955_RD2LO_MASK 0x0100 /* RD2LO */ | ||
322 | #define WM8955_RD2LO_SHIFT 8 /* RD2LO */ | ||
323 | #define WM8955_RD2LO_WIDTH 1 /* RD2LO */ | ||
324 | #define WM8955_RI2LO 0x0080 /* RI2LO */ | ||
325 | #define WM8955_RI2LO_MASK 0x0080 /* RI2LO */ | ||
326 | #define WM8955_RI2LO_SHIFT 7 /* RI2LO */ | ||
327 | #define WM8955_RI2LO_WIDTH 1 /* RI2LO */ | ||
328 | #define WM8955_RI2LOVOL_MASK 0x0070 /* RI2LOVOL - [6:4] */ | ||
329 | #define WM8955_RI2LOVOL_SHIFT 4 /* RI2LOVOL - [6:4] */ | ||
330 | #define WM8955_RI2LOVOL_WIDTH 3 /* RI2LOVOL - [6:4] */ | ||
331 | |||
332 | /* | ||
333 | * R36 (0x24) - Right out Mix (1) | ||
334 | */ | ||
335 | #define WM8955_LD2RO 0x0100 /* LD2RO */ | ||
336 | #define WM8955_LD2RO_MASK 0x0100 /* LD2RO */ | ||
337 | #define WM8955_LD2RO_SHIFT 8 /* LD2RO */ | ||
338 | #define WM8955_LD2RO_WIDTH 1 /* LD2RO */ | ||
339 | #define WM8955_LI2RO 0x0080 /* LI2RO */ | ||
340 | #define WM8955_LI2RO_MASK 0x0080 /* LI2RO */ | ||
341 | #define WM8955_LI2RO_SHIFT 7 /* LI2RO */ | ||
342 | #define WM8955_LI2RO_WIDTH 1 /* LI2RO */ | ||
343 | #define WM8955_LI2ROVOL_MASK 0x0070 /* LI2ROVOL - [6:4] */ | ||
344 | #define WM8955_LI2ROVOL_SHIFT 4 /* LI2ROVOL - [6:4] */ | ||
345 | #define WM8955_LI2ROVOL_WIDTH 3 /* LI2ROVOL - [6:4] */ | ||
346 | |||
347 | /* | ||
348 | * R37 (0x25) - Right Out Mix (2) | ||
349 | */ | ||
350 | #define WM8955_RD2RO 0x0100 /* RD2RO */ | ||
351 | #define WM8955_RD2RO_MASK 0x0100 /* RD2RO */ | ||
352 | #define WM8955_RD2RO_SHIFT 8 /* RD2RO */ | ||
353 | #define WM8955_RD2RO_WIDTH 1 /* RD2RO */ | ||
354 | #define WM8955_RI2RO 0x0080 /* RI2RO */ | ||
355 | #define WM8955_RI2RO_MASK 0x0080 /* RI2RO */ | ||
356 | #define WM8955_RI2RO_SHIFT 7 /* RI2RO */ | ||
357 | #define WM8955_RI2RO_WIDTH 1 /* RI2RO */ | ||
358 | #define WM8955_RI2ROVOL_MASK 0x0070 /* RI2ROVOL - [6:4] */ | ||
359 | #define WM8955_RI2ROVOL_SHIFT 4 /* RI2ROVOL - [6:4] */ | ||
360 | #define WM8955_RI2ROVOL_WIDTH 3 /* RI2ROVOL - [6:4] */ | ||
361 | |||
362 | /* | ||
363 | * R38 (0x26) - Mono out Mix (1) | ||
364 | */ | ||
365 | #define WM8955_LD2MO 0x0100 /* LD2MO */ | ||
366 | #define WM8955_LD2MO_MASK 0x0100 /* LD2MO */ | ||
367 | #define WM8955_LD2MO_SHIFT 8 /* LD2MO */ | ||
368 | #define WM8955_LD2MO_WIDTH 1 /* LD2MO */ | ||
369 | #define WM8955_LI2MO 0x0080 /* LI2MO */ | ||
370 | #define WM8955_LI2MO_MASK 0x0080 /* LI2MO */ | ||
371 | #define WM8955_LI2MO_SHIFT 7 /* LI2MO */ | ||
372 | #define WM8955_LI2MO_WIDTH 1 /* LI2MO */ | ||
373 | #define WM8955_LI2MOVOL_MASK 0x0070 /* LI2MOVOL - [6:4] */ | ||
374 | #define WM8955_LI2MOVOL_SHIFT 4 /* LI2MOVOL - [6:4] */ | ||
375 | #define WM8955_LI2MOVOL_WIDTH 3 /* LI2MOVOL - [6:4] */ | ||
376 | #define WM8955_DMEN 0x0001 /* DMEN */ | ||
377 | #define WM8955_DMEN_MASK 0x0001 /* DMEN */ | ||
378 | #define WM8955_DMEN_SHIFT 0 /* DMEN */ | ||
379 | #define WM8955_DMEN_WIDTH 1 /* DMEN */ | ||
380 | |||
381 | /* | ||
382 | * R39 (0x27) - Mono out Mix (2) | ||
383 | */ | ||
384 | #define WM8955_RD2MO 0x0100 /* RD2MO */ | ||
385 | #define WM8955_RD2MO_MASK 0x0100 /* RD2MO */ | ||
386 | #define WM8955_RD2MO_SHIFT 8 /* RD2MO */ | ||
387 | #define WM8955_RD2MO_WIDTH 1 /* RD2MO */ | ||
388 | #define WM8955_RI2MO 0x0080 /* RI2MO */ | ||
389 | #define WM8955_RI2MO_MASK 0x0080 /* RI2MO */ | ||
390 | #define WM8955_RI2MO_SHIFT 7 /* RI2MO */ | ||
391 | #define WM8955_RI2MO_WIDTH 1 /* RI2MO */ | ||
392 | #define WM8955_RI2MOVOL_MASK 0x0070 /* RI2MOVOL - [6:4] */ | ||
393 | #define WM8955_RI2MOVOL_SHIFT 4 /* RI2MOVOL - [6:4] */ | ||
394 | #define WM8955_RI2MOVOL_WIDTH 3 /* RI2MOVOL - [6:4] */ | ||
395 | |||
396 | /* | ||
397 | * R40 (0x28) - LOUT2 volume | ||
398 | */ | ||
399 | #define WM8955_LO2VU 0x0100 /* LO2VU */ | ||
400 | #define WM8955_LO2VU_MASK 0x0100 /* LO2VU */ | ||
401 | #define WM8955_LO2VU_SHIFT 8 /* LO2VU */ | ||
402 | #define WM8955_LO2VU_WIDTH 1 /* LO2VU */ | ||
403 | #define WM8955_LO2ZC 0x0080 /* LO2ZC */ | ||
404 | #define WM8955_LO2ZC_MASK 0x0080 /* LO2ZC */ | ||
405 | #define WM8955_LO2ZC_SHIFT 7 /* LO2ZC */ | ||
406 | #define WM8955_LO2ZC_WIDTH 1 /* LO2ZC */ | ||
407 | #define WM8955_LOUT2VOL_MASK 0x007F /* LOUT2VOL - [6:0] */ | ||
408 | #define WM8955_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [6:0] */ | ||
409 | #define WM8955_LOUT2VOL_WIDTH 7 /* LOUT2VOL - [6:0] */ | ||
410 | |||
411 | /* | ||
412 | * R41 (0x29) - ROUT2 volume | ||
413 | */ | ||
414 | #define WM8955_RO2VU 0x0100 /* RO2VU */ | ||
415 | #define WM8955_RO2VU_MASK 0x0100 /* RO2VU */ | ||
416 | #define WM8955_RO2VU_SHIFT 8 /* RO2VU */ | ||
417 | #define WM8955_RO2VU_WIDTH 1 /* RO2VU */ | ||
418 | #define WM8955_RO2ZC 0x0080 /* RO2ZC */ | ||
419 | #define WM8955_RO2ZC_MASK 0x0080 /* RO2ZC */ | ||
420 | #define WM8955_RO2ZC_SHIFT 7 /* RO2ZC */ | ||
421 | #define WM8955_RO2ZC_WIDTH 1 /* RO2ZC */ | ||
422 | #define WM8955_ROUT2VOL_MASK 0x007F /* ROUT2VOL - [6:0] */ | ||
423 | #define WM8955_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [6:0] */ | ||
424 | #define WM8955_ROUT2VOL_WIDTH 7 /* ROUT2VOL - [6:0] */ | ||
425 | |||
426 | /* | ||
427 | * R42 (0x2A) - MONOOUT volume | ||
428 | */ | ||
429 | #define WM8955_MOZC 0x0080 /* MOZC */ | ||
430 | #define WM8955_MOZC_MASK 0x0080 /* MOZC */ | ||
431 | #define WM8955_MOZC_SHIFT 7 /* MOZC */ | ||
432 | #define WM8955_MOZC_WIDTH 1 /* MOZC */ | ||
433 | #define WM8955_MOUTVOL_MASK 0x007F /* MOUTVOL - [6:0] */ | ||
434 | #define WM8955_MOUTVOL_SHIFT 0 /* MOUTVOL - [6:0] */ | ||
435 | #define WM8955_MOUTVOL_WIDTH 7 /* MOUTVOL - [6:0] */ | ||
436 | |||
437 | /* | ||
438 | * R43 (0x2B) - Clocking / PLL | ||
439 | */ | ||
440 | #define WM8955_MCLKSEL 0x0100 /* MCLKSEL */ | ||
441 | #define WM8955_MCLKSEL_MASK 0x0100 /* MCLKSEL */ | ||
442 | #define WM8955_MCLKSEL_SHIFT 8 /* MCLKSEL */ | ||
443 | #define WM8955_MCLKSEL_WIDTH 1 /* MCLKSEL */ | ||
444 | #define WM8955_PLLOUTDIV2 0x0020 /* PLLOUTDIV2 */ | ||
445 | #define WM8955_PLLOUTDIV2_MASK 0x0020 /* PLLOUTDIV2 */ | ||
446 | #define WM8955_PLLOUTDIV2_SHIFT 5 /* PLLOUTDIV2 */ | ||
447 | #define WM8955_PLLOUTDIV2_WIDTH 1 /* PLLOUTDIV2 */ | ||
448 | #define WM8955_PLL_RB 0x0010 /* PLL_RB */ | ||
449 | #define WM8955_PLL_RB_MASK 0x0010 /* PLL_RB */ | ||
450 | #define WM8955_PLL_RB_SHIFT 4 /* PLL_RB */ | ||
451 | #define WM8955_PLL_RB_WIDTH 1 /* PLL_RB */ | ||
452 | #define WM8955_PLLEN 0x0008 /* PLLEN */ | ||
453 | #define WM8955_PLLEN_MASK 0x0008 /* PLLEN */ | ||
454 | #define WM8955_PLLEN_SHIFT 3 /* PLLEN */ | ||
455 | #define WM8955_PLLEN_WIDTH 1 /* PLLEN */ | ||
456 | |||
457 | /* | ||
458 | * R44 (0x2C) - PLL Control 1 | ||
459 | */ | ||
460 | #define WM8955_N_MASK 0x01E0 /* N - [8:5] */ | ||
461 | #define WM8955_N_SHIFT 5 /* N - [8:5] */ | ||
462 | #define WM8955_N_WIDTH 4 /* N - [8:5] */ | ||
463 | #define WM8955_K_21_18_MASK 0x000F /* K(21:18) - [3:0] */ | ||
464 | #define WM8955_K_21_18_SHIFT 0 /* K(21:18) - [3:0] */ | ||
465 | #define WM8955_K_21_18_WIDTH 4 /* K(21:18) - [3:0] */ | ||
466 | |||
467 | /* | ||
468 | * R45 (0x2D) - PLL Control 2 | ||
469 | */ | ||
470 | #define WM8955_K_17_9_MASK 0x01FF /* K(17:9) - [8:0] */ | ||
471 | #define WM8955_K_17_9_SHIFT 0 /* K(17:9) - [8:0] */ | ||
472 | #define WM8955_K_17_9_WIDTH 9 /* K(17:9) - [8:0] */ | ||
473 | |||
474 | /* | ||
475 | * R46 (0x2E) - PLL Control 3 | ||
476 | */ | ||
477 | #define WM8955_K_8_0_MASK 0x01FF /* K(8:0) - [8:0] */ | ||
478 | #define WM8955_K_8_0_SHIFT 0 /* K(8:0) - [8:0] */ | ||
479 | #define WM8955_K_8_0_WIDTH 9 /* K(8:0) - [8:0] */ | ||
480 | |||
481 | /* | ||
482 | * R59 (0x3B) - PLL Control 4 | ||
483 | */ | ||
484 | #define WM8955_KEN 0x0080 /* KEN */ | ||
485 | #define WM8955_KEN_MASK 0x0080 /* KEN */ | ||
486 | #define WM8955_KEN_SHIFT 7 /* KEN */ | ||
487 | #define WM8955_KEN_WIDTH 1 /* KEN */ | ||
488 | |||
489 | #endif | ||
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f59703be61c8..f1e63e01b04d 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pm.h> | 15 | #include <linux/pm.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/slab.h> | ||
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> | 21 | #include <sound/pcm_params.h> |
@@ -307,7 +308,6 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec) | |||
307 | 308 | ||
308 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 309 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
309 | 310 | ||
310 | snd_soc_dapm_new_widgets(codec); | ||
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
313 | 313 | ||
@@ -540,8 +540,8 @@ static int pll_factors(unsigned int source, unsigned int target, | |||
540 | return 0; | 540 | return 0; |
541 | } | 541 | } |
542 | 542 | ||
543 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, | 543 | static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
544 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 544 | int source, unsigned int freq_in, unsigned int freq_out) |
545 | { | 545 | { |
546 | struct snd_soc_codec *codec = codec_dai->codec; | 546 | struct snd_soc_codec *codec = codec_dai->codec; |
547 | u16 reg; | 547 | u16 reg; |
@@ -713,17 +713,9 @@ static int wm8960_probe(struct platform_device *pdev) | |||
713 | snd_soc_add_controls(codec, wm8960_snd_controls, | 713 | snd_soc_add_controls(codec, wm8960_snd_controls, |
714 | ARRAY_SIZE(wm8960_snd_controls)); | 714 | ARRAY_SIZE(wm8960_snd_controls)); |
715 | wm8960_add_widgets(codec); | 715 | wm8960_add_widgets(codec); |
716 | ret = snd_soc_init_card(socdev); | ||
717 | if (ret < 0) { | ||
718 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
719 | goto card_err; | ||
720 | } | ||
721 | 716 | ||
722 | return ret; | 717 | return ret; |
723 | 718 | ||
724 | card_err: | ||
725 | snd_soc_free_pcms(socdev); | ||
726 | snd_soc_dapm_free(socdev); | ||
727 | pcm_err: | 719 | pcm_err: |
728 | return ret; | 720 | return ret; |
729 | } | 721 | } |
@@ -883,21 +875,6 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client) | |||
883 | return 0; | 875 | return 0; |
884 | } | 876 | } |
885 | 877 | ||
886 | #ifdef CONFIG_PM | ||
887 | static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
888 | { | ||
889 | return snd_soc_suspend_device(&client->dev); | ||
890 | } | ||
891 | |||
892 | static int wm8960_i2c_resume(struct i2c_client *client) | ||
893 | { | ||
894 | return snd_soc_resume_device(&client->dev); | ||
895 | } | ||
896 | #else | ||
897 | #define wm8960_i2c_suspend NULL | ||
898 | #define wm8960_i2c_resume NULL | ||
899 | #endif | ||
900 | |||
901 | static const struct i2c_device_id wm8960_i2c_id[] = { | 878 | static const struct i2c_device_id wm8960_i2c_id[] = { |
902 | { "wm8960", 0 }, | 879 | { "wm8960", 0 }, |
903 | { } | 880 | { } |
@@ -911,8 +888,6 @@ static struct i2c_driver wm8960_i2c_driver = { | |||
911 | }, | 888 | }, |
912 | .probe = wm8960_i2c_probe, | 889 | .probe = wm8960_i2c_probe, |
913 | .remove = __devexit_p(wm8960_i2c_remove), | 890 | .remove = __devexit_p(wm8960_i2c_remove), |
914 | .suspend = wm8960_i2c_suspend, | ||
915 | .resume = wm8960_i2c_resume, | ||
916 | .id_table = wm8960_i2c_id, | 891 | .id_table = wm8960_i2c_id, |
917 | }; | 892 | }; |
918 | 893 | ||
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 503032085899..50634ab76a5c 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -986,19 +987,9 @@ static int wm8961_probe(struct platform_device *pdev) | |||
986 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, | 987 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, |
987 | ARRAY_SIZE(wm8961_dapm_widgets)); | 988 | ARRAY_SIZE(wm8961_dapm_widgets)); |
988 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 989 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
989 | snd_soc_dapm_new_widgets(codec); | ||
990 | |||
991 | ret = snd_soc_init_card(socdev); | ||
992 | if (ret < 0) { | ||
993 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
994 | goto card_err; | ||
995 | } | ||
996 | 990 | ||
997 | return ret; | 991 | return ret; |
998 | 992 | ||
999 | card_err: | ||
1000 | snd_soc_free_pcms(socdev); | ||
1001 | snd_soc_dapm_free(socdev); | ||
1002 | pcm_err: | 993 | pcm_err: |
1003 | return ret; | 994 | return ret; |
1004 | } | 995 | } |
@@ -1032,6 +1023,9 @@ static int wm8961_resume(struct platform_device *pdev) | |||
1032 | int i; | 1023 | int i; |
1033 | 1024 | ||
1034 | for (i = 0; i < codec->reg_cache_size; i++) { | 1025 | for (i = 0; i < codec->reg_cache_size; i++) { |
1026 | if (reg_cache[i] == wm8961_reg_defaults[i]) | ||
1027 | continue; | ||
1028 | |||
1035 | if (i == WM8961_SOFTWARE_RESET) | 1029 | if (i == WM8961_SOFTWARE_RESET) |
1036 | continue; | 1030 | continue; |
1037 | 1031 | ||
@@ -1206,21 +1200,6 @@ static __devexit int wm8961_i2c_remove(struct i2c_client *client) | |||
1206 | return 0; | 1200 | return 0; |
1207 | } | 1201 | } |
1208 | 1202 | ||
1209 | #ifdef CONFIG_PM | ||
1210 | static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state) | ||
1211 | { | ||
1212 | return snd_soc_suspend_device(&client->dev); | ||
1213 | } | ||
1214 | |||
1215 | static int wm8961_i2c_resume(struct i2c_client *client) | ||
1216 | { | ||
1217 | return snd_soc_resume_device(&client->dev); | ||
1218 | } | ||
1219 | #else | ||
1220 | #define wm8961_i2c_suspend NULL | ||
1221 | #define wm8961_i2c_resume NULL | ||
1222 | #endif | ||
1223 | |||
1224 | static const struct i2c_device_id wm8961_i2c_id[] = { | 1203 | static const struct i2c_device_id wm8961_i2c_id[] = { |
1225 | { "wm8961", 0 }, | 1204 | { "wm8961", 0 }, |
1226 | { } | 1205 | { } |
@@ -1234,8 +1213,6 @@ static struct i2c_driver wm8961_i2c_driver = { | |||
1234 | }, | 1213 | }, |
1235 | .probe = wm8961_i2c_probe, | 1214 | .probe = wm8961_i2c_probe, |
1236 | .remove = __devexit_p(wm8961_i2c_remove), | 1215 | .remove = __devexit_p(wm8961_i2c_remove), |
1237 | .suspend = wm8961_i2c_suspend, | ||
1238 | .resume = wm8961_i2c_resume, | ||
1239 | .id_table = wm8961_i2c_id, | 1216 | .id_table = wm8961_i2c_id, |
1240 | }; | 1217 | }; |
1241 | 1218 | ||
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index d66efb0546ea..a65b781af512 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -338,8 +339,6 @@ static int wm8971_add_widgets(struct snd_soc_codec *codec) | |||
338 | 339 | ||
339 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 340 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
340 | 341 | ||
341 | snd_soc_dapm_new_widgets(codec); | ||
342 | |||
343 | return 0; | 342 | return 0; |
344 | } | 343 | } |
345 | 344 | ||
@@ -703,16 +702,9 @@ static int wm8971_init(struct snd_soc_device *socdev, | |||
703 | snd_soc_add_controls(codec, wm8971_snd_controls, | 702 | snd_soc_add_controls(codec, wm8971_snd_controls, |
704 | ARRAY_SIZE(wm8971_snd_controls)); | 703 | ARRAY_SIZE(wm8971_snd_controls)); |
705 | wm8971_add_widgets(codec); | 704 | wm8971_add_widgets(codec); |
706 | ret = snd_soc_init_card(socdev); | 705 | |
707 | if (ret < 0) { | ||
708 | printk(KERN_ERR "wm8971: failed to register card\n"); | ||
709 | goto card_err; | ||
710 | } | ||
711 | return ret; | 706 | return ret; |
712 | 707 | ||
713 | card_err: | ||
714 | snd_soc_free_pcms(socdev); | ||
715 | snd_soc_dapm_free(socdev); | ||
716 | err: | 708 | err: |
717 | kfree(codec->reg_cache); | 709 | kfree(codec->reg_cache); |
718 | return ret; | 710 | return ret; |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 98d663afc97d..69708c4cc004 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -47,7 +48,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { | |||
47 | }; | 48 | }; |
48 | 49 | ||
49 | #define WM8974_POWER1_BIASEN 0x08 | 50 | #define WM8974_POWER1_BIASEN 0x08 |
50 | #define WM8974_POWER1_BUFIOEN 0x10 | 51 | #define WM8974_POWER1_BUFIOEN 0x04 |
51 | 52 | ||
52 | struct wm8974_priv { | 53 | struct wm8974_priv { |
53 | struct snd_soc_codec codec; | 54 | struct snd_soc_codec codec; |
@@ -170,6 +171,10 @@ SOC_ENUM("Aux Mode", wm8974_auxmode), | |||
170 | 171 | ||
171 | SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0), | 172 | SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0), |
172 | SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1), | 173 | SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1), |
174 | |||
175 | /* DAC / ADC oversampling */ | ||
176 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8974_DAC, 8, 1, 0), | ||
177 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8974_ADC, 8, 1, 0), | ||
173 | }; | 178 | }; |
174 | 179 | ||
175 | /* Speaker Output Mixer */ | 180 | /* Speaker Output Mixer */ |
@@ -276,41 +281,42 @@ static int wm8974_add_widgets(struct snd_soc_codec *codec) | |||
276 | 281 | ||
277 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 282 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
278 | 283 | ||
279 | snd_soc_dapm_new_widgets(codec); | ||
280 | return 0; | 284 | return 0; |
281 | } | 285 | } |
282 | 286 | ||
283 | struct pll_ { | 287 | struct pll_ { |
284 | unsigned int pre_div:4; /* prescale - 1 */ | 288 | unsigned int pre_div:1; |
285 | unsigned int n:4; | 289 | unsigned int n:4; |
286 | unsigned int k; | 290 | unsigned int k; |
287 | }; | 291 | }; |
288 | 292 | ||
289 | static struct pll_ pll_div; | ||
290 | |||
291 | /* The size in bits of the pll divide multiplied by 10 | 293 | /* The size in bits of the pll divide multiplied by 10 |
292 | * to allow rounding later */ | 294 | * to allow rounding later */ |
293 | #define FIXED_PLL_SIZE ((1 << 24) * 10) | 295 | #define FIXED_PLL_SIZE ((1 << 24) * 10) |
294 | 296 | ||
295 | static void pll_factors(unsigned int target, unsigned int source) | 297 | static void pll_factors(struct pll_ *pll_div, |
298 | unsigned int target, unsigned int source) | ||
296 | { | 299 | { |
297 | unsigned long long Kpart; | 300 | unsigned long long Kpart; |
298 | unsigned int K, Ndiv, Nmod; | 301 | unsigned int K, Ndiv, Nmod; |
299 | 302 | ||
303 | /* There is a fixed divide by 4 in the output path */ | ||
304 | target *= 4; | ||
305 | |||
300 | Ndiv = target / source; | 306 | Ndiv = target / source; |
301 | if (Ndiv < 6) { | 307 | if (Ndiv < 6) { |
302 | source >>= 1; | 308 | source /= 2; |
303 | pll_div.pre_div = 1; | 309 | pll_div->pre_div = 1; |
304 | Ndiv = target / source; | 310 | Ndiv = target / source; |
305 | } else | 311 | } else |
306 | pll_div.pre_div = 0; | 312 | pll_div->pre_div = 0; |
307 | 313 | ||
308 | if ((Ndiv < 6) || (Ndiv > 12)) | 314 | if ((Ndiv < 6) || (Ndiv > 12)) |
309 | printk(KERN_WARNING | 315 | printk(KERN_WARNING |
310 | "WM8974 N value %u outwith recommended range!\n", | 316 | "WM8974 N value %u outwith recommended range!\n", |
311 | Ndiv); | 317 | Ndiv); |
312 | 318 | ||
313 | pll_div.n = Ndiv; | 319 | pll_div->n = Ndiv; |
314 | Nmod = target % source; | 320 | Nmod = target % source; |
315 | Kpart = FIXED_PLL_SIZE * (long long)Nmod; | 321 | Kpart = FIXED_PLL_SIZE * (long long)Nmod; |
316 | 322 | ||
@@ -325,13 +331,14 @@ static void pll_factors(unsigned int target, unsigned int source) | |||
325 | /* Move down to proper range now rounding is done */ | 331 | /* Move down to proper range now rounding is done */ |
326 | K /= 10; | 332 | K /= 10; |
327 | 333 | ||
328 | pll_div.k = K; | 334 | pll_div->k = K; |
329 | } | 335 | } |
330 | 336 | ||
331 | static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, | 337 | static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
332 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 338 | int source, unsigned int freq_in, unsigned int freq_out) |
333 | { | 339 | { |
334 | struct snd_soc_codec *codec = codec_dai->codec; | 340 | struct snd_soc_codec *codec = codec_dai->codec; |
341 | struct pll_ pll_div; | ||
335 | u16 reg; | 342 | u16 reg; |
336 | 343 | ||
337 | if (freq_in == 0 || freq_out == 0) { | 344 | if (freq_in == 0 || freq_out == 0) { |
@@ -345,7 +352,7 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
345 | return 0; | 352 | return 0; |
346 | } | 353 | } |
347 | 354 | ||
348 | pll_factors(freq_out*4, freq_in); | 355 | pll_factors(&pll_div, freq_out, freq_in); |
349 | 356 | ||
350 | snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); | 357 | snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); |
351 | snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); | 358 | snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); |
@@ -379,14 +386,6 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
379 | reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; | 386 | reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; |
380 | snd_soc_write(codec, WM8974_CLOCK, reg | div); | 387 | snd_soc_write(codec, WM8974_CLOCK, reg | div); |
381 | break; | 388 | break; |
382 | case WM8974_ADCCLK: | ||
383 | reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7; | ||
384 | snd_soc_write(codec, WM8974_ADC, reg | div); | ||
385 | break; | ||
386 | case WM8974_DACCLK: | ||
387 | reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7; | ||
388 | snd_soc_write(codec, WM8974_DAC, reg | div); | ||
389 | break; | ||
390 | case WM8974_BCLKDIV: | 389 | case WM8974_BCLKDIV: |
391 | reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; | 390 | reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; |
392 | snd_soc_write(codec, WM8974_CLOCK, reg | div); | 391 | snd_soc_write(codec, WM8974_CLOCK, reg | div); |
@@ -480,23 +479,23 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, | |||
480 | 479 | ||
481 | /* filter coefficient */ | 480 | /* filter coefficient */ |
482 | switch (params_rate(params)) { | 481 | switch (params_rate(params)) { |
483 | case SNDRV_PCM_RATE_8000: | 482 | case 8000: |
484 | adn |= 0x5 << 1; | 483 | adn |= 0x5 << 1; |
485 | break; | 484 | break; |
486 | case SNDRV_PCM_RATE_11025: | 485 | case 11025: |
487 | adn |= 0x4 << 1; | 486 | adn |= 0x4 << 1; |
488 | break; | 487 | break; |
489 | case SNDRV_PCM_RATE_16000: | 488 | case 16000: |
490 | adn |= 0x3 << 1; | 489 | adn |= 0x3 << 1; |
491 | break; | 490 | break; |
492 | case SNDRV_PCM_RATE_22050: | 491 | case 22050: |
493 | adn |= 0x2 << 1; | 492 | adn |= 0x2 << 1; |
494 | break; | 493 | break; |
495 | case SNDRV_PCM_RATE_32000: | 494 | case 32000: |
496 | adn |= 0x1 << 1; | 495 | adn |= 0x1 << 1; |
497 | break; | 496 | break; |
498 | case SNDRV_PCM_RATE_44100: | 497 | case 44100: |
499 | case SNDRV_PCM_RATE_48000: | 498 | case 48000: |
500 | break; | 499 | break; |
501 | } | 500 | } |
502 | 501 | ||
@@ -638,17 +637,9 @@ static int wm8974_probe(struct platform_device *pdev) | |||
638 | snd_soc_add_controls(codec, wm8974_snd_controls, | 637 | snd_soc_add_controls(codec, wm8974_snd_controls, |
639 | ARRAY_SIZE(wm8974_snd_controls)); | 638 | ARRAY_SIZE(wm8974_snd_controls)); |
640 | wm8974_add_widgets(codec); | 639 | wm8974_add_widgets(codec); |
641 | ret = snd_soc_init_card(socdev); | ||
642 | if (ret < 0) { | ||
643 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
644 | goto card_err; | ||
645 | } | ||
646 | 640 | ||
647 | return ret; | 641 | return ret; |
648 | 642 | ||
649 | card_err: | ||
650 | snd_soc_free_pcms(socdev); | ||
651 | snd_soc_dapm_free(socdev); | ||
652 | pcm_err: | 643 | pcm_err: |
653 | return ret; | 644 | return ret; |
654 | } | 645 | } |
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 98de9562d4d2..896a7f0f3fc4 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h | |||
@@ -57,17 +57,7 @@ | |||
57 | /* Clock divider Id's */ | 57 | /* Clock divider Id's */ |
58 | #define WM8974_OPCLKDIV 0 | 58 | #define WM8974_OPCLKDIV 0 |
59 | #define WM8974_MCLKDIV 1 | 59 | #define WM8974_MCLKDIV 1 |
60 | #define WM8974_ADCCLK 2 | 60 | #define WM8974_BCLKDIV 2 |
61 | #define WM8974_DACCLK 3 | ||
62 | #define WM8974_BCLKDIV 4 | ||
63 | |||
64 | /* DAC clock dividers */ | ||
65 | #define WM8974_DACCLK_F2 (1 << 3) | ||
66 | #define WM8974_DACCLK_F4 (0 << 3) | ||
67 | |||
68 | /* ADC clock dividers */ | ||
69 | #define WM8974_ADCCLK_F2 (1 << 3) | ||
70 | #define WM8974_ADCCLK_F4 (0 << 3) | ||
71 | 61 | ||
72 | /* PLL Out dividers */ | 62 | /* PLL Out dividers */ |
73 | #define WM8974_OPCLKDIV_1 (0 << 4) | 63 | #define WM8974_OPCLKDIV_1 (0 << 4) |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c new file mode 100644 index 000000000000..526f56b09066 --- /dev/null +++ b/sound/soc/codecs/wm8978.c | |||
@@ -0,0 +1,1150 @@ | |||
1 | /* | ||
2 | * wm8978.c -- WM8978 ALSA SoC Audio Codec driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
5 | * Copyright (C) 2007 Carlos Munoz <carlos@kenati.com> | ||
6 | * Copyright 2006-2009 Wolfson Microelectronics PLC. | ||
7 | * Based on wm8974 and wm8990 by Liam Girdwood <lrg@slimlogic.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <asm/div64.h> | ||
31 | |||
32 | #include "wm8978.h" | ||
33 | |||
34 | static struct snd_soc_codec *wm8978_codec; | ||
35 | |||
36 | /* wm8978 register cache. Note that register 0 is not included in the cache. */ | ||
37 | static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { | ||
38 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ | ||
39 | 0x0050, 0x0000, 0x0140, 0x0000, /* 0x04...0x07 */ | ||
40 | 0x0000, 0x0000, 0x0000, 0x00ff, /* 0x08...0x0b */ | ||
41 | 0x00ff, 0x0000, 0x0100, 0x00ff, /* 0x0c...0x0f */ | ||
42 | 0x00ff, 0x0000, 0x012c, 0x002c, /* 0x10...0x13 */ | ||
43 | 0x002c, 0x002c, 0x002c, 0x0000, /* 0x14...0x17 */ | ||
44 | 0x0032, 0x0000, 0x0000, 0x0000, /* 0x18...0x1b */ | ||
45 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1c...0x1f */ | ||
46 | 0x0038, 0x000b, 0x0032, 0x0000, /* 0x20...0x23 */ | ||
47 | 0x0008, 0x000c, 0x0093, 0x00e9, /* 0x24...0x27 */ | ||
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x28...0x2b */ | ||
49 | 0x0033, 0x0010, 0x0010, 0x0100, /* 0x2c...0x2f */ | ||
50 | 0x0100, 0x0002, 0x0001, 0x0001, /* 0x30...0x33 */ | ||
51 | 0x0039, 0x0039, 0x0039, 0x0039, /* 0x34...0x37 */ | ||
52 | 0x0001, 0x0001, /* 0x38...0x3b */ | ||
53 | }; | ||
54 | |||
55 | /* codec private data */ | ||
56 | struct wm8978_priv { | ||
57 | struct snd_soc_codec codec; | ||
58 | unsigned int f_pllout; | ||
59 | unsigned int f_mclk; | ||
60 | unsigned int f_256fs; | ||
61 | unsigned int f_opclk; | ||
62 | int mclk_idx; | ||
63 | enum wm8978_sysclk_src sysclk; | ||
64 | u16 reg_cache[WM8978_CACHEREGNUM]; | ||
65 | }; | ||
66 | |||
67 | static const char *wm8978_companding[] = {"Off", "NC", "u-law", "A-law"}; | ||
68 | static const char *wm8978_eqmode[] = {"Capture", "Playback"}; | ||
69 | static const char *wm8978_bw[] = {"Narrow", "Wide"}; | ||
70 | static const char *wm8978_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz"}; | ||
71 | static const char *wm8978_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz"}; | ||
72 | static const char *wm8978_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz"}; | ||
73 | static const char *wm8978_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"}; | ||
74 | static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; | ||
75 | static const char *wm8978_alc3[] = {"ALC", "Limiter"}; | ||
76 | static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; | ||
77 | |||
78 | static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, | ||
79 | wm8978_companding); | ||
80 | static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, | ||
81 | wm8978_companding); | ||
82 | static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); | ||
83 | static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); | ||
84 | static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); | ||
85 | static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); | ||
86 | static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); | ||
87 | static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); | ||
88 | static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); | ||
89 | static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); | ||
90 | static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); | ||
91 | static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); | ||
92 | static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); | ||
93 | |||
94 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | ||
95 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
96 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); | ||
97 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); | ||
98 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1); | ||
99 | |||
100 | static const struct snd_kcontrol_new wm8978_snd_controls[] = { | ||
101 | |||
102 | SOC_SINGLE("Digital Loopback Switch", | ||
103 | WM8978_COMPANDING_CONTROL, 0, 1, 0), | ||
104 | |||
105 | SOC_ENUM("ADC Companding", adc_compand), | ||
106 | SOC_ENUM("DAC Companding", dac_compand), | ||
107 | |||
108 | SOC_DOUBLE("DAC Inversion Switch", WM8978_DAC_CONTROL, 0, 1, 1, 0), | ||
109 | |||
110 | SOC_DOUBLE_R_TLV("PCM Volume", | ||
111 | WM8978_LEFT_DAC_DIGITAL_VOLUME, WM8978_RIGHT_DAC_DIGITAL_VOLUME, | ||
112 | 0, 255, 0, digital_tlv), | ||
113 | |||
114 | SOC_SINGLE("High Pass Filter Switch", WM8978_ADC_CONTROL, 8, 1, 0), | ||
115 | SOC_SINGLE("High Pass Cut Off", WM8978_ADC_CONTROL, 4, 7, 0), | ||
116 | SOC_DOUBLE("ADC Inversion Switch", WM8978_ADC_CONTROL, 0, 1, 1, 0), | ||
117 | |||
118 | SOC_DOUBLE_R_TLV("ADC Volume", | ||
119 | WM8978_LEFT_ADC_DIGITAL_VOLUME, WM8978_RIGHT_ADC_DIGITAL_VOLUME, | ||
120 | 0, 255, 0, digital_tlv), | ||
121 | |||
122 | SOC_ENUM("Equaliser Function", eqmode), | ||
123 | SOC_ENUM("EQ1 Cut Off", eq1), | ||
124 | SOC_SINGLE_TLV("EQ1 Volume", WM8978_EQ1, 0, 24, 1, eq_tlv), | ||
125 | |||
126 | SOC_ENUM("Equaliser EQ2 Bandwith", eq2bw), | ||
127 | SOC_ENUM("EQ2 Cut Off", eq2), | ||
128 | SOC_SINGLE_TLV("EQ2 Volume", WM8978_EQ2, 0, 24, 1, eq_tlv), | ||
129 | |||
130 | SOC_ENUM("Equaliser EQ3 Bandwith", eq3bw), | ||
131 | SOC_ENUM("EQ3 Cut Off", eq3), | ||
132 | SOC_SINGLE_TLV("EQ3 Volume", WM8978_EQ3, 0, 24, 1, eq_tlv), | ||
133 | |||
134 | SOC_ENUM("Equaliser EQ4 Bandwith", eq4bw), | ||
135 | SOC_ENUM("EQ4 Cut Off", eq4), | ||
136 | SOC_SINGLE_TLV("EQ4 Volume", WM8978_EQ4, 0, 24, 1, eq_tlv), | ||
137 | |||
138 | SOC_ENUM("EQ5 Cut Off", eq5), | ||
139 | SOC_SINGLE_TLV("EQ5 Volume", WM8978_EQ5, 0, 24, 1, eq_tlv), | ||
140 | |||
141 | SOC_SINGLE("DAC Playback Limiter Switch", | ||
142 | WM8978_DAC_LIMITER_1, 8, 1, 0), | ||
143 | SOC_SINGLE("DAC Playback Limiter Decay", | ||
144 | WM8978_DAC_LIMITER_1, 4, 15, 0), | ||
145 | SOC_SINGLE("DAC Playback Limiter Attack", | ||
146 | WM8978_DAC_LIMITER_1, 0, 15, 0), | ||
147 | |||
148 | SOC_SINGLE("DAC Playback Limiter Threshold", | ||
149 | WM8978_DAC_LIMITER_2, 4, 7, 0), | ||
150 | SOC_SINGLE("DAC Playback Limiter Boost", | ||
151 | WM8978_DAC_LIMITER_2, 0, 15, 0), | ||
152 | |||
153 | SOC_ENUM("ALC Enable Switch", alc1), | ||
154 | SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), | ||
155 | SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), | ||
156 | |||
157 | SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 7, 0), | ||
158 | SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), | ||
159 | |||
160 | SOC_ENUM("ALC Capture Mode", alc3), | ||
161 | SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 15, 0), | ||
162 | SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 15, 0), | ||
163 | |||
164 | SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), | ||
165 | SOC_SINGLE("ALC Capture Noise Gate Threshold", | ||
166 | WM8978_NOISE_GATE, 0, 7, 0), | ||
167 | |||
168 | SOC_DOUBLE_R("Capture PGA ZC Switch", | ||
169 | WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL, | ||
170 | 7, 1, 0), | ||
171 | |||
172 | /* OUT1 - Headphones */ | ||
173 | SOC_DOUBLE_R("Headphone Playback ZC Switch", | ||
174 | WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 7, 1, 0), | ||
175 | |||
176 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", | ||
177 | WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, | ||
178 | 0, 63, 0, spk_tlv), | ||
179 | |||
180 | /* OUT2 - Speakers */ | ||
181 | SOC_DOUBLE_R("Speaker Playback ZC Switch", | ||
182 | WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 7, 1, 0), | ||
183 | |||
184 | SOC_DOUBLE_R_TLV("Speaker Playback Volume", | ||
185 | WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, | ||
186 | 0, 63, 0, spk_tlv), | ||
187 | |||
188 | /* OUT3/4 - Line Output */ | ||
189 | SOC_DOUBLE_R("Line Playback Switch", | ||
190 | WM8978_OUT3_MIXER_CONTROL, WM8978_OUT4_MIXER_CONTROL, 6, 1, 1), | ||
191 | |||
192 | /* Mixer #3: Boost (Input) mixer */ | ||
193 | SOC_DOUBLE_R("PGA Boost (+20dB)", | ||
194 | WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, | ||
195 | 8, 1, 0), | ||
196 | SOC_DOUBLE_R_TLV("L2/R2 Boost Volume", | ||
197 | WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, | ||
198 | 4, 7, 0, boost_tlv), | ||
199 | SOC_DOUBLE_R_TLV("Aux Boost Volume", | ||
200 | WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, | ||
201 | 0, 7, 0, boost_tlv), | ||
202 | |||
203 | /* Input PGA volume */ | ||
204 | SOC_DOUBLE_R_TLV("Input PGA Volume", | ||
205 | WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL, | ||
206 | 0, 63, 0, inpga_tlv), | ||
207 | |||
208 | /* Headphone */ | ||
209 | SOC_DOUBLE_R("Headphone Switch", | ||
210 | WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 6, 1, 1), | ||
211 | |||
212 | /* Speaker */ | ||
213 | SOC_DOUBLE_R("Speaker Switch", | ||
214 | WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), | ||
215 | |||
216 | /* DAC / ADC oversampling */ | ||
217 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, 8, 1, 0), | ||
218 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, 8, 1, 0), | ||
219 | }; | ||
220 | |||
221 | /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ | ||
222 | static const struct snd_kcontrol_new wm8978_left_out_mixer[] = { | ||
223 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_LEFT_MIXER_CONTROL, 1, 1, 0), | ||
224 | SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_LEFT_MIXER_CONTROL, 5, 1, 0), | ||
225 | SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_LEFT_MIXER_CONTROL, 0, 1, 0), | ||
226 | }; | ||
227 | |||
228 | static const struct snd_kcontrol_new wm8978_right_out_mixer[] = { | ||
229 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_RIGHT_MIXER_CONTROL, 1, 1, 0), | ||
230 | SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 5, 1, 0), | ||
231 | SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 0, 1, 0), | ||
232 | }; | ||
233 | |||
234 | /* OUT3/OUT4 Mixer not implemented */ | ||
235 | |||
236 | /* Mixer #2: Input PGA Mute */ | ||
237 | static const struct snd_kcontrol_new wm8978_left_input_mixer[] = { | ||
238 | SOC_DAPM_SINGLE("L2 Switch", WM8978_INPUT_CONTROL, 2, 1, 0), | ||
239 | SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 1, 1, 0), | ||
240 | SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 0, 1, 0), | ||
241 | }; | ||
242 | static const struct snd_kcontrol_new wm8978_right_input_mixer[] = { | ||
243 | SOC_DAPM_SINGLE("R2 Switch", WM8978_INPUT_CONTROL, 6, 1, 0), | ||
244 | SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 5, 1, 0), | ||
245 | SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 4, 1, 0), | ||
246 | }; | ||
247 | |||
248 | static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = { | ||
249 | SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", | ||
250 | WM8978_POWER_MANAGEMENT_3, 0, 0), | ||
251 | SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", | ||
252 | WM8978_POWER_MANAGEMENT_3, 1, 0), | ||
253 | SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", | ||
254 | WM8978_POWER_MANAGEMENT_2, 0, 0), | ||
255 | SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", | ||
256 | WM8978_POWER_MANAGEMENT_2, 1, 0), | ||
257 | |||
258 | /* Mixer #1: OUT1,2 */ | ||
259 | SOC_MIXER_ARRAY("Left Output Mixer", WM8978_POWER_MANAGEMENT_3, | ||
260 | 2, 0, wm8978_left_out_mixer), | ||
261 | SOC_MIXER_ARRAY("Right Output Mixer", WM8978_POWER_MANAGEMENT_3, | ||
262 | 3, 0, wm8978_right_out_mixer), | ||
263 | |||
264 | SOC_MIXER_ARRAY("Left Input Mixer", WM8978_POWER_MANAGEMENT_2, | ||
265 | 2, 0, wm8978_left_input_mixer), | ||
266 | SOC_MIXER_ARRAY("Right Input Mixer", WM8978_POWER_MANAGEMENT_2, | ||
267 | 3, 0, wm8978_right_input_mixer), | ||
268 | |||
269 | SND_SOC_DAPM_PGA("Left Boost Mixer", WM8978_POWER_MANAGEMENT_2, | ||
270 | 4, 0, NULL, 0), | ||
271 | SND_SOC_DAPM_PGA("Right Boost Mixer", WM8978_POWER_MANAGEMENT_2, | ||
272 | 5, 0, NULL, 0), | ||
273 | |||
274 | SND_SOC_DAPM_PGA("Left Capture PGA", WM8978_LEFT_INP_PGA_CONTROL, | ||
275 | 6, 1, NULL, 0), | ||
276 | SND_SOC_DAPM_PGA("Right Capture PGA", WM8978_RIGHT_INP_PGA_CONTROL, | ||
277 | 6, 1, NULL, 0), | ||
278 | |||
279 | SND_SOC_DAPM_PGA("Left Headphone Out", WM8978_POWER_MANAGEMENT_2, | ||
280 | 7, 0, NULL, 0), | ||
281 | SND_SOC_DAPM_PGA("Right Headphone Out", WM8978_POWER_MANAGEMENT_2, | ||
282 | 8, 0, NULL, 0), | ||
283 | |||
284 | SND_SOC_DAPM_PGA("Left Speaker Out", WM8978_POWER_MANAGEMENT_3, | ||
285 | 6, 0, NULL, 0), | ||
286 | SND_SOC_DAPM_PGA("Right Speaker Out", WM8978_POWER_MANAGEMENT_3, | ||
287 | 5, 0, NULL, 0), | ||
288 | |||
289 | SND_SOC_DAPM_MIXER("OUT4 VMID", WM8978_POWER_MANAGEMENT_3, | ||
290 | 8, 0, NULL, 0), | ||
291 | |||
292 | SND_SOC_DAPM_MICBIAS("Mic Bias", WM8978_POWER_MANAGEMENT_1, 4, 0), | ||
293 | |||
294 | SND_SOC_DAPM_INPUT("LMICN"), | ||
295 | SND_SOC_DAPM_INPUT("LMICP"), | ||
296 | SND_SOC_DAPM_INPUT("RMICN"), | ||
297 | SND_SOC_DAPM_INPUT("RMICP"), | ||
298 | SND_SOC_DAPM_INPUT("LAUX"), | ||
299 | SND_SOC_DAPM_INPUT("RAUX"), | ||
300 | SND_SOC_DAPM_INPUT("L2"), | ||
301 | SND_SOC_DAPM_INPUT("R2"), | ||
302 | SND_SOC_DAPM_OUTPUT("LHP"), | ||
303 | SND_SOC_DAPM_OUTPUT("RHP"), | ||
304 | SND_SOC_DAPM_OUTPUT("LSPK"), | ||
305 | SND_SOC_DAPM_OUTPUT("RSPK"), | ||
306 | }; | ||
307 | |||
308 | static const struct snd_soc_dapm_route audio_map[] = { | ||
309 | /* Output mixer */ | ||
310 | {"Right Output Mixer", "PCM Playback Switch", "Right DAC"}, | ||
311 | {"Right Output Mixer", "Aux Playback Switch", "RAUX"}, | ||
312 | {"Right Output Mixer", "Line Bypass Switch", "Right Boost Mixer"}, | ||
313 | |||
314 | {"Left Output Mixer", "PCM Playback Switch", "Left DAC"}, | ||
315 | {"Left Output Mixer", "Aux Playback Switch", "LAUX"}, | ||
316 | {"Left Output Mixer", "Line Bypass Switch", "Left Boost Mixer"}, | ||
317 | |||
318 | /* Outputs */ | ||
319 | {"Right Headphone Out", NULL, "Right Output Mixer"}, | ||
320 | {"RHP", NULL, "Right Headphone Out"}, | ||
321 | |||
322 | {"Left Headphone Out", NULL, "Left Output Mixer"}, | ||
323 | {"LHP", NULL, "Left Headphone Out"}, | ||
324 | |||
325 | {"Right Speaker Out", NULL, "Right Output Mixer"}, | ||
326 | {"RSPK", NULL, "Right Speaker Out"}, | ||
327 | |||
328 | {"Left Speaker Out", NULL, "Left Output Mixer"}, | ||
329 | {"LSPK", NULL, "Left Speaker Out"}, | ||
330 | |||
331 | /* Boost Mixer */ | ||
332 | {"Right ADC", NULL, "Right Boost Mixer"}, | ||
333 | |||
334 | {"Right Boost Mixer", NULL, "RAUX"}, | ||
335 | {"Right Boost Mixer", NULL, "Right Capture PGA"}, | ||
336 | {"Right Boost Mixer", NULL, "R2"}, | ||
337 | |||
338 | {"Left ADC", NULL, "Left Boost Mixer"}, | ||
339 | |||
340 | {"Left Boost Mixer", NULL, "LAUX"}, | ||
341 | {"Left Boost Mixer", NULL, "Left Capture PGA"}, | ||
342 | {"Left Boost Mixer", NULL, "L2"}, | ||
343 | |||
344 | /* Input PGA */ | ||
345 | {"Right Capture PGA", NULL, "Right Input Mixer"}, | ||
346 | {"Left Capture PGA", NULL, "Left Input Mixer"}, | ||
347 | |||
348 | {"Right Input Mixer", "R2 Switch", "R2"}, | ||
349 | {"Right Input Mixer", "MicN Switch", "RMICN"}, | ||
350 | {"Right Input Mixer", "MicP Switch", "RMICP"}, | ||
351 | |||
352 | {"Left Input Mixer", "L2 Switch", "L2"}, | ||
353 | {"Left Input Mixer", "MicN Switch", "LMICN"}, | ||
354 | {"Left Input Mixer", "MicP Switch", "LMICP"}, | ||
355 | }; | ||
356 | |||
357 | static int wm8978_add_widgets(struct snd_soc_codec *codec) | ||
358 | { | ||
359 | snd_soc_dapm_new_controls(codec, wm8978_dapm_widgets, | ||
360 | ARRAY_SIZE(wm8978_dapm_widgets)); | ||
361 | |||
362 | /* set up the WM8978 audio map */ | ||
363 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /* PLL divisors */ | ||
369 | struct wm8978_pll_div { | ||
370 | u32 k; | ||
371 | u8 n; | ||
372 | u8 div2; | ||
373 | }; | ||
374 | |||
375 | #define FIXED_PLL_SIZE (1 << 24) | ||
376 | |||
377 | static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, | ||
378 | unsigned int source) | ||
379 | { | ||
380 | u64 k_part; | ||
381 | unsigned int k, n_div, n_mod; | ||
382 | |||
383 | n_div = target / source; | ||
384 | if (n_div < 6) { | ||
385 | source >>= 1; | ||
386 | pll_div->div2 = 1; | ||
387 | n_div = target / source; | ||
388 | } else { | ||
389 | pll_div->div2 = 0; | ||
390 | } | ||
391 | |||
392 | if (n_div < 6 || n_div > 12) | ||
393 | dev_warn(wm8978_codec->dev, | ||
394 | "WM8978 N value exceeds recommended range! N = %u\n", | ||
395 | n_div); | ||
396 | |||
397 | pll_div->n = n_div; | ||
398 | n_mod = target - source * n_div; | ||
399 | k_part = FIXED_PLL_SIZE * (long long)n_mod + source / 2; | ||
400 | |||
401 | do_div(k_part, source); | ||
402 | |||
403 | k = k_part & 0xFFFFFFFF; | ||
404 | |||
405 | pll_div->k = k; | ||
406 | } | ||
407 | |||
408 | /* MCLK dividers */ | ||
409 | static const int mclk_numerator[] = {1, 3, 2, 3, 4, 6, 8, 12}; | ||
410 | static const int mclk_denominator[] = {1, 2, 1, 1, 1, 1, 1, 1}; | ||
411 | |||
412 | /* | ||
413 | * find index >= idx, such that, for a given f_out, | ||
414 | * 3 * f_mclk / 4 <= f_PLLOUT < 13 * f_mclk / 4 | ||
415 | * f_out can be f_256fs or f_opclk, currently only used for f_256fs. Can be | ||
416 | * generalised for f_opclk with suitable coefficient arrays, but currently | ||
417 | * the OPCLK divisor is calculated directly, not iteratively. | ||
418 | */ | ||
419 | static int wm8978_enum_mclk(unsigned int f_out, unsigned int f_mclk, | ||
420 | unsigned int *f_pllout) | ||
421 | { | ||
422 | int i; | ||
423 | |||
424 | for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) { | ||
425 | unsigned int f_pllout_x4 = 4 * f_out * mclk_numerator[i] / | ||
426 | mclk_denominator[i]; | ||
427 | if (3 * f_mclk <= f_pllout_x4 && f_pllout_x4 < 13 * f_mclk) { | ||
428 | *f_pllout = f_pllout_x4 / 4; | ||
429 | return i; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | /* | ||
437 | * Calculate internal frequencies and dividers, according to Figure 40 | ||
438 | * "PLL and Clock Select Circuit" in WM8978 datasheet Rev. 2.6 | ||
439 | */ | ||
440 | static int wm8978_configure_pll(struct snd_soc_codec *codec) | ||
441 | { | ||
442 | struct wm8978_priv *wm8978 = codec->private_data; | ||
443 | struct wm8978_pll_div pll_div; | ||
444 | unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk, | ||
445 | f_256fs = wm8978->f_256fs; | ||
446 | unsigned int f2; | ||
447 | |||
448 | if (!f_mclk) | ||
449 | return -EINVAL; | ||
450 | |||
451 | if (f_opclk) { | ||
452 | unsigned int opclk_div; | ||
453 | /* Cannot set up MCLK divider now, do later */ | ||
454 | wm8978->mclk_idx = -1; | ||
455 | |||
456 | /* | ||
457 | * The user needs OPCLK. Choose OPCLKDIV to put | ||
458 | * 6 <= R = f2 / f1 < 13, 1 <= OPCLKDIV <= 4. | ||
459 | * f_opclk = f_mclk * prescale * R / 4 / OPCLKDIV, where | ||
460 | * prescale = 1, or prescale = 2. Prescale is calculated inside | ||
461 | * pll_factors(). We have to select f_PLLOUT, such that | ||
462 | * f_mclk * 3 / 4 <= f_PLLOUT < f_mclk * 13 / 4. Must be | ||
463 | * f_mclk * 3 / 16 <= f_opclk < f_mclk * 13 / 4. | ||
464 | */ | ||
465 | if (16 * f_opclk < 3 * f_mclk || 4 * f_opclk >= 13 * f_mclk) | ||
466 | return -EINVAL; | ||
467 | |||
468 | if (4 * f_opclk < 3 * f_mclk) | ||
469 | /* Have to use OPCLKDIV */ | ||
470 | opclk_div = (3 * f_mclk / 4 + f_opclk - 1) / f_opclk; | ||
471 | else | ||
472 | opclk_div = 1; | ||
473 | |||
474 | dev_dbg(codec->dev, "%s: OPCLKDIV=%d\n", __func__, opclk_div); | ||
475 | |||
476 | snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 0x30, | ||
477 | (opclk_div - 1) << 4); | ||
478 | |||
479 | wm8978->f_pllout = f_opclk * opclk_div; | ||
480 | } else if (f_256fs) { | ||
481 | /* | ||
482 | * Not using OPCLK, but PLL is used for the codec, choose R: | ||
483 | * 6 <= R = f2 / f1 < 13, to put 1 <= MCLKDIV <= 12. | ||
484 | * f_256fs = f_mclk * prescale * R / 4 / MCLKDIV, where | ||
485 | * prescale = 1, or prescale = 2. Prescale is calculated inside | ||
486 | * pll_factors(). We have to select f_PLLOUT, such that | ||
487 | * f_mclk * 3 / 4 <= f_PLLOUT < f_mclk * 13 / 4. Must be | ||
488 | * f_mclk * 3 / 48 <= f_256fs < f_mclk * 13 / 4. This means MCLK | ||
489 | * must be 3.781MHz <= f_MCLK <= 32.768MHz | ||
490 | */ | ||
491 | int idx = wm8978_enum_mclk(f_256fs, f_mclk, &wm8978->f_pllout); | ||
492 | if (idx < 0) | ||
493 | return idx; | ||
494 | |||
495 | wm8978->mclk_idx = idx; | ||
496 | |||
497 | /* GPIO1 into default mode as input - before configuring PLL */ | ||
498 | snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0); | ||
499 | } else { | ||
500 | return -EINVAL; | ||
501 | } | ||
502 | |||
503 | f2 = wm8978->f_pllout * 4; | ||
504 | |||
505 | dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, | ||
506 | wm8978->f_mclk, wm8978->f_pllout); | ||
507 | |||
508 | pll_factors(&pll_div, f2, wm8978->f_mclk); | ||
509 | |||
510 | dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", | ||
511 | __func__, pll_div.n, pll_div.k, pll_div.div2); | ||
512 | |||
513 | /* Turn PLL off for configuration... */ | ||
514 | snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0); | ||
515 | |||
516 | snd_soc_write(codec, WM8978_PLL_N, (pll_div.div2 << 4) | pll_div.n); | ||
517 | snd_soc_write(codec, WM8978_PLL_K1, pll_div.k >> 18); | ||
518 | snd_soc_write(codec, WM8978_PLL_K2, (pll_div.k >> 9) & 0x1ff); | ||
519 | snd_soc_write(codec, WM8978_PLL_K3, pll_div.k & 0x1ff); | ||
520 | |||
521 | /* ...and on again */ | ||
522 | snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20); | ||
523 | |||
524 | if (f_opclk) | ||
525 | /* Output PLL (OPCLK) to GPIO1 */ | ||
526 | snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 4); | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Configure WM8978 clock dividers. | ||
533 | */ | ||
534 | static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | ||
535 | int div_id, int div) | ||
536 | { | ||
537 | struct snd_soc_codec *codec = codec_dai->codec; | ||
538 | struct wm8978_priv *wm8978 = codec->private_data; | ||
539 | int ret = 0; | ||
540 | |||
541 | switch (div_id) { | ||
542 | case WM8978_OPCLKRATE: | ||
543 | wm8978->f_opclk = div; | ||
544 | |||
545 | if (wm8978->f_mclk) | ||
546 | /* | ||
547 | * We know the MCLK frequency, the user has requested | ||
548 | * OPCLK, configure the PLL based on that and start it | ||
549 | * and OPCLK immediately. We will configure PLL to match | ||
550 | * user-requested OPCLK frquency as good as possible. | ||
551 | * In fact, it is likely, that matching the sampling | ||
552 | * rate, when it becomes known, is more important, and | ||
553 | * we will not be reconfiguring PLL then, because we | ||
554 | * must not interrupt OPCLK. But it should be fine, | ||
555 | * because typically the user will request OPCLK to run | ||
556 | * at 256fs or 512fs, and for these cases we will also | ||
557 | * find an exact MCLK divider configuration - it will | ||
558 | * be equal to or double the OPCLK divisor. | ||
559 | */ | ||
560 | ret = wm8978_configure_pll(codec); | ||
561 | break; | ||
562 | case WM8978_BCLKDIV: | ||
563 | if (div & ~0x1c) | ||
564 | return -EINVAL; | ||
565 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0x1c, div); | ||
566 | break; | ||
567 | default: | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | dev_dbg(codec->dev, "%s: ID %d, value %u\n", __func__, div_id, div); | ||
572 | |||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | /* | ||
577 | * @freq: when .set_pll() us not used, freq is codec MCLK input frequency | ||
578 | */ | ||
579 | static int wm8978_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, | ||
580 | unsigned int freq, int dir) | ||
581 | { | ||
582 | struct snd_soc_codec *codec = codec_dai->codec; | ||
583 | struct wm8978_priv *wm8978 = codec->private_data; | ||
584 | int ret = 0; | ||
585 | |||
586 | dev_dbg(codec->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq); | ||
587 | |||
588 | if (freq) { | ||
589 | wm8978->f_mclk = freq; | ||
590 | |||
591 | /* Even if MCLK is used for system clock, might have to drive OPCLK */ | ||
592 | if (wm8978->f_opclk) | ||
593 | ret = wm8978_configure_pll(codec); | ||
594 | |||
595 | /* Our sysclk is fixed to 256 * fs, will configure in .hw_params() */ | ||
596 | |||
597 | if (!ret) | ||
598 | wm8978->sysclk = clk_id; | ||
599 | } | ||
600 | |||
601 | if (wm8978->sysclk == WM8978_PLL && (!freq || clk_id == WM8978_MCLK)) { | ||
602 | /* Clock CODEC directly from MCLK */ | ||
603 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0x100, 0); | ||
604 | |||
605 | /* GPIO1 into default mode as input - before configuring PLL */ | ||
606 | snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0); | ||
607 | |||
608 | /* Turn off PLL */ | ||
609 | snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0); | ||
610 | wm8978->sysclk = WM8978_MCLK; | ||
611 | wm8978->f_pllout = 0; | ||
612 | wm8978->f_opclk = 0; | ||
613 | } | ||
614 | |||
615 | return ret; | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * Set ADC and Voice DAC format. | ||
620 | */ | ||
621 | static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
622 | { | ||
623 | struct snd_soc_codec *codec = codec_dai->codec; | ||
624 | /* | ||
625 | * BCLK polarity mask = 0x100, LRC clock polarity mask = 0x80, | ||
626 | * Data Format mask = 0x18: all will be calculated anew | ||
627 | */ | ||
628 | u16 iface = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x198; | ||
629 | u16 clk = snd_soc_read(codec, WM8978_CLOCKING); | ||
630 | |||
631 | dev_dbg(codec->dev, "%s\n", __func__); | ||
632 | |||
633 | /* set master/slave audio interface */ | ||
634 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
635 | case SND_SOC_DAIFMT_CBM_CFM: | ||
636 | clk |= 1; | ||
637 | break; | ||
638 | case SND_SOC_DAIFMT_CBS_CFS: | ||
639 | clk &= ~1; | ||
640 | break; | ||
641 | default: | ||
642 | return -EINVAL; | ||
643 | } | ||
644 | |||
645 | /* interface format */ | ||
646 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
647 | case SND_SOC_DAIFMT_I2S: | ||
648 | iface |= 0x10; | ||
649 | break; | ||
650 | case SND_SOC_DAIFMT_RIGHT_J: | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_LEFT_J: | ||
653 | iface |= 0x8; | ||
654 | break; | ||
655 | case SND_SOC_DAIFMT_DSP_A: | ||
656 | iface |= 0x18; | ||
657 | break; | ||
658 | default: | ||
659 | return -EINVAL; | ||
660 | } | ||
661 | |||
662 | /* clock inversion */ | ||
663 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
664 | case SND_SOC_DAIFMT_NB_NF: | ||
665 | break; | ||
666 | case SND_SOC_DAIFMT_IB_IF: | ||
667 | iface |= 0x180; | ||
668 | break; | ||
669 | case SND_SOC_DAIFMT_IB_NF: | ||
670 | iface |= 0x100; | ||
671 | break; | ||
672 | case SND_SOC_DAIFMT_NB_IF: | ||
673 | iface |= 0x80; | ||
674 | break; | ||
675 | default: | ||
676 | return -EINVAL; | ||
677 | } | ||
678 | |||
679 | snd_soc_write(codec, WM8978_AUDIO_INTERFACE, iface); | ||
680 | snd_soc_write(codec, WM8978_CLOCKING, clk); | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | /* | ||
686 | * Set PCM DAI bit size and sample rate. | ||
687 | */ | ||
688 | static int wm8978_hw_params(struct snd_pcm_substream *substream, | ||
689 | struct snd_pcm_hw_params *params, | ||
690 | struct snd_soc_dai *dai) | ||
691 | { | ||
692 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
693 | struct snd_soc_device *socdev = rtd->socdev; | ||
694 | struct snd_soc_codec *codec = socdev->card->codec; | ||
695 | struct wm8978_priv *wm8978 = codec->private_data; | ||
696 | /* Word length mask = 0x60 */ | ||
697 | u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; | ||
698 | /* Sampling rate mask = 0xe (for filters) */ | ||
699 | u16 add_ctl = snd_soc_read(codec, WM8978_ADDITIONAL_CONTROL) & ~0xe; | ||
700 | u16 clking = snd_soc_read(codec, WM8978_CLOCKING); | ||
701 | enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? | ||
702 | WM8978_PLL : WM8978_MCLK; | ||
703 | unsigned int f_sel, diff, diff_best = INT_MAX; | ||
704 | int i, best = 0; | ||
705 | |||
706 | if (!wm8978->f_mclk) | ||
707 | return -EINVAL; | ||
708 | |||
709 | /* bit size */ | ||
710 | switch (params_format(params)) { | ||
711 | case SNDRV_PCM_FORMAT_S16_LE: | ||
712 | break; | ||
713 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
714 | iface_ctl |= 0x20; | ||
715 | break; | ||
716 | case SNDRV_PCM_FORMAT_S24_LE: | ||
717 | iface_ctl |= 0x40; | ||
718 | break; | ||
719 | case SNDRV_PCM_FORMAT_S32_LE: | ||
720 | iface_ctl |= 0x60; | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | /* filter coefficient */ | ||
725 | switch (params_rate(params)) { | ||
726 | case 8000: | ||
727 | add_ctl |= 0x5 << 1; | ||
728 | break; | ||
729 | case 11025: | ||
730 | add_ctl |= 0x4 << 1; | ||
731 | break; | ||
732 | case 16000: | ||
733 | add_ctl |= 0x3 << 1; | ||
734 | break; | ||
735 | case 22050: | ||
736 | add_ctl |= 0x2 << 1; | ||
737 | break; | ||
738 | case 32000: | ||
739 | add_ctl |= 0x1 << 1; | ||
740 | break; | ||
741 | case 44100: | ||
742 | case 48000: | ||
743 | break; | ||
744 | } | ||
745 | |||
746 | /* Sampling rate is known now, can configure the MCLK divider */ | ||
747 | wm8978->f_256fs = params_rate(params) * 256; | ||
748 | |||
749 | if (wm8978->sysclk == WM8978_MCLK) { | ||
750 | wm8978->mclk_idx = -1; | ||
751 | f_sel = wm8978->f_mclk; | ||
752 | } else { | ||
753 | if (!wm8978->f_pllout) { | ||
754 | /* We only enter here, if OPCLK is not used */ | ||
755 | int ret = wm8978_configure_pll(codec); | ||
756 | if (ret < 0) | ||
757 | return ret; | ||
758 | } | ||
759 | f_sel = wm8978->f_pllout; | ||
760 | } | ||
761 | |||
762 | if (wm8978->mclk_idx < 0) { | ||
763 | /* Either MCLK is used directly, or OPCLK is used */ | ||
764 | if (f_sel < wm8978->f_256fs || f_sel > 12 * wm8978->f_256fs) | ||
765 | return -EINVAL; | ||
766 | |||
767 | for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) { | ||
768 | diff = abs(wm8978->f_256fs * 3 - | ||
769 | f_sel * 3 * mclk_denominator[i] / mclk_numerator[i]); | ||
770 | |||
771 | if (diff < diff_best) { | ||
772 | diff_best = diff; | ||
773 | best = i; | ||
774 | } | ||
775 | |||
776 | if (!diff) | ||
777 | break; | ||
778 | } | ||
779 | } else { | ||
780 | /* OPCLK not used, codec driven by PLL */ | ||
781 | best = wm8978->mclk_idx; | ||
782 | diff = 0; | ||
783 | } | ||
784 | |||
785 | if (diff) | ||
786 | dev_warn(codec->dev, "Imprecise sampling rate: %uHz%s\n", | ||
787 | f_sel * mclk_denominator[best] / mclk_numerator[best] / 256, | ||
788 | wm8978->sysclk == WM8978_MCLK ? | ||
789 | ", consider using PLL" : ""); | ||
790 | |||
791 | dev_dbg(codec->dev, "%s: fmt %d, rate %u, MCLK divisor #%d\n", __func__, | ||
792 | params_format(params), params_rate(params), best); | ||
793 | |||
794 | /* MCLK divisor mask = 0xe0 */ | ||
795 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, best << 5); | ||
796 | |||
797 | snd_soc_write(codec, WM8978_AUDIO_INTERFACE, iface_ctl); | ||
798 | snd_soc_write(codec, WM8978_ADDITIONAL_CONTROL, add_ctl); | ||
799 | |||
800 | if (wm8978->sysclk != current_clk_id) { | ||
801 | if (wm8978->sysclk == WM8978_PLL) | ||
802 | /* Run CODEC from PLL instead of MCLK */ | ||
803 | snd_soc_update_bits(codec, WM8978_CLOCKING, | ||
804 | 0x100, 0x100); | ||
805 | else | ||
806 | /* Clock CODEC directly from MCLK */ | ||
807 | snd_soc_update_bits(codec, WM8978_CLOCKING, 0x100, 0); | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int wm8978_mute(struct snd_soc_dai *dai, int mute) | ||
814 | { | ||
815 | struct snd_soc_codec *codec = dai->codec; | ||
816 | |||
817 | dev_dbg(codec->dev, "%s: %d\n", __func__, mute); | ||
818 | |||
819 | if (mute) | ||
820 | snd_soc_update_bits(codec, WM8978_DAC_CONTROL, 0x40, 0x40); | ||
821 | else | ||
822 | snd_soc_update_bits(codec, WM8978_DAC_CONTROL, 0x40, 0); | ||
823 | |||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | static int wm8978_set_bias_level(struct snd_soc_codec *codec, | ||
828 | enum snd_soc_bias_level level) | ||
829 | { | ||
830 | u16 power1 = snd_soc_read(codec, WM8978_POWER_MANAGEMENT_1) & ~3; | ||
831 | |||
832 | switch (level) { | ||
833 | case SND_SOC_BIAS_ON: | ||
834 | case SND_SOC_BIAS_PREPARE: | ||
835 | power1 |= 1; /* VMID 75k */ | ||
836 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, power1); | ||
837 | break; | ||
838 | case SND_SOC_BIAS_STANDBY: | ||
839 | /* bit 3: enable bias, bit 2: enable I/O tie off buffer */ | ||
840 | power1 |= 0xc; | ||
841 | |||
842 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
843 | /* Initial cap charge at VMID 5k */ | ||
844 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, | ||
845 | power1 | 0x3); | ||
846 | mdelay(100); | ||
847 | } | ||
848 | |||
849 | power1 |= 0x2; /* VMID 500k */ | ||
850 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, power1); | ||
851 | break; | ||
852 | case SND_SOC_BIAS_OFF: | ||
853 | /* Preserve PLL - OPCLK may be used by someone */ | ||
854 | snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, ~0x20, 0); | ||
855 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_2, 0); | ||
856 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_3, 0); | ||
857 | break; | ||
858 | } | ||
859 | |||
860 | dev_dbg(codec->dev, "%s: %d, %x\n", __func__, level, power1); | ||
861 | |||
862 | codec->bias_level = level; | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | #define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
867 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
868 | |||
869 | static struct snd_soc_dai_ops wm8978_dai_ops = { | ||
870 | .hw_params = wm8978_hw_params, | ||
871 | .digital_mute = wm8978_mute, | ||
872 | .set_fmt = wm8978_set_dai_fmt, | ||
873 | .set_clkdiv = wm8978_set_dai_clkdiv, | ||
874 | .set_sysclk = wm8978_set_dai_sysclk, | ||
875 | }; | ||
876 | |||
877 | /* Also supports 12kHz */ | ||
878 | struct snd_soc_dai wm8978_dai = { | ||
879 | .name = "WM8978 HiFi", | ||
880 | .id = 1, | ||
881 | .playback = { | ||
882 | .stream_name = "Playback", | ||
883 | .channels_min = 1, | ||
884 | .channels_max = 2, | ||
885 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
886 | .formats = WM8978_FORMATS, | ||
887 | }, | ||
888 | .capture = { | ||
889 | .stream_name = "Capture", | ||
890 | .channels_min = 1, | ||
891 | .channels_max = 2, | ||
892 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
893 | .formats = WM8978_FORMATS, | ||
894 | }, | ||
895 | .ops = &wm8978_dai_ops, | ||
896 | }; | ||
897 | EXPORT_SYMBOL_GPL(wm8978_dai); | ||
898 | |||
899 | static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) | ||
900 | { | ||
901 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
902 | struct snd_soc_codec *codec = socdev->card->codec; | ||
903 | |||
904 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
905 | /* Also switch PLL off */ | ||
906 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static int wm8978_resume(struct platform_device *pdev) | ||
912 | { | ||
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec = socdev->card->codec; | ||
915 | struct wm8978_priv *wm8978 = codec->private_data; | ||
916 | int i; | ||
917 | u16 *cache = codec->reg_cache; | ||
918 | |||
919 | /* Sync reg_cache with the hardware */ | ||
920 | for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) { | ||
921 | if (i == WM8978_RESET) | ||
922 | continue; | ||
923 | if (cache[i] != wm8978_reg[i]) | ||
924 | snd_soc_write(codec, i, cache[i]); | ||
925 | } | ||
926 | |||
927 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
928 | |||
929 | if (wm8978->f_pllout) | ||
930 | /* Switch PLL on */ | ||
931 | snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static int wm8978_probe(struct platform_device *pdev) | ||
937 | { | ||
938 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
939 | struct snd_soc_codec *codec; | ||
940 | int ret = 0; | ||
941 | |||
942 | if (wm8978_codec == NULL) { | ||
943 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
944 | return -ENODEV; | ||
945 | } | ||
946 | |||
947 | socdev->card->codec = wm8978_codec; | ||
948 | codec = wm8978_codec; | ||
949 | |||
950 | /* register pcms */ | ||
951 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
952 | if (ret < 0) { | ||
953 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
954 | goto pcm_err; | ||
955 | } | ||
956 | |||
957 | snd_soc_add_controls(codec, wm8978_snd_controls, | ||
958 | ARRAY_SIZE(wm8978_snd_controls)); | ||
959 | wm8978_add_widgets(codec); | ||
960 | |||
961 | pcm_err: | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | /* power down chip */ | ||
966 | static int wm8978_remove(struct platform_device *pdev) | ||
967 | { | ||
968 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
969 | |||
970 | snd_soc_free_pcms(socdev); | ||
971 | snd_soc_dapm_free(socdev); | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | struct snd_soc_codec_device soc_codec_dev_wm8978 = { | ||
977 | .probe = wm8978_probe, | ||
978 | .remove = wm8978_remove, | ||
979 | .suspend = wm8978_suspend, | ||
980 | .resume = wm8978_resume, | ||
981 | }; | ||
982 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978); | ||
983 | |||
984 | /* | ||
985 | * These registers contain an "update" bit - bit 8. This means, for example, | ||
986 | * that one can write new DAC digital volume for both channels, but only when | ||
987 | * the update bit is set, will also the volume be updated - simultaneously for | ||
988 | * both channels. | ||
989 | */ | ||
990 | static const int update_reg[] = { | ||
991 | WM8978_LEFT_DAC_DIGITAL_VOLUME, | ||
992 | WM8978_RIGHT_DAC_DIGITAL_VOLUME, | ||
993 | WM8978_LEFT_ADC_DIGITAL_VOLUME, | ||
994 | WM8978_RIGHT_ADC_DIGITAL_VOLUME, | ||
995 | WM8978_LEFT_INP_PGA_CONTROL, | ||
996 | WM8978_RIGHT_INP_PGA_CONTROL, | ||
997 | WM8978_LOUT1_HP_CONTROL, | ||
998 | WM8978_ROUT1_HP_CONTROL, | ||
999 | WM8978_LOUT2_SPK_CONTROL, | ||
1000 | WM8978_ROUT2_SPK_CONTROL, | ||
1001 | }; | ||
1002 | |||
1003 | static __devinit int wm8978_register(struct wm8978_priv *wm8978) | ||
1004 | { | ||
1005 | int ret, i; | ||
1006 | struct snd_soc_codec *codec = &wm8978->codec; | ||
1007 | |||
1008 | if (wm8978_codec) { | ||
1009 | dev_err(codec->dev, "Another WM8978 is registered\n"); | ||
1010 | return -EINVAL; | ||
1011 | } | ||
1012 | |||
1013 | /* | ||
1014 | * Set default system clock to PLL, it is more precise, this is also the | ||
1015 | * default hardware setting | ||
1016 | */ | ||
1017 | wm8978->sysclk = WM8978_PLL; | ||
1018 | |||
1019 | mutex_init(&codec->mutex); | ||
1020 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1021 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1022 | |||
1023 | codec->private_data = wm8978; | ||
1024 | codec->name = "WM8978"; | ||
1025 | codec->owner = THIS_MODULE; | ||
1026 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1027 | codec->set_bias_level = wm8978_set_bias_level; | ||
1028 | codec->dai = &wm8978_dai; | ||
1029 | codec->num_dai = 1; | ||
1030 | codec->reg_cache_size = WM8978_CACHEREGNUM; | ||
1031 | codec->reg_cache = &wm8978->reg_cache; | ||
1032 | |||
1033 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | ||
1034 | if (ret < 0) { | ||
1035 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1036 | goto err; | ||
1037 | } | ||
1038 | |||
1039 | memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg)); | ||
1040 | |||
1041 | /* | ||
1042 | * Set the update bit in all registers, that have one. This way all | ||
1043 | * writes to those registers will also cause the update bit to be | ||
1044 | * written. | ||
1045 | */ | ||
1046 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) | ||
1047 | ((u16 *)codec->reg_cache)[update_reg[i]] |= 0x100; | ||
1048 | |||
1049 | /* Reset the codec */ | ||
1050 | ret = snd_soc_write(codec, WM8978_RESET, 0); | ||
1051 | if (ret < 0) { | ||
1052 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1053 | goto err; | ||
1054 | } | ||
1055 | |||
1056 | wm8978_dai.dev = codec->dev; | ||
1057 | |||
1058 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1059 | |||
1060 | wm8978_codec = codec; | ||
1061 | |||
1062 | ret = snd_soc_register_codec(codec); | ||
1063 | if (ret != 0) { | ||
1064 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1065 | goto err; | ||
1066 | } | ||
1067 | |||
1068 | ret = snd_soc_register_dai(&wm8978_dai); | ||
1069 | if (ret != 0) { | ||
1070 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1071 | goto err_codec; | ||
1072 | } | ||
1073 | |||
1074 | return 0; | ||
1075 | |||
1076 | err_codec: | ||
1077 | snd_soc_unregister_codec(codec); | ||
1078 | err: | ||
1079 | kfree(wm8978); | ||
1080 | return ret; | ||
1081 | } | ||
1082 | |||
1083 | static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) | ||
1084 | { | ||
1085 | wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); | ||
1086 | snd_soc_unregister_dai(&wm8978_dai); | ||
1087 | snd_soc_unregister_codec(&wm8978->codec); | ||
1088 | kfree(wm8978); | ||
1089 | wm8978_codec = NULL; | ||
1090 | } | ||
1091 | |||
1092 | static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, | ||
1093 | const struct i2c_device_id *id) | ||
1094 | { | ||
1095 | struct wm8978_priv *wm8978; | ||
1096 | struct snd_soc_codec *codec; | ||
1097 | |||
1098 | wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); | ||
1099 | if (wm8978 == NULL) | ||
1100 | return -ENOMEM; | ||
1101 | |||
1102 | codec = &wm8978->codec; | ||
1103 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1104 | |||
1105 | i2c_set_clientdata(i2c, wm8978); | ||
1106 | codec->control_data = i2c; | ||
1107 | |||
1108 | codec->dev = &i2c->dev; | ||
1109 | |||
1110 | return wm8978_register(wm8978); | ||
1111 | } | ||
1112 | |||
1113 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) | ||
1114 | { | ||
1115 | struct wm8978_priv *wm8978 = i2c_get_clientdata(client); | ||
1116 | wm8978_unregister(wm8978); | ||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | static const struct i2c_device_id wm8978_i2c_id[] = { | ||
1121 | { "wm8978", 0 }, | ||
1122 | { } | ||
1123 | }; | ||
1124 | MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); | ||
1125 | |||
1126 | static struct i2c_driver wm8978_i2c_driver = { | ||
1127 | .driver = { | ||
1128 | .name = "WM8978", | ||
1129 | .owner = THIS_MODULE, | ||
1130 | }, | ||
1131 | .probe = wm8978_i2c_probe, | ||
1132 | .remove = __devexit_p(wm8978_i2c_remove), | ||
1133 | .id_table = wm8978_i2c_id, | ||
1134 | }; | ||
1135 | |||
1136 | static int __init wm8978_modinit(void) | ||
1137 | { | ||
1138 | return i2c_add_driver(&wm8978_i2c_driver); | ||
1139 | } | ||
1140 | module_init(wm8978_modinit); | ||
1141 | |||
1142 | static void __exit wm8978_exit(void) | ||
1143 | { | ||
1144 | i2c_del_driver(&wm8978_i2c_driver); | ||
1145 | } | ||
1146 | module_exit(wm8978_exit); | ||
1147 | |||
1148 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); | ||
1149 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
1150 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h new file mode 100644 index 000000000000..56ec83270917 --- /dev/null +++ b/sound/soc/codecs/wm8978.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * wm8978.h -- codec driver for WM8978 | ||
3 | * | ||
4 | * Copyright 2009 Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __WM8978_H__ | ||
12 | #define __WM8978_H__ | ||
13 | |||
14 | /* | ||
15 | * Register values. | ||
16 | */ | ||
17 | #define WM8978_RESET 0x00 | ||
18 | #define WM8978_POWER_MANAGEMENT_1 0x01 | ||
19 | #define WM8978_POWER_MANAGEMENT_2 0x02 | ||
20 | #define WM8978_POWER_MANAGEMENT_3 0x03 | ||
21 | #define WM8978_AUDIO_INTERFACE 0x04 | ||
22 | #define WM8978_COMPANDING_CONTROL 0x05 | ||
23 | #define WM8978_CLOCKING 0x06 | ||
24 | #define WM8978_ADDITIONAL_CONTROL 0x07 | ||
25 | #define WM8978_GPIO_CONTROL 0x08 | ||
26 | #define WM8978_JACK_DETECT_CONTROL_1 0x09 | ||
27 | #define WM8978_DAC_CONTROL 0x0A | ||
28 | #define WM8978_LEFT_DAC_DIGITAL_VOLUME 0x0B | ||
29 | #define WM8978_RIGHT_DAC_DIGITAL_VOLUME 0x0C | ||
30 | #define WM8978_JACK_DETECT_CONTROL_2 0x0D | ||
31 | #define WM8978_ADC_CONTROL 0x0E | ||
32 | #define WM8978_LEFT_ADC_DIGITAL_VOLUME 0x0F | ||
33 | #define WM8978_RIGHT_ADC_DIGITAL_VOLUME 0x10 | ||
34 | #define WM8978_EQ1 0x12 | ||
35 | #define WM8978_EQ2 0x13 | ||
36 | #define WM8978_EQ3 0x14 | ||
37 | #define WM8978_EQ4 0x15 | ||
38 | #define WM8978_EQ5 0x16 | ||
39 | #define WM8978_DAC_LIMITER_1 0x18 | ||
40 | #define WM8978_DAC_LIMITER_2 0x19 | ||
41 | #define WM8978_NOTCH_FILTER_1 0x1b | ||
42 | #define WM8978_NOTCH_FILTER_2 0x1c | ||
43 | #define WM8978_NOTCH_FILTER_3 0x1d | ||
44 | #define WM8978_NOTCH_FILTER_4 0x1e | ||
45 | #define WM8978_ALC_CONTROL_1 0x20 | ||
46 | #define WM8978_ALC_CONTROL_2 0x21 | ||
47 | #define WM8978_ALC_CONTROL_3 0x22 | ||
48 | #define WM8978_NOISE_GATE 0x23 | ||
49 | #define WM8978_PLL_N 0x24 | ||
50 | #define WM8978_PLL_K1 0x25 | ||
51 | #define WM8978_PLL_K2 0x26 | ||
52 | #define WM8978_PLL_K3 0x27 | ||
53 | #define WM8978_3D_CONTROL 0x29 | ||
54 | #define WM8978_BEEP_CONTROL 0x2b | ||
55 | #define WM8978_INPUT_CONTROL 0x2c | ||
56 | #define WM8978_LEFT_INP_PGA_CONTROL 0x2d | ||
57 | #define WM8978_RIGHT_INP_PGA_CONTROL 0x2e | ||
58 | #define WM8978_LEFT_ADC_BOOST_CONTROL 0x2f | ||
59 | #define WM8978_RIGHT_ADC_BOOST_CONTROL 0x30 | ||
60 | #define WM8978_OUTPUT_CONTROL 0x31 | ||
61 | #define WM8978_LEFT_MIXER_CONTROL 0x32 | ||
62 | #define WM8978_RIGHT_MIXER_CONTROL 0x33 | ||
63 | #define WM8978_LOUT1_HP_CONTROL 0x34 | ||
64 | #define WM8978_ROUT1_HP_CONTROL 0x35 | ||
65 | #define WM8978_LOUT2_SPK_CONTROL 0x36 | ||
66 | #define WM8978_ROUT2_SPK_CONTROL 0x37 | ||
67 | #define WM8978_OUT3_MIXER_CONTROL 0x38 | ||
68 | #define WM8978_OUT4_MIXER_CONTROL 0x39 | ||
69 | |||
70 | #define WM8978_CACHEREGNUM 58 | ||
71 | |||
72 | /* Clock divider Id's */ | ||
73 | enum wm8978_clk_id { | ||
74 | WM8978_OPCLKRATE, | ||
75 | WM8978_BCLKDIV, | ||
76 | }; | ||
77 | |||
78 | enum wm8978_sysclk_src { | ||
79 | WM8978_PLL, | ||
80 | WM8978_MCLK | ||
81 | }; | ||
82 | |||
83 | extern struct snd_soc_dai wm8978_dai; | ||
84 | extern struct snd_soc_codec_device soc_codec_dev_wm8978; | ||
85 | |||
86 | #endif /* __WM8978_H__ */ | ||
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 3f530f8a972a..bb18c3ecfeb9 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/slab.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -790,19 +791,9 @@ static int wm8988_probe(struct platform_device *pdev) | |||
790 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, | 791 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, |
791 | ARRAY_SIZE(wm8988_dapm_widgets)); | 792 | ARRAY_SIZE(wm8988_dapm_widgets)); |
792 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 793 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
793 | snd_soc_dapm_new_widgets(codec); | ||
794 | |||
795 | ret = snd_soc_init_card(socdev); | ||
796 | if (ret < 0) { | ||
797 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
798 | goto card_err; | ||
799 | } | ||
800 | 794 | ||
801 | return ret; | 795 | return ret; |
802 | 796 | ||
803 | card_err: | ||
804 | snd_soc_free_pcms(socdev); | ||
805 | snd_soc_dapm_free(socdev); | ||
806 | pcm_err: | 797 | pcm_err: |
807 | return ret; | 798 | return ret; |
808 | } | 799 | } |
@@ -944,21 +935,6 @@ static int wm8988_i2c_remove(struct i2c_client *client) | |||
944 | return 0; | 935 | return 0; |
945 | } | 936 | } |
946 | 937 | ||
947 | #ifdef CONFIG_PM | ||
948 | static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
949 | { | ||
950 | return snd_soc_suspend_device(&client->dev); | ||
951 | } | ||
952 | |||
953 | static int wm8988_i2c_resume(struct i2c_client *client) | ||
954 | { | ||
955 | return snd_soc_resume_device(&client->dev); | ||
956 | } | ||
957 | #else | ||
958 | #define wm8988_i2c_suspend NULL | ||
959 | #define wm8988_i2c_resume NULL | ||
960 | #endif | ||
961 | |||
962 | static const struct i2c_device_id wm8988_i2c_id[] = { | 938 | static const struct i2c_device_id wm8988_i2c_id[] = { |
963 | { "wm8988", 0 }, | 939 | { "wm8988", 0 }, |
964 | { } | 940 | { } |
@@ -972,8 +948,6 @@ static struct i2c_driver wm8988_i2c_driver = { | |||
972 | }, | 948 | }, |
973 | .probe = wm8988_i2c_probe, | 949 | .probe = wm8988_i2c_probe, |
974 | .remove = wm8988_i2c_remove, | 950 | .remove = wm8988_i2c_remove, |
975 | .suspend = wm8988_i2c_suspend, | ||
976 | .resume = wm8988_i2c_resume, | ||
977 | .id_table = wm8988_i2c_id, | 951 | .id_table = wm8988_i2c_id, |
978 | }; | 952 | }; |
979 | #endif | 953 | #endif |
@@ -1006,21 +980,6 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi) | |||
1006 | return 0; | 980 | return 0; |
1007 | } | 981 | } |
1008 | 982 | ||
1009 | #ifdef CONFIG_PM | ||
1010 | static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg) | ||
1011 | { | ||
1012 | return snd_soc_suspend_device(&spi->dev); | ||
1013 | } | ||
1014 | |||
1015 | static int wm8988_spi_resume(struct spi_device *spi) | ||
1016 | { | ||
1017 | return snd_soc_resume_device(&spi->dev); | ||
1018 | } | ||
1019 | #else | ||
1020 | #define wm8988_spi_suspend NULL | ||
1021 | #define wm8988_spi_resume NULL | ||
1022 | #endif | ||
1023 | |||
1024 | static struct spi_driver wm8988_spi_driver = { | 983 | static struct spi_driver wm8988_spi_driver = { |
1025 | .driver = { | 984 | .driver = { |
1026 | .name = "wm8988", | 985 | .name = "wm8988", |
@@ -1029,8 +988,6 @@ static struct spi_driver wm8988_spi_driver = { | |||
1029 | }, | 988 | }, |
1030 | .probe = wm8988_spi_probe, | 989 | .probe = wm8988_spi_probe, |
1031 | .remove = __devexit_p(wm8988_spi_remove), | 990 | .remove = __devexit_p(wm8988_spi_remove), |
1032 | .suspend = wm8988_spi_suspend, | ||
1033 | .resume = wm8988_spi_resume, | ||
1034 | }; | 991 | }; |
1035 | #endif | 992 | #endif |
1036 | 993 | ||
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 2d702db4131d..831f4730bfd5 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -920,7 +921,6 @@ static int wm8990_add_widgets(struct snd_soc_codec *codec) | |||
920 | /* set up the WM8990 audio map */ | 921 | /* set up the WM8990 audio map */ |
921 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 922 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
922 | 923 | ||
923 | snd_soc_dapm_new_widgets(codec); | ||
924 | return 0; | 924 | return 0; |
925 | } | 925 | } |
926 | 926 | ||
@@ -972,8 +972,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target, | |||
972 | pll_div->k = K; | 972 | pll_div->k = K; |
973 | } | 973 | } |
974 | 974 | ||
975 | static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, | 975 | static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
976 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 976 | int source, unsigned int freq_in, unsigned int freq_out) |
977 | { | 977 | { |
978 | u16 reg; | 978 | u16 reg; |
979 | struct snd_soc_codec *codec = codec_dai->codec; | 979 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -991,7 +991,7 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
991 | reg = snd_soc_read(codec, WM8990_CLOCKING_2); | 991 | reg = snd_soc_read(codec, WM8990_CLOCKING_2); |
992 | snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); | 992 | snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); |
993 | 993 | ||
994 | /* set up N , fractional mode and pre-divisor if neccessary */ | 994 | /* set up N , fractional mode and pre-divisor if necessary */ |
995 | snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | | 995 | snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | |
996 | (pll_div.div2?WM8990_PRESCALE:0)); | 996 | (pll_div.div2?WM8990_PRESCALE:0)); |
997 | snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); | 997 | snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); |
@@ -1320,10 +1320,6 @@ static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | |||
1320 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1320 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1321 | struct snd_soc_codec *codec = socdev->card->codec; | 1321 | struct snd_soc_codec *codec = socdev->card->codec; |
1322 | 1322 | ||
1323 | /* we only need to suspend if we are a valid card */ | ||
1324 | if (!codec->card) | ||
1325 | return 0; | ||
1326 | |||
1327 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1323 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1328 | return 0; | 1324 | return 0; |
1329 | } | 1325 | } |
@@ -1336,10 +1332,6 @@ static int wm8990_resume(struct platform_device *pdev) | |||
1336 | u8 data[2]; | 1332 | u8 data[2]; |
1337 | u16 *cache = codec->reg_cache; | 1333 | u16 *cache = codec->reg_cache; |
1338 | 1334 | ||
1339 | /* we only need to resume if we are a valid card */ | ||
1340 | if (!codec->card) | ||
1341 | return 0; | ||
1342 | |||
1343 | /* Sync reg_cache with the hardware */ | 1335 | /* Sync reg_cache with the hardware */ |
1344 | for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) { | 1336 | for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) { |
1345 | if (i + 1 == WM8990_RESET) | 1337 | if (i + 1 == WM8990_RESET) |
@@ -1409,16 +1401,9 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1409 | snd_soc_add_controls(codec, wm8990_snd_controls, | 1401 | snd_soc_add_controls(codec, wm8990_snd_controls, |
1410 | ARRAY_SIZE(wm8990_snd_controls)); | 1402 | ARRAY_SIZE(wm8990_snd_controls)); |
1411 | wm8990_add_widgets(codec); | 1403 | wm8990_add_widgets(codec); |
1412 | ret = snd_soc_init_card(socdev); | 1404 | |
1413 | if (ret < 0) { | ||
1414 | printk(KERN_ERR "wm8990: failed to register card\n"); | ||
1415 | goto card_err; | ||
1416 | } | ||
1417 | return ret; | 1405 | return ret; |
1418 | 1406 | ||
1419 | card_err: | ||
1420 | snd_soc_free_pcms(socdev); | ||
1421 | snd_soc_dapm_free(socdev); | ||
1422 | pcm_err: | 1407 | pcm_err: |
1423 | kfree(codec->reg_cache); | 1408 | kfree(codec->reg_cache); |
1424 | return ret; | 1409 | return ret; |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d9987999e92c..03e8b1a6a56c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8993.c -- WM8993 ALSA SoC audio driver | 2 | * wm8993.c -- WM8993 ALSA SoC audio driver |
3 | * | 3 | * |
4 | * Copyright 2009 Wolfson Microelectronics plc | 4 | * Copyright 2009, 2010 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -16,7 +16,9 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/regulator/consumer.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | ||
20 | #include <sound/core.h> | 22 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -29,6 +31,16 @@ | |||
29 | #include "wm8993.h" | 31 | #include "wm8993.h" |
30 | #include "wm_hubs.h" | 32 | #include "wm_hubs.h" |
31 | 33 | ||
34 | #define WM8993_NUM_SUPPLIES 6 | ||
35 | static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = { | ||
36 | "DCVDD", | ||
37 | "DBVDD", | ||
38 | "AVDD1", | ||
39 | "AVDD2", | ||
40 | "CPVDD", | ||
41 | "SPKVDD", | ||
42 | }; | ||
43 | |||
32 | static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = { | 44 | static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = { |
33 | 0x8993, /* R0 - Software Reset */ | 45 | 0x8993, /* R0 - Software Reset */ |
34 | 0x0000, /* R1 - Power Management (1) */ | 46 | 0x0000, /* R1 - Power Management (1) */ |
@@ -213,7 +225,9 @@ static struct { | |||
213 | }; | 225 | }; |
214 | 226 | ||
215 | struct wm8993_priv { | 227 | struct wm8993_priv { |
228 | struct wm_hubs_data hubs_data; | ||
216 | u16 reg_cache[WM8993_REGISTER_COUNT]; | 229 | u16 reg_cache[WM8993_REGISTER_COUNT]; |
230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; | ||
217 | struct wm8993_platform_data pdata; | 231 | struct wm8993_platform_data pdata; |
218 | struct snd_soc_codec codec; | 232 | struct snd_soc_codec codec; |
219 | int master; | 233 | int master; |
@@ -227,36 +241,9 @@ struct wm8993_priv { | |||
227 | int class_w_users; | 241 | int class_w_users; |
228 | unsigned int fll_fref; | 242 | unsigned int fll_fref; |
229 | unsigned int fll_fout; | 243 | unsigned int fll_fout; |
244 | int fll_src; | ||
230 | }; | 245 | }; |
231 | 246 | ||
232 | static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg) | ||
233 | { | ||
234 | struct i2c_msg xfer[2]; | ||
235 | u16 data; | ||
236 | int ret; | ||
237 | struct i2c_client *i2c = codec->control_data; | ||
238 | |||
239 | /* Write register */ | ||
240 | xfer[0].addr = i2c->addr; | ||
241 | xfer[0].flags = 0; | ||
242 | xfer[0].len = 1; | ||
243 | xfer[0].buf = ® | ||
244 | |||
245 | /* Read data */ | ||
246 | xfer[1].addr = i2c->addr; | ||
247 | xfer[1].flags = I2C_M_RD; | ||
248 | xfer[1].len = 2; | ||
249 | xfer[1].buf = (u8 *)&data; | ||
250 | |||
251 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
252 | if (ret != 2) { | ||
253 | dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | return (data >> 8) | ((data & 0xff) << 8); | ||
258 | } | ||
259 | |||
260 | static int wm8993_volatile(unsigned int reg) | 247 | static int wm8993_volatile(unsigned int reg) |
261 | { | 248 | { |
262 | switch (reg) { | 249 | switch (reg) { |
@@ -271,48 +258,6 @@ static int wm8993_volatile(unsigned int reg) | |||
271 | } | 258 | } |
272 | } | 259 | } |
273 | 260 | ||
274 | static unsigned int wm8993_read(struct snd_soc_codec *codec, | ||
275 | unsigned int reg) | ||
276 | { | ||
277 | u16 *reg_cache = codec->reg_cache; | ||
278 | |||
279 | BUG_ON(reg > WM8993_MAX_REGISTER); | ||
280 | |||
281 | if (wm8993_volatile(reg)) | ||
282 | return wm8993_read_hw(codec, reg); | ||
283 | else | ||
284 | return reg_cache[reg]; | ||
285 | } | ||
286 | |||
287 | static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg, | ||
288 | unsigned int value) | ||
289 | { | ||
290 | u16 *reg_cache = codec->reg_cache; | ||
291 | u8 data[3]; | ||
292 | int ret; | ||
293 | |||
294 | BUG_ON(reg > WM8993_MAX_REGISTER); | ||
295 | |||
296 | /* data is | ||
297 | * D15..D9 WM8993 register offset | ||
298 | * D8...D0 register data | ||
299 | */ | ||
300 | data[0] = reg; | ||
301 | data[1] = value >> 8; | ||
302 | data[2] = value & 0x00ff; | ||
303 | |||
304 | if (!wm8993_volatile(reg)) | ||
305 | reg_cache[reg] = value; | ||
306 | |||
307 | ret = codec->hw_write(codec->control_data, data, 3); | ||
308 | |||
309 | if (ret == 3) | ||
310 | return 0; | ||
311 | if (ret < 0) | ||
312 | return ret; | ||
313 | return -EIO; | ||
314 | } | ||
315 | |||
316 | struct _fll_div { | 261 | struct _fll_div { |
317 | u16 fll_fratio; | 262 | u16 fll_fratio; |
318 | u16 fll_outdiv; | 263 | u16 fll_outdiv; |
@@ -422,7 +367,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
422 | return 0; | 367 | return 0; |
423 | } | 368 | } |
424 | 369 | ||
425 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, | 370 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, |
426 | unsigned int Fref, unsigned int Fout) | 371 | unsigned int Fref, unsigned int Fout) |
427 | { | 372 | { |
428 | struct snd_soc_codec *codec = dai->codec; | 373 | struct snd_soc_codec *codec = dai->codec; |
@@ -441,9 +386,9 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, | |||
441 | wm8993->fll_fref = 0; | 386 | wm8993->fll_fref = 0; |
442 | wm8993->fll_fout = 0; | 387 | wm8993->fll_fout = 0; |
443 | 388 | ||
444 | reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); | 389 | reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); |
445 | reg1 &= ~WM8993_FLL_ENA; | 390 | reg1 &= ~WM8993_FLL_ENA; |
446 | wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); | 391 | snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); |
447 | 392 | ||
448 | return 0; | 393 | return 0; |
449 | } | 394 | } |
@@ -452,7 +397,7 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, | |||
452 | if (ret != 0) | 397 | if (ret != 0) |
453 | return ret; | 398 | return ret; |
454 | 399 | ||
455 | reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5); | 400 | reg5 = snd_soc_read(codec, WM8993_FLL_CONTROL_5); |
456 | reg5 &= ~WM8993_FLL_CLK_SRC_MASK; | 401 | reg5 &= ~WM8993_FLL_CLK_SRC_MASK; |
457 | 402 | ||
458 | switch (fll_id) { | 403 | switch (fll_id) { |
@@ -474,38 +419,39 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, | |||
474 | 419 | ||
475 | /* Any FLL configuration change requires that the FLL be | 420 | /* Any FLL configuration change requires that the FLL be |
476 | * disabled first. */ | 421 | * disabled first. */ |
477 | reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); | 422 | reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); |
478 | reg1 &= ~WM8993_FLL_ENA; | 423 | reg1 &= ~WM8993_FLL_ENA; |
479 | wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); | 424 | snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); |
480 | 425 | ||
481 | /* Apply the configuration */ | 426 | /* Apply the configuration */ |
482 | if (fll_div.k) | 427 | if (fll_div.k) |
483 | reg1 |= WM8993_FLL_FRAC_MASK; | 428 | reg1 |= WM8993_FLL_FRAC_MASK; |
484 | else | 429 | else |
485 | reg1 &= ~WM8993_FLL_FRAC_MASK; | 430 | reg1 &= ~WM8993_FLL_FRAC_MASK; |
486 | wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); | 431 | snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); |
487 | 432 | ||
488 | wm8993_write(codec, WM8993_FLL_CONTROL_2, | 433 | snd_soc_write(codec, WM8993_FLL_CONTROL_2, |
489 | (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | | 434 | (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | |
490 | (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); | 435 | (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); |
491 | wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); | 436 | snd_soc_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); |
492 | 437 | ||
493 | reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4); | 438 | reg4 = snd_soc_read(codec, WM8993_FLL_CONTROL_4); |
494 | reg4 &= ~WM8993_FLL_N_MASK; | 439 | reg4 &= ~WM8993_FLL_N_MASK; |
495 | reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; | 440 | reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; |
496 | wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4); | 441 | snd_soc_write(codec, WM8993_FLL_CONTROL_4, reg4); |
497 | 442 | ||
498 | reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; | 443 | reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; |
499 | reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; | 444 | reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; |
500 | wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5); | 445 | snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5); |
501 | 446 | ||
502 | /* Enable the FLL */ | 447 | /* Enable the FLL */ |
503 | wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); | 448 | snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); |
504 | 449 | ||
505 | dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); | 450 | dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); |
506 | 451 | ||
507 | wm8993->fll_fref = Fref; | 452 | wm8993->fll_fref = Fref; |
508 | wm8993->fll_fout = Fout; | 453 | wm8993->fll_fout = Fout; |
454 | wm8993->fll_src = source; | ||
509 | 455 | ||
510 | return 0; | 456 | return 0; |
511 | } | 457 | } |
@@ -520,7 +466,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
520 | case WM8993_SYSCLK_MCLK: | 466 | case WM8993_SYSCLK_MCLK: |
521 | dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); | 467 | dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); |
522 | 468 | ||
523 | reg = wm8993_read(codec, WM8993_CLOCKING_2); | 469 | reg = snd_soc_read(codec, WM8993_CLOCKING_2); |
524 | reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); | 470 | reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); |
525 | if (wm8993->mclk_rate > 13500000) { | 471 | if (wm8993->mclk_rate > 13500000) { |
526 | reg |= WM8993_MCLK_DIV; | 472 | reg |= WM8993_MCLK_DIV; |
@@ -529,14 +475,14 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
529 | reg &= ~WM8993_MCLK_DIV; | 475 | reg &= ~WM8993_MCLK_DIV; |
530 | wm8993->sysclk_rate = wm8993->mclk_rate; | 476 | wm8993->sysclk_rate = wm8993->mclk_rate; |
531 | } | 477 | } |
532 | wm8993_write(codec, WM8993_CLOCKING_2, reg); | 478 | snd_soc_write(codec, WM8993_CLOCKING_2, reg); |
533 | break; | 479 | break; |
534 | 480 | ||
535 | case WM8993_SYSCLK_FLL: | 481 | case WM8993_SYSCLK_FLL: |
536 | dev_dbg(codec->dev, "Using %dHz FLL clock\n", | 482 | dev_dbg(codec->dev, "Using %dHz FLL clock\n", |
537 | wm8993->fll_fout); | 483 | wm8993->fll_fout); |
538 | 484 | ||
539 | reg = wm8993_read(codec, WM8993_CLOCKING_2); | 485 | reg = snd_soc_read(codec, WM8993_CLOCKING_2); |
540 | reg |= WM8993_SYSCLK_SRC; | 486 | reg |= WM8993_SYSCLK_SRC; |
541 | if (wm8993->fll_fout > 13500000) { | 487 | if (wm8993->fll_fout > 13500000) { |
542 | reg |= WM8993_MCLK_DIV; | 488 | reg |= WM8993_MCLK_DIV; |
@@ -545,7 +491,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
545 | reg &= ~WM8993_MCLK_DIV; | 491 | reg &= ~WM8993_MCLK_DIV; |
546 | wm8993->sysclk_rate = wm8993->fll_fout; | 492 | wm8993->sysclk_rate = wm8993->fll_fout; |
547 | } | 493 | } |
548 | wm8993_write(codec, WM8993_CLOCKING_2, reg); | 494 | snd_soc_write(codec, WM8993_CLOCKING_2, reg); |
549 | break; | 495 | break; |
550 | 496 | ||
551 | default: | 497 | default: |
@@ -689,7 +635,7 @@ SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, | |||
689 | 635 | ||
690 | SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0), | 636 | SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0), |
691 | SOC_ENUM("DRC Path", drc_path), | 637 | SOC_ENUM("DRC Path", drc_path), |
692 | SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2, | 638 | SOC_SINGLE_TLV("DRC Compressor Threshold Volume", WM8993_DRC_CONTROL_2, |
693 | 2, 60, 1, drc_comp_threash), | 639 | 2, 60, 1, drc_comp_threash), |
694 | SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3, | 640 | SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3, |
695 | 11, 30, 1, drc_comp_amp), | 641 | 11, 30, 1, drc_comp_amp), |
@@ -709,7 +655,7 @@ SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0, | |||
709 | SOC_ENUM("DRC Quick Release Rate", drc_qr_rate), | 655 | SOC_ENUM("DRC Quick Release Rate", drc_qr_rate), |
710 | SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0), | 656 | SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0), |
711 | SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0), | 657 | SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0), |
712 | SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth), | 658 | SOC_ENUM("DRC Smoothing Hysteresis Threshold", drc_smooth), |
713 | SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0, | 659 | SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0, |
714 | drc_startup_tlv), | 660 | drc_startup_tlv), |
715 | 661 | ||
@@ -978,10 +924,33 @@ static const struct snd_soc_dapm_route routes[] = { | |||
978 | { "Right Headphone Mux", "DAC", "DACR" }, | 924 | { "Right Headphone Mux", "DAC", "DACR" }, |
979 | }; | 925 | }; |
980 | 926 | ||
927 | static void wm8993_cache_restore(struct snd_soc_codec *codec) | ||
928 | { | ||
929 | u16 *cache = codec->reg_cache; | ||
930 | int i; | ||
931 | |||
932 | if (!codec->cache_sync) | ||
933 | return; | ||
934 | |||
935 | /* Reenable hardware writes */ | ||
936 | codec->cache_only = 0; | ||
937 | |||
938 | /* Restore the register settings */ | ||
939 | for (i = 1; i < WM8993_MAX_REGISTER; i++) { | ||
940 | if (cache[i] == wm8993_reg_defaults[i]) | ||
941 | continue; | ||
942 | snd_soc_write(codec, i, cache[i]); | ||
943 | } | ||
944 | |||
945 | /* We're in sync again */ | ||
946 | codec->cache_sync = 0; | ||
947 | } | ||
948 | |||
981 | static int wm8993_set_bias_level(struct snd_soc_codec *codec, | 949 | static int wm8993_set_bias_level(struct snd_soc_codec *codec, |
982 | enum snd_soc_bias_level level) | 950 | enum snd_soc_bias_level level) |
983 | { | 951 | { |
984 | struct wm8993_priv *wm8993 = codec->private_data; | 952 | struct wm8993_priv *wm8993 = codec->private_data; |
953 | int ret; | ||
985 | 954 | ||
986 | switch (level) { | 955 | switch (level) { |
987 | case SND_SOC_BIAS_ON: | 956 | case SND_SOC_BIAS_ON: |
@@ -995,6 +964,18 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
995 | 964 | ||
996 | case SND_SOC_BIAS_STANDBY: | 965 | case SND_SOC_BIAS_STANDBY: |
997 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 966 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
967 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
968 | wm8993->supplies); | ||
969 | if (ret != 0) | ||
970 | return ret; | ||
971 | |||
972 | wm8993_cache_restore(codec); | ||
973 | |||
974 | /* Tune DC servo configuration */ | ||
975 | snd_soc_write(codec, 0x44, 3); | ||
976 | snd_soc_write(codec, 0x56, 3); | ||
977 | snd_soc_write(codec, 0x44, 0); | ||
978 | |||
998 | /* Bring up VMID with fast soft start */ | 979 | /* Bring up VMID with fast soft start */ |
999 | snd_soc_update_bits(codec, WM8993_ANTIPOP2, | 980 | snd_soc_update_bits(codec, WM8993_ANTIPOP2, |
1000 | WM8993_STARTUP_BIAS_ENA | | 981 | WM8993_STARTUP_BIAS_ENA | |
@@ -1042,6 +1023,18 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec, | |||
1042 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | 1023 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, |
1043 | WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, | 1024 | WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, |
1044 | 0); | 1025 | 0); |
1026 | |||
1027 | #ifdef CONFIG_REGULATOR | ||
1028 | /* Post 2.6.34 we will be able to get a callback when | ||
1029 | * the regulators are disabled which we can use but | ||
1030 | * for now just assume that the power will be cut if | ||
1031 | * the regulator API is in use. | ||
1032 | */ | ||
1033 | codec->cache_sync = 1; | ||
1034 | #endif | ||
1035 | |||
1036 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), | ||
1037 | wm8993->supplies); | ||
1045 | break; | 1038 | break; |
1046 | } | 1039 | } |
1047 | 1040 | ||
@@ -1075,8 +1068,8 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, | |||
1075 | { | 1068 | { |
1076 | struct snd_soc_codec *codec = dai->codec; | 1069 | struct snd_soc_codec *codec = dai->codec; |
1077 | struct wm8993_priv *wm8993 = codec->private_data; | 1070 | struct wm8993_priv *wm8993 = codec->private_data; |
1078 | unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); | 1071 | unsigned int aif1 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_1); |
1079 | unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); | 1072 | unsigned int aif4 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_4); |
1080 | 1073 | ||
1081 | aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | | 1074 | aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | |
1082 | WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); | 1075 | WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); |
@@ -1159,8 +1152,8 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, | |||
1159 | return -EINVAL; | 1152 | return -EINVAL; |
1160 | } | 1153 | } |
1161 | 1154 | ||
1162 | wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); | 1155 | snd_soc_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); |
1163 | wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); | 1156 | snd_soc_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); |
1164 | 1157 | ||
1165 | return 0; | 1158 | return 0; |
1166 | } | 1159 | } |
@@ -1174,16 +1167,16 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, | |||
1174 | int ret, i, best, best_val, cur_val; | 1167 | int ret, i, best, best_val, cur_val; |
1175 | unsigned int clocking1, clocking3, aif1, aif4; | 1168 | unsigned int clocking1, clocking3, aif1, aif4; |
1176 | 1169 | ||
1177 | clocking1 = wm8993_read(codec, WM8993_CLOCKING_1); | 1170 | clocking1 = snd_soc_read(codec, WM8993_CLOCKING_1); |
1178 | clocking1 &= ~WM8993_BCLK_DIV_MASK; | 1171 | clocking1 &= ~WM8993_BCLK_DIV_MASK; |
1179 | 1172 | ||
1180 | clocking3 = wm8993_read(codec, WM8993_CLOCKING_3); | 1173 | clocking3 = snd_soc_read(codec, WM8993_CLOCKING_3); |
1181 | clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); | 1174 | clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); |
1182 | 1175 | ||
1183 | aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); | 1176 | aif1 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_1); |
1184 | aif1 &= ~WM8993_AIF_WL_MASK; | 1177 | aif1 &= ~WM8993_AIF_WL_MASK; |
1185 | 1178 | ||
1186 | aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); | 1179 | aif4 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_4); |
1187 | aif4 &= ~WM8993_LRCLK_RATE_MASK; | 1180 | aif4 &= ~WM8993_LRCLK_RATE_MASK; |
1188 | 1181 | ||
1189 | /* What BCLK do we need? */ | 1182 | /* What BCLK do we need? */ |
@@ -1276,14 +1269,14 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, | |||
1276 | dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs); | 1269 | dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs); |
1277 | aif4 |= wm8993->bclk / wm8993->fs; | 1270 | aif4 |= wm8993->bclk / wm8993->fs; |
1278 | 1271 | ||
1279 | wm8993_write(codec, WM8993_CLOCKING_1, clocking1); | 1272 | snd_soc_write(codec, WM8993_CLOCKING_1, clocking1); |
1280 | wm8993_write(codec, WM8993_CLOCKING_3, clocking3); | 1273 | snd_soc_write(codec, WM8993_CLOCKING_3, clocking3); |
1281 | wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); | 1274 | snd_soc_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); |
1282 | wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); | 1275 | snd_soc_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); |
1283 | 1276 | ||
1284 | /* ReTune Mobile? */ | 1277 | /* ReTune Mobile? */ |
1285 | if (wm8993->pdata.num_retune_configs) { | 1278 | if (wm8993->pdata.num_retune_configs) { |
1286 | u16 eq1 = wm8993_read(codec, WM8993_EQ1); | 1279 | u16 eq1 = snd_soc_read(codec, WM8993_EQ1); |
1287 | struct wm8993_retune_mobile_setting *s; | 1280 | struct wm8993_retune_mobile_setting *s; |
1288 | 1281 | ||
1289 | best = 0; | 1282 | best = 0; |
@@ -1306,7 +1299,7 @@ static int wm8993_hw_params(struct snd_pcm_substream *substream, | |||
1306 | snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0); | 1299 | snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0); |
1307 | 1300 | ||
1308 | for (i = 1; i < ARRAY_SIZE(s->config); i++) | 1301 | for (i = 1; i < ARRAY_SIZE(s->config); i++) |
1309 | wm8993_write(codec, WM8993_EQ1 + i, s->config[i]); | 1302 | snd_soc_write(codec, WM8993_EQ1 + i, s->config[i]); |
1310 | 1303 | ||
1311 | snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1); | 1304 | snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1); |
1312 | } | 1305 | } |
@@ -1319,14 +1312,14 @@ static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1319 | struct snd_soc_codec *codec = codec_dai->codec; | 1312 | struct snd_soc_codec *codec = codec_dai->codec; |
1320 | unsigned int reg; | 1313 | unsigned int reg; |
1321 | 1314 | ||
1322 | reg = wm8993_read(codec, WM8993_DAC_CTRL); | 1315 | reg = snd_soc_read(codec, WM8993_DAC_CTRL); |
1323 | 1316 | ||
1324 | if (mute) | 1317 | if (mute) |
1325 | reg |= WM8993_DAC_MUTE; | 1318 | reg |= WM8993_DAC_MUTE; |
1326 | else | 1319 | else |
1327 | reg &= ~WM8993_DAC_MUTE; | 1320 | reg &= ~WM8993_DAC_MUTE; |
1328 | 1321 | ||
1329 | wm8993_write(codec, WM8993_DAC_CTRL, reg); | 1322 | snd_soc_write(codec, WM8993_DAC_CTRL, reg); |
1330 | 1323 | ||
1331 | return 0; | 1324 | return 0; |
1332 | } | 1325 | } |
@@ -1464,19 +1457,8 @@ static int wm8993_probe(struct platform_device *pdev) | |||
1464 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, | 1457 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, |
1465 | wm8993->pdata.lineout2_diff); | 1458 | wm8993->pdata.lineout2_diff); |
1466 | 1459 | ||
1467 | snd_soc_dapm_new_widgets(codec); | ||
1468 | |||
1469 | ret = snd_soc_init_card(socdev); | ||
1470 | if (ret < 0) { | ||
1471 | dev_err(codec->dev, "failed to register card\n"); | ||
1472 | goto card_err; | ||
1473 | } | ||
1474 | |||
1475 | return ret; | 1460 | return ret; |
1476 | 1461 | ||
1477 | card_err: | ||
1478 | snd_soc_free_pcms(socdev); | ||
1479 | snd_soc_dapm_free(socdev); | ||
1480 | err: | 1462 | err: |
1481 | return ret; | 1463 | return ret; |
1482 | } | 1464 | } |
@@ -1491,9 +1473,66 @@ static int wm8993_remove(struct platform_device *pdev) | |||
1491 | return 0; | 1473 | return 0; |
1492 | } | 1474 | } |
1493 | 1475 | ||
1476 | #ifdef CONFIG_PM | ||
1477 | static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | ||
1478 | { | ||
1479 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1480 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1481 | struct wm8993_priv *wm8993 = codec->private_data; | ||
1482 | int fll_fout = wm8993->fll_fout; | ||
1483 | int fll_fref = wm8993->fll_fref; | ||
1484 | int ret; | ||
1485 | |||
1486 | /* Stop the FLL in an orderly fashion */ | ||
1487 | ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); | ||
1488 | if (ret != 0) { | ||
1489 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | ||
1490 | return ret; | ||
1491 | } | ||
1492 | |||
1493 | wm8993->fll_fout = fll_fout; | ||
1494 | wm8993->fll_fref = fll_fref; | ||
1495 | |||
1496 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1497 | |||
1498 | return 0; | ||
1499 | } | ||
1500 | |||
1501 | static int wm8993_resume(struct platform_device *pdev) | ||
1502 | { | ||
1503 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1505 | struct wm8993_priv *wm8993 = codec->private_data; | ||
1506 | int ret; | ||
1507 | |||
1508 | wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1509 | |||
1510 | /* Restart the FLL? */ | ||
1511 | if (wm8993->fll_fout) { | ||
1512 | int fll_fout = wm8993->fll_fout; | ||
1513 | int fll_fref = wm8993->fll_fref; | ||
1514 | |||
1515 | wm8993->fll_fref = 0; | ||
1516 | wm8993->fll_fout = 0; | ||
1517 | |||
1518 | ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, | ||
1519 | fll_fref, fll_fout); | ||
1520 | if (ret != 0) | ||
1521 | dev_err(codec->dev, "Failed to restart FLL\n"); | ||
1522 | } | ||
1523 | |||
1524 | return 0; | ||
1525 | } | ||
1526 | #else | ||
1527 | #define wm8993_suspend NULL | ||
1528 | #define wm8993_resume NULL | ||
1529 | #endif | ||
1530 | |||
1494 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { | 1531 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { |
1495 | .probe = wm8993_probe, | 1532 | .probe = wm8993_probe, |
1496 | .remove = wm8993_remove, | 1533 | .remove = wm8993_remove, |
1534 | .suspend = wm8993_suspend, | ||
1535 | .resume = wm8993_resume, | ||
1497 | }; | 1536 | }; |
1498 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); | 1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); |
1499 | 1538 | ||
@@ -1504,6 +1543,7 @@ static int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1504 | struct snd_soc_codec *codec; | 1543 | struct snd_soc_codec *codec; |
1505 | unsigned int val; | 1544 | unsigned int val; |
1506 | int ret; | 1545 | int ret; |
1546 | int i; | ||
1507 | 1547 | ||
1508 | if (wm8993_codec) { | 1548 | if (wm8993_codec) { |
1509 | dev_err(&i2c->dev, "A WM8993 is already registered\n"); | 1549 | dev_err(&i2c->dev, "A WM8993 is already registered\n"); |
@@ -1524,9 +1564,7 @@ static int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1524 | INIT_LIST_HEAD(&codec->dapm_paths); | 1564 | INIT_LIST_HEAD(&codec->dapm_paths); |
1525 | 1565 | ||
1526 | codec->name = "WM8993"; | 1566 | codec->name = "WM8993"; |
1527 | codec->read = wm8993_read; | 1567 | codec->volatile_register = wm8993_volatile; |
1528 | codec->write = wm8993_write; | ||
1529 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1530 | codec->reg_cache = wm8993->reg_cache; | 1568 | codec->reg_cache = wm8993->reg_cache; |
1531 | codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); | 1569 | codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); |
1532 | codec->bias_level = SND_SOC_BIAS_OFF; | 1570 | codec->bias_level = SND_SOC_BIAS_OFF; |
@@ -1535,25 +1573,53 @@ static int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1535 | codec->num_dai = 1; | 1573 | codec->num_dai = 1; |
1536 | codec->private_data = wm8993; | 1574 | codec->private_data = wm8993; |
1537 | 1575 | ||
1576 | wm8993->hubs_data.hp_startup_mode = 1; | ||
1577 | wm8993->hubs_data.dcs_codes = -2; | ||
1578 | |||
1538 | memcpy(wm8993->reg_cache, wm8993_reg_defaults, | 1579 | memcpy(wm8993->reg_cache, wm8993_reg_defaults, |
1539 | sizeof(wm8993->reg_cache)); | 1580 | sizeof(wm8993->reg_cache)); |
1540 | 1581 | ||
1582 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1583 | if (ret != 0) { | ||
1584 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1585 | goto err; | ||
1586 | } | ||
1587 | |||
1541 | i2c_set_clientdata(i2c, wm8993); | 1588 | i2c_set_clientdata(i2c, wm8993); |
1542 | codec->control_data = i2c; | 1589 | codec->control_data = i2c; |
1543 | wm8993_codec = codec; | 1590 | wm8993_codec = codec; |
1544 | 1591 | ||
1545 | codec->dev = &i2c->dev; | 1592 | codec->dev = &i2c->dev; |
1546 | 1593 | ||
1547 | val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET); | 1594 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) |
1595 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1596 | |||
1597 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), | ||
1598 | wm8993->supplies); | ||
1599 | if (ret != 0) { | ||
1600 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1601 | goto err; | ||
1602 | } | ||
1603 | |||
1604 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
1605 | wm8993->supplies); | ||
1606 | if (ret != 0) { | ||
1607 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1608 | goto err_get; | ||
1609 | } | ||
1610 | |||
1611 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); | ||
1548 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { | 1612 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { |
1549 | dev_err(codec->dev, "Invalid ID register value %x\n", val); | 1613 | dev_err(codec->dev, "Invalid ID register value %x\n", val); |
1550 | ret = -EINVAL; | 1614 | ret = -EINVAL; |
1551 | goto err; | 1615 | goto err_enable; |
1552 | } | 1616 | } |
1553 | 1617 | ||
1554 | ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | 1618 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); |
1555 | if (ret != 0) | 1619 | if (ret != 0) |
1556 | goto err; | 1620 | goto err_enable; |
1621 | |||
1622 | codec->cache_only = 1; | ||
1557 | 1623 | ||
1558 | /* By default we're using the output mixers */ | 1624 | /* By default we're using the output mixers */ |
1559 | wm8993->class_w_users = 2; | 1625 | wm8993->class_w_users = 2; |
@@ -1572,36 +1638,18 @@ static int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1572 | /* Use automatic clock configuration */ | 1638 | /* Use automatic clock configuration */ |
1573 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | 1639 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); |
1574 | 1640 | ||
1575 | if (!wm8993->pdata.lineout1_diff) | 1641 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, |
1576 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | 1642 | wm8993->pdata.lineout2_diff, |
1577 | WM8993_LINEOUT1_MODE, | 1643 | wm8993->pdata.lineout1fb, |
1578 | WM8993_LINEOUT1_MODE); | 1644 | wm8993->pdata.lineout2fb, |
1579 | if (!wm8993->pdata.lineout2_diff) | 1645 | wm8993->pdata.jd_scthr, |
1580 | snd_soc_update_bits(codec, WM8993_LINE_MIXER2, | 1646 | wm8993->pdata.jd_thr, |
1581 | WM8993_LINEOUT2_MODE, | 1647 | wm8993->pdata.micbias1_lvl, |
1582 | WM8993_LINEOUT2_MODE); | 1648 | wm8993->pdata.micbias2_lvl); |
1583 | 1649 | ||
1584 | if (wm8993->pdata.lineout1fb) | ||
1585 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
1586 | WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); | ||
1587 | |||
1588 | if (wm8993->pdata.lineout2fb) | ||
1589 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
1590 | WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); | ||
1591 | |||
1592 | /* Apply the microphone bias/detection configuration - the | ||
1593 | * platform data is directly applicable to the register. */ | ||
1594 | snd_soc_update_bits(codec, WM8993_MICBIAS, | ||
1595 | WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | | ||
1596 | WM8993_MICB1_LVL | WM8993_MICB2_LVL, | ||
1597 | wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT | | ||
1598 | wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT | | ||
1599 | wm8993->pdata.micbias1_lvl | | ||
1600 | wm8993->pdata.micbias1_lvl << 1); | ||
1601 | |||
1602 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1650 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1603 | if (ret != 0) | 1651 | if (ret != 0) |
1604 | goto err; | 1652 | goto err_enable; |
1605 | 1653 | ||
1606 | wm8993_dai.dev = codec->dev; | 1654 | wm8993_dai.dev = codec->dev; |
1607 | 1655 | ||
@@ -1615,6 +1663,10 @@ static int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1615 | 1663 | ||
1616 | err_bias: | 1664 | err_bias: |
1617 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1665 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1666 | err_enable: | ||
1667 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1668 | err_get: | ||
1669 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1618 | err: | 1670 | err: |
1619 | wm8993_codec = NULL; | 1671 | wm8993_codec = NULL; |
1620 | kfree(wm8993); | 1672 | kfree(wm8993); |
@@ -1629,6 +1681,7 @@ static int wm8993_i2c_remove(struct i2c_client *client) | |||
1629 | snd_soc_unregister_dai(&wm8993_dai); | 1681 | snd_soc_unregister_dai(&wm8993_dai); |
1630 | 1682 | ||
1631 | wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); | 1683 | wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); |
1684 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1632 | kfree(wm8993); | 1685 | kfree(wm8993); |
1633 | 1686 | ||
1634 | return 0; | 1687 | return 0; |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c new file mode 100644 index 000000000000..9da0724cd47a --- /dev/null +++ b/sound/soc/codecs/wm8994.c | |||
@@ -0,0 +1,3874 @@ | |||
1 | /* | ||
2 | * wm8994.c -- WM8994 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2009 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | |||
31 | #include <linux/mfd/wm8994/core.h> | ||
32 | #include <linux/mfd/wm8994/registers.h> | ||
33 | #include <linux/mfd/wm8994/pdata.h> | ||
34 | #include <linux/mfd/wm8994/gpio.h> | ||
35 | |||
36 | #include "wm8994.h" | ||
37 | #include "wm_hubs.h" | ||
38 | |||
39 | static struct snd_soc_codec *wm8994_codec; | ||
40 | struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
41 | |||
42 | struct fll_config { | ||
43 | int src; | ||
44 | int in; | ||
45 | int out; | ||
46 | }; | ||
47 | |||
48 | #define WM8994_NUM_DRC 3 | ||
49 | #define WM8994_NUM_EQ 3 | ||
50 | |||
51 | static int wm8994_drc_base[] = { | ||
52 | WM8994_AIF1_DRC1_1, | ||
53 | WM8994_AIF1_DRC2_1, | ||
54 | WM8994_AIF2_DRC_1, | ||
55 | }; | ||
56 | |||
57 | static int wm8994_retune_mobile_base[] = { | ||
58 | WM8994_AIF1_DAC1_EQ_GAINS_1, | ||
59 | WM8994_AIF1_DAC2_EQ_GAINS_1, | ||
60 | WM8994_AIF2_EQ_GAINS_1, | ||
61 | }; | ||
62 | |||
63 | #define WM8994_REG_CACHE_SIZE 0x621 | ||
64 | |||
65 | /* codec private data */ | ||
66 | struct wm8994_priv { | ||
67 | struct wm_hubs_data hubs; | ||
68 | struct snd_soc_codec codec; | ||
69 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; | ||
70 | int sysclk[2]; | ||
71 | int sysclk_rate[2]; | ||
72 | int mclk[2]; | ||
73 | int aifclk[2]; | ||
74 | struct fll_config fll[2], fll_suspend[2]; | ||
75 | |||
76 | int dac_rates[2]; | ||
77 | int lrclk_shared[2]; | ||
78 | |||
79 | /* Platform dependant DRC configuration */ | ||
80 | const char **drc_texts; | ||
81 | int drc_cfg[WM8994_NUM_DRC]; | ||
82 | struct soc_enum drc_enum; | ||
83 | |||
84 | /* Platform dependant ReTune mobile configuration */ | ||
85 | int num_retune_mobile_texts; | ||
86 | const char **retune_mobile_texts; | ||
87 | int retune_mobile_cfg[WM8994_NUM_EQ]; | ||
88 | struct soc_enum retune_mobile_enum; | ||
89 | |||
90 | struct wm8994_pdata *pdata; | ||
91 | }; | ||
92 | |||
93 | static struct { | ||
94 | unsigned short readable; /* Mask of readable bits */ | ||
95 | unsigned short writable; /* Mask of writable bits */ | ||
96 | unsigned short vol; /* Mask of volatile bits */ | ||
97 | } access_masks[] = { | ||
98 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R0 - Software Reset */ | ||
99 | { 0x3B37, 0x3B37, 0x0000 }, /* R1 - Power Management (1) */ | ||
100 | { 0x6BF0, 0x6BF0, 0x0000 }, /* R2 - Power Management (2) */ | ||
101 | { 0x3FF0, 0x3FF0, 0x0000 }, /* R3 - Power Management (3) */ | ||
102 | { 0x3F3F, 0x3F3F, 0x0000 }, /* R4 - Power Management (4) */ | ||
103 | { 0x3F0F, 0x3F0F, 0x0000 }, /* R5 - Power Management (5) */ | ||
104 | { 0x003F, 0x003F, 0x0000 }, /* R6 - Power Management (6) */ | ||
105 | { 0x0000, 0x0000, 0x0000 }, /* R7 */ | ||
106 | { 0x0000, 0x0000, 0x0000 }, /* R8 */ | ||
107 | { 0x0000, 0x0000, 0x0000 }, /* R9 */ | ||
108 | { 0x0000, 0x0000, 0x0000 }, /* R10 */ | ||
109 | { 0x0000, 0x0000, 0x0000 }, /* R11 */ | ||
110 | { 0x0000, 0x0000, 0x0000 }, /* R12 */ | ||
111 | { 0x0000, 0x0000, 0x0000 }, /* R13 */ | ||
112 | { 0x0000, 0x0000, 0x0000 }, /* R14 */ | ||
113 | { 0x0000, 0x0000, 0x0000 }, /* R15 */ | ||
114 | { 0x0000, 0x0000, 0x0000 }, /* R16 */ | ||
115 | { 0x0000, 0x0000, 0x0000 }, /* R17 */ | ||
116 | { 0x0000, 0x0000, 0x0000 }, /* R18 */ | ||
117 | { 0x0000, 0x0000, 0x0000 }, /* R19 */ | ||
118 | { 0x0000, 0x0000, 0x0000 }, /* R20 */ | ||
119 | { 0x01C0, 0x01C0, 0x0000 }, /* R21 - Input Mixer (1) */ | ||
120 | { 0x0000, 0x0000, 0x0000 }, /* R22 */ | ||
121 | { 0x0000, 0x0000, 0x0000 }, /* R23 */ | ||
122 | { 0x00DF, 0x01DF, 0x0000 }, /* R24 - Left Line Input 1&2 Volume */ | ||
123 | { 0x00DF, 0x01DF, 0x0000 }, /* R25 - Left Line Input 3&4 Volume */ | ||
124 | { 0x00DF, 0x01DF, 0x0000 }, /* R26 - Right Line Input 1&2 Volume */ | ||
125 | { 0x00DF, 0x01DF, 0x0000 }, /* R27 - Right Line Input 3&4 Volume */ | ||
126 | { 0x00FF, 0x01FF, 0x0000 }, /* R28 - Left Output Volume */ | ||
127 | { 0x00FF, 0x01FF, 0x0000 }, /* R29 - Right Output Volume */ | ||
128 | { 0x0077, 0x0077, 0x0000 }, /* R30 - Line Outputs Volume */ | ||
129 | { 0x0030, 0x0030, 0x0000 }, /* R31 - HPOUT2 Volume */ | ||
130 | { 0x00FF, 0x01FF, 0x0000 }, /* R32 - Left OPGA Volume */ | ||
131 | { 0x00FF, 0x01FF, 0x0000 }, /* R33 - Right OPGA Volume */ | ||
132 | { 0x007F, 0x007F, 0x0000 }, /* R34 - SPKMIXL Attenuation */ | ||
133 | { 0x017F, 0x017F, 0x0000 }, /* R35 - SPKMIXR Attenuation */ | ||
134 | { 0x003F, 0x003F, 0x0000 }, /* R36 - SPKOUT Mixers */ | ||
135 | { 0x003F, 0x003F, 0x0000 }, /* R37 - ClassD */ | ||
136 | { 0x00FF, 0x01FF, 0x0000 }, /* R38 - Speaker Volume Left */ | ||
137 | { 0x00FF, 0x01FF, 0x0000 }, /* R39 - Speaker Volume Right */ | ||
138 | { 0x00FF, 0x00FF, 0x0000 }, /* R40 - Input Mixer (2) */ | ||
139 | { 0x01B7, 0x01B7, 0x0000 }, /* R41 - Input Mixer (3) */ | ||
140 | { 0x01B7, 0x01B7, 0x0000 }, /* R42 - Input Mixer (4) */ | ||
141 | { 0x01C7, 0x01C7, 0x0000 }, /* R43 - Input Mixer (5) */ | ||
142 | { 0x01C7, 0x01C7, 0x0000 }, /* R44 - Input Mixer (6) */ | ||
143 | { 0x01FF, 0x01FF, 0x0000 }, /* R45 - Output Mixer (1) */ | ||
144 | { 0x01FF, 0x01FF, 0x0000 }, /* R46 - Output Mixer (2) */ | ||
145 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R47 - Output Mixer (3) */ | ||
146 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R48 - Output Mixer (4) */ | ||
147 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R49 - Output Mixer (5) */ | ||
148 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R50 - Output Mixer (6) */ | ||
149 | { 0x0038, 0x0038, 0x0000 }, /* R51 - HPOUT2 Mixer */ | ||
150 | { 0x0077, 0x0077, 0x0000 }, /* R52 - Line Mixer (1) */ | ||
151 | { 0x0077, 0x0077, 0x0000 }, /* R53 - Line Mixer (2) */ | ||
152 | { 0x03FF, 0x03FF, 0x0000 }, /* R54 - Speaker Mixer */ | ||
153 | { 0x00C1, 0x00C1, 0x0000 }, /* R55 - Additional Control */ | ||
154 | { 0x00F0, 0x00F0, 0x0000 }, /* R56 - AntiPOP (1) */ | ||
155 | { 0x01EF, 0x01EF, 0x0000 }, /* R57 - AntiPOP (2) */ | ||
156 | { 0x00FF, 0x00FF, 0x0000 }, /* R58 - MICBIAS */ | ||
157 | { 0x000F, 0x000F, 0x0000 }, /* R59 - LDO 1 */ | ||
158 | { 0x0007, 0x0007, 0x0000 }, /* R60 - LDO 2 */ | ||
159 | { 0x0000, 0x0000, 0x0000 }, /* R61 */ | ||
160 | { 0x0000, 0x0000, 0x0000 }, /* R62 */ | ||
161 | { 0x0000, 0x0000, 0x0000 }, /* R63 */ | ||
162 | { 0x0000, 0x0000, 0x0000 }, /* R64 */ | ||
163 | { 0x0000, 0x0000, 0x0000 }, /* R65 */ | ||
164 | { 0x0000, 0x0000, 0x0000 }, /* R66 */ | ||
165 | { 0x0000, 0x0000, 0x0000 }, /* R67 */ | ||
166 | { 0x0000, 0x0000, 0x0000 }, /* R68 */ | ||
167 | { 0x0000, 0x0000, 0x0000 }, /* R69 */ | ||
168 | { 0x0000, 0x0000, 0x0000 }, /* R70 */ | ||
169 | { 0x0000, 0x0000, 0x0000 }, /* R71 */ | ||
170 | { 0x0000, 0x0000, 0x0000 }, /* R72 */ | ||
171 | { 0x0000, 0x0000, 0x0000 }, /* R73 */ | ||
172 | { 0x0000, 0x0000, 0x0000 }, /* R74 */ | ||
173 | { 0x0000, 0x0000, 0x0000 }, /* R75 */ | ||
174 | { 0x8000, 0x8000, 0x0000 }, /* R76 - Charge Pump (1) */ | ||
175 | { 0x0000, 0x0000, 0x0000 }, /* R77 */ | ||
176 | { 0x0000, 0x0000, 0x0000 }, /* R78 */ | ||
177 | { 0x0000, 0x0000, 0x0000 }, /* R79 */ | ||
178 | { 0x0000, 0x0000, 0x0000 }, /* R80 */ | ||
179 | { 0x0301, 0x0301, 0x0000 }, /* R81 - Class W (1) */ | ||
180 | { 0x0000, 0x0000, 0x0000 }, /* R82 */ | ||
181 | { 0x0000, 0x0000, 0x0000 }, /* R83 */ | ||
182 | { 0x333F, 0x333F, 0x0000 }, /* R84 - DC Servo (1) */ | ||
183 | { 0x0FEF, 0x0FEF, 0x0000 }, /* R85 - DC Servo (2) */ | ||
184 | { 0x0000, 0x0000, 0x0000 }, /* R86 */ | ||
185 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R87 - DC Servo (4) */ | ||
186 | { 0x0333, 0x0000, 0x0000 }, /* R88 - DC Servo Readback */ | ||
187 | { 0x0000, 0x0000, 0x0000 }, /* R89 */ | ||
188 | { 0x0000, 0x0000, 0x0000 }, /* R90 */ | ||
189 | { 0x0000, 0x0000, 0x0000 }, /* R91 */ | ||
190 | { 0x0000, 0x0000, 0x0000 }, /* R92 */ | ||
191 | { 0x0000, 0x0000, 0x0000 }, /* R93 */ | ||
192 | { 0x0000, 0x0000, 0x0000 }, /* R94 */ | ||
193 | { 0x0000, 0x0000, 0x0000 }, /* R95 */ | ||
194 | { 0x00EE, 0x00EE, 0x0000 }, /* R96 - Analogue HP (1) */ | ||
195 | { 0x0000, 0x0000, 0x0000 }, /* R97 */ | ||
196 | { 0x0000, 0x0000, 0x0000 }, /* R98 */ | ||
197 | { 0x0000, 0x0000, 0x0000 }, /* R99 */ | ||
198 | { 0x0000, 0x0000, 0x0000 }, /* R100 */ | ||
199 | { 0x0000, 0x0000, 0x0000 }, /* R101 */ | ||
200 | { 0x0000, 0x0000, 0x0000 }, /* R102 */ | ||
201 | { 0x0000, 0x0000, 0x0000 }, /* R103 */ | ||
202 | { 0x0000, 0x0000, 0x0000 }, /* R104 */ | ||
203 | { 0x0000, 0x0000, 0x0000 }, /* R105 */ | ||
204 | { 0x0000, 0x0000, 0x0000 }, /* R106 */ | ||
205 | { 0x0000, 0x0000, 0x0000 }, /* R107 */ | ||
206 | { 0x0000, 0x0000, 0x0000 }, /* R108 */ | ||
207 | { 0x0000, 0x0000, 0x0000 }, /* R109 */ | ||
208 | { 0x0000, 0x0000, 0x0000 }, /* R110 */ | ||
209 | { 0x0000, 0x0000, 0x0000 }, /* R111 */ | ||
210 | { 0x0000, 0x0000, 0x0000 }, /* R112 */ | ||
211 | { 0x0000, 0x0000, 0x0000 }, /* R113 */ | ||
212 | { 0x0000, 0x0000, 0x0000 }, /* R114 */ | ||
213 | { 0x0000, 0x0000, 0x0000 }, /* R115 */ | ||
214 | { 0x0000, 0x0000, 0x0000 }, /* R116 */ | ||
215 | { 0x0000, 0x0000, 0x0000 }, /* R117 */ | ||
216 | { 0x0000, 0x0000, 0x0000 }, /* R118 */ | ||
217 | { 0x0000, 0x0000, 0x0000 }, /* R119 */ | ||
218 | { 0x0000, 0x0000, 0x0000 }, /* R120 */ | ||
219 | { 0x0000, 0x0000, 0x0000 }, /* R121 */ | ||
220 | { 0x0000, 0x0000, 0x0000 }, /* R122 */ | ||
221 | { 0x0000, 0x0000, 0x0000 }, /* R123 */ | ||
222 | { 0x0000, 0x0000, 0x0000 }, /* R124 */ | ||
223 | { 0x0000, 0x0000, 0x0000 }, /* R125 */ | ||
224 | { 0x0000, 0x0000, 0x0000 }, /* R126 */ | ||
225 | { 0x0000, 0x0000, 0x0000 }, /* R127 */ | ||
226 | { 0x0000, 0x0000, 0x0000 }, /* R128 */ | ||
227 | { 0x0000, 0x0000, 0x0000 }, /* R129 */ | ||
228 | { 0x0000, 0x0000, 0x0000 }, /* R130 */ | ||
229 | { 0x0000, 0x0000, 0x0000 }, /* R131 */ | ||
230 | { 0x0000, 0x0000, 0x0000 }, /* R132 */ | ||
231 | { 0x0000, 0x0000, 0x0000 }, /* R133 */ | ||
232 | { 0x0000, 0x0000, 0x0000 }, /* R134 */ | ||
233 | { 0x0000, 0x0000, 0x0000 }, /* R135 */ | ||
234 | { 0x0000, 0x0000, 0x0000 }, /* R136 */ | ||
235 | { 0x0000, 0x0000, 0x0000 }, /* R137 */ | ||
236 | { 0x0000, 0x0000, 0x0000 }, /* R138 */ | ||
237 | { 0x0000, 0x0000, 0x0000 }, /* R139 */ | ||
238 | { 0x0000, 0x0000, 0x0000 }, /* R140 */ | ||
239 | { 0x0000, 0x0000, 0x0000 }, /* R141 */ | ||
240 | { 0x0000, 0x0000, 0x0000 }, /* R142 */ | ||
241 | { 0x0000, 0x0000, 0x0000 }, /* R143 */ | ||
242 | { 0x0000, 0x0000, 0x0000 }, /* R144 */ | ||
243 | { 0x0000, 0x0000, 0x0000 }, /* R145 */ | ||
244 | { 0x0000, 0x0000, 0x0000 }, /* R146 */ | ||
245 | { 0x0000, 0x0000, 0x0000 }, /* R147 */ | ||
246 | { 0x0000, 0x0000, 0x0000 }, /* R148 */ | ||
247 | { 0x0000, 0x0000, 0x0000 }, /* R149 */ | ||
248 | { 0x0000, 0x0000, 0x0000 }, /* R150 */ | ||
249 | { 0x0000, 0x0000, 0x0000 }, /* R151 */ | ||
250 | { 0x0000, 0x0000, 0x0000 }, /* R152 */ | ||
251 | { 0x0000, 0x0000, 0x0000 }, /* R153 */ | ||
252 | { 0x0000, 0x0000, 0x0000 }, /* R154 */ | ||
253 | { 0x0000, 0x0000, 0x0000 }, /* R155 */ | ||
254 | { 0x0000, 0x0000, 0x0000 }, /* R156 */ | ||
255 | { 0x0000, 0x0000, 0x0000 }, /* R157 */ | ||
256 | { 0x0000, 0x0000, 0x0000 }, /* R158 */ | ||
257 | { 0x0000, 0x0000, 0x0000 }, /* R159 */ | ||
258 | { 0x0000, 0x0000, 0x0000 }, /* R160 */ | ||
259 | { 0x0000, 0x0000, 0x0000 }, /* R161 */ | ||
260 | { 0x0000, 0x0000, 0x0000 }, /* R162 */ | ||
261 | { 0x0000, 0x0000, 0x0000 }, /* R163 */ | ||
262 | { 0x0000, 0x0000, 0x0000 }, /* R164 */ | ||
263 | { 0x0000, 0x0000, 0x0000 }, /* R165 */ | ||
264 | { 0x0000, 0x0000, 0x0000 }, /* R166 */ | ||
265 | { 0x0000, 0x0000, 0x0000 }, /* R167 */ | ||
266 | { 0x0000, 0x0000, 0x0000 }, /* R168 */ | ||
267 | { 0x0000, 0x0000, 0x0000 }, /* R169 */ | ||
268 | { 0x0000, 0x0000, 0x0000 }, /* R170 */ | ||
269 | { 0x0000, 0x0000, 0x0000 }, /* R171 */ | ||
270 | { 0x0000, 0x0000, 0x0000 }, /* R172 */ | ||
271 | { 0x0000, 0x0000, 0x0000 }, /* R173 */ | ||
272 | { 0x0000, 0x0000, 0x0000 }, /* R174 */ | ||
273 | { 0x0000, 0x0000, 0x0000 }, /* R175 */ | ||
274 | { 0x0000, 0x0000, 0x0000 }, /* R176 */ | ||
275 | { 0x0000, 0x0000, 0x0000 }, /* R177 */ | ||
276 | { 0x0000, 0x0000, 0x0000 }, /* R178 */ | ||
277 | { 0x0000, 0x0000, 0x0000 }, /* R179 */ | ||
278 | { 0x0000, 0x0000, 0x0000 }, /* R180 */ | ||
279 | { 0x0000, 0x0000, 0x0000 }, /* R181 */ | ||
280 | { 0x0000, 0x0000, 0x0000 }, /* R182 */ | ||
281 | { 0x0000, 0x0000, 0x0000 }, /* R183 */ | ||
282 | { 0x0000, 0x0000, 0x0000 }, /* R184 */ | ||
283 | { 0x0000, 0x0000, 0x0000 }, /* R185 */ | ||
284 | { 0x0000, 0x0000, 0x0000 }, /* R186 */ | ||
285 | { 0x0000, 0x0000, 0x0000 }, /* R187 */ | ||
286 | { 0x0000, 0x0000, 0x0000 }, /* R188 */ | ||
287 | { 0x0000, 0x0000, 0x0000 }, /* R189 */ | ||
288 | { 0x0000, 0x0000, 0x0000 }, /* R190 */ | ||
289 | { 0x0000, 0x0000, 0x0000 }, /* R191 */ | ||
290 | { 0x0000, 0x0000, 0x0000 }, /* R192 */ | ||
291 | { 0x0000, 0x0000, 0x0000 }, /* R193 */ | ||
292 | { 0x0000, 0x0000, 0x0000 }, /* R194 */ | ||
293 | { 0x0000, 0x0000, 0x0000 }, /* R195 */ | ||
294 | { 0x0000, 0x0000, 0x0000 }, /* R196 */ | ||
295 | { 0x0000, 0x0000, 0x0000 }, /* R197 */ | ||
296 | { 0x0000, 0x0000, 0x0000 }, /* R198 */ | ||
297 | { 0x0000, 0x0000, 0x0000 }, /* R199 */ | ||
298 | { 0x0000, 0x0000, 0x0000 }, /* R200 */ | ||
299 | { 0x0000, 0x0000, 0x0000 }, /* R201 */ | ||
300 | { 0x0000, 0x0000, 0x0000 }, /* R202 */ | ||
301 | { 0x0000, 0x0000, 0x0000 }, /* R203 */ | ||
302 | { 0x0000, 0x0000, 0x0000 }, /* R204 */ | ||
303 | { 0x0000, 0x0000, 0x0000 }, /* R205 */ | ||
304 | { 0x0000, 0x0000, 0x0000 }, /* R206 */ | ||
305 | { 0x0000, 0x0000, 0x0000 }, /* R207 */ | ||
306 | { 0x0000, 0x0000, 0x0000 }, /* R208 */ | ||
307 | { 0x0000, 0x0000, 0x0000 }, /* R209 */ | ||
308 | { 0x0000, 0x0000, 0x0000 }, /* R210 */ | ||
309 | { 0x0000, 0x0000, 0x0000 }, /* R211 */ | ||
310 | { 0x0000, 0x0000, 0x0000 }, /* R212 */ | ||
311 | { 0x0000, 0x0000, 0x0000 }, /* R213 */ | ||
312 | { 0x0000, 0x0000, 0x0000 }, /* R214 */ | ||
313 | { 0x0000, 0x0000, 0x0000 }, /* R215 */ | ||
314 | { 0x0000, 0x0000, 0x0000 }, /* R216 */ | ||
315 | { 0x0000, 0x0000, 0x0000 }, /* R217 */ | ||
316 | { 0x0000, 0x0000, 0x0000 }, /* R218 */ | ||
317 | { 0x0000, 0x0000, 0x0000 }, /* R219 */ | ||
318 | { 0x0000, 0x0000, 0x0000 }, /* R220 */ | ||
319 | { 0x0000, 0x0000, 0x0000 }, /* R221 */ | ||
320 | { 0x0000, 0x0000, 0x0000 }, /* R222 */ | ||
321 | { 0x0000, 0x0000, 0x0000 }, /* R223 */ | ||
322 | { 0x0000, 0x0000, 0x0000 }, /* R224 */ | ||
323 | { 0x0000, 0x0000, 0x0000 }, /* R225 */ | ||
324 | { 0x0000, 0x0000, 0x0000 }, /* R226 */ | ||
325 | { 0x0000, 0x0000, 0x0000 }, /* R227 */ | ||
326 | { 0x0000, 0x0000, 0x0000 }, /* R228 */ | ||
327 | { 0x0000, 0x0000, 0x0000 }, /* R229 */ | ||
328 | { 0x0000, 0x0000, 0x0000 }, /* R230 */ | ||
329 | { 0x0000, 0x0000, 0x0000 }, /* R231 */ | ||
330 | { 0x0000, 0x0000, 0x0000 }, /* R232 */ | ||
331 | { 0x0000, 0x0000, 0x0000 }, /* R233 */ | ||
332 | { 0x0000, 0x0000, 0x0000 }, /* R234 */ | ||
333 | { 0x0000, 0x0000, 0x0000 }, /* R235 */ | ||
334 | { 0x0000, 0x0000, 0x0000 }, /* R236 */ | ||
335 | { 0x0000, 0x0000, 0x0000 }, /* R237 */ | ||
336 | { 0x0000, 0x0000, 0x0000 }, /* R238 */ | ||
337 | { 0x0000, 0x0000, 0x0000 }, /* R239 */ | ||
338 | { 0x0000, 0x0000, 0x0000 }, /* R240 */ | ||
339 | { 0x0000, 0x0000, 0x0000 }, /* R241 */ | ||
340 | { 0x0000, 0x0000, 0x0000 }, /* R242 */ | ||
341 | { 0x0000, 0x0000, 0x0000 }, /* R243 */ | ||
342 | { 0x0000, 0x0000, 0x0000 }, /* R244 */ | ||
343 | { 0x0000, 0x0000, 0x0000 }, /* R245 */ | ||
344 | { 0x0000, 0x0000, 0x0000 }, /* R246 */ | ||
345 | { 0x0000, 0x0000, 0x0000 }, /* R247 */ | ||
346 | { 0x0000, 0x0000, 0x0000 }, /* R248 */ | ||
347 | { 0x0000, 0x0000, 0x0000 }, /* R249 */ | ||
348 | { 0x0000, 0x0000, 0x0000 }, /* R250 */ | ||
349 | { 0x0000, 0x0000, 0x0000 }, /* R251 */ | ||
350 | { 0x0000, 0x0000, 0x0000 }, /* R252 */ | ||
351 | { 0x0000, 0x0000, 0x0000 }, /* R253 */ | ||
352 | { 0x0000, 0x0000, 0x0000 }, /* R254 */ | ||
353 | { 0x0000, 0x0000, 0x0000 }, /* R255 */ | ||
354 | { 0x000F, 0x0000, 0x0000 }, /* R256 - Chip Revision */ | ||
355 | { 0x0074, 0x0074, 0x0000 }, /* R257 - Control Interface */ | ||
356 | { 0x0000, 0x0000, 0x0000 }, /* R258 */ | ||
357 | { 0x0000, 0x0000, 0x0000 }, /* R259 */ | ||
358 | { 0x0000, 0x0000, 0x0000 }, /* R260 */ | ||
359 | { 0x0000, 0x0000, 0x0000 }, /* R261 */ | ||
360 | { 0x0000, 0x0000, 0x0000 }, /* R262 */ | ||
361 | { 0x0000, 0x0000, 0x0000 }, /* R263 */ | ||
362 | { 0x0000, 0x0000, 0x0000 }, /* R264 */ | ||
363 | { 0x0000, 0x0000, 0x0000 }, /* R265 */ | ||
364 | { 0x0000, 0x0000, 0x0000 }, /* R266 */ | ||
365 | { 0x0000, 0x0000, 0x0000 }, /* R267 */ | ||
366 | { 0x0000, 0x0000, 0x0000 }, /* R268 */ | ||
367 | { 0x0000, 0x0000, 0x0000 }, /* R269 */ | ||
368 | { 0x0000, 0x0000, 0x0000 }, /* R270 */ | ||
369 | { 0x0000, 0x0000, 0x0000 }, /* R271 */ | ||
370 | { 0x807F, 0x837F, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ | ||
371 | { 0x017F, 0x0000, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ | ||
372 | { 0x0000, 0x0000, 0x0000 }, /* R274 */ | ||
373 | { 0x0000, 0x0000, 0x0000 }, /* R275 */ | ||
374 | { 0x0000, 0x0000, 0x0000 }, /* R276 */ | ||
375 | { 0x0000, 0x0000, 0x0000 }, /* R277 */ | ||
376 | { 0x0000, 0x0000, 0x0000 }, /* R278 */ | ||
377 | { 0x0000, 0x0000, 0x0000 }, /* R279 */ | ||
378 | { 0x0000, 0x0000, 0x0000 }, /* R280 */ | ||
379 | { 0x0000, 0x0000, 0x0000 }, /* R281 */ | ||
380 | { 0x0000, 0x0000, 0x0000 }, /* R282 */ | ||
381 | { 0x0000, 0x0000, 0x0000 }, /* R283 */ | ||
382 | { 0x0000, 0x0000, 0x0000 }, /* R284 */ | ||
383 | { 0x0000, 0x0000, 0x0000 }, /* R285 */ | ||
384 | { 0x0000, 0x0000, 0x0000 }, /* R286 */ | ||
385 | { 0x0000, 0x0000, 0x0000 }, /* R287 */ | ||
386 | { 0x0000, 0x0000, 0x0000 }, /* R288 */ | ||
387 | { 0x0000, 0x0000, 0x0000 }, /* R289 */ | ||
388 | { 0x0000, 0x0000, 0x0000 }, /* R290 */ | ||
389 | { 0x0000, 0x0000, 0x0000 }, /* R291 */ | ||
390 | { 0x0000, 0x0000, 0x0000 }, /* R292 */ | ||
391 | { 0x0000, 0x0000, 0x0000 }, /* R293 */ | ||
392 | { 0x0000, 0x0000, 0x0000 }, /* R294 */ | ||
393 | { 0x0000, 0x0000, 0x0000 }, /* R295 */ | ||
394 | { 0x0000, 0x0000, 0x0000 }, /* R296 */ | ||
395 | { 0x0000, 0x0000, 0x0000 }, /* R297 */ | ||
396 | { 0x0000, 0x0000, 0x0000 }, /* R298 */ | ||
397 | { 0x0000, 0x0000, 0x0000 }, /* R299 */ | ||
398 | { 0x0000, 0x0000, 0x0000 }, /* R300 */ | ||
399 | { 0x0000, 0x0000, 0x0000 }, /* R301 */ | ||
400 | { 0x0000, 0x0000, 0x0000 }, /* R302 */ | ||
401 | { 0x0000, 0x0000, 0x0000 }, /* R303 */ | ||
402 | { 0x0000, 0x0000, 0x0000 }, /* R304 */ | ||
403 | { 0x0000, 0x0000, 0x0000 }, /* R305 */ | ||
404 | { 0x0000, 0x0000, 0x0000 }, /* R306 */ | ||
405 | { 0x0000, 0x0000, 0x0000 }, /* R307 */ | ||
406 | { 0x0000, 0x0000, 0x0000 }, /* R308 */ | ||
407 | { 0x0000, 0x0000, 0x0000 }, /* R309 */ | ||
408 | { 0x0000, 0x0000, 0x0000 }, /* R310 */ | ||
409 | { 0x0000, 0x0000, 0x0000 }, /* R311 */ | ||
410 | { 0x0000, 0x0000, 0x0000 }, /* R312 */ | ||
411 | { 0x0000, 0x0000, 0x0000 }, /* R313 */ | ||
412 | { 0x0000, 0x0000, 0x0000 }, /* R314 */ | ||
413 | { 0x0000, 0x0000, 0x0000 }, /* R315 */ | ||
414 | { 0x0000, 0x0000, 0x0000 }, /* R316 */ | ||
415 | { 0x0000, 0x0000, 0x0000 }, /* R317 */ | ||
416 | { 0x0000, 0x0000, 0x0000 }, /* R318 */ | ||
417 | { 0x0000, 0x0000, 0x0000 }, /* R319 */ | ||
418 | { 0x0000, 0x0000, 0x0000 }, /* R320 */ | ||
419 | { 0x0000, 0x0000, 0x0000 }, /* R321 */ | ||
420 | { 0x0000, 0x0000, 0x0000 }, /* R322 */ | ||
421 | { 0x0000, 0x0000, 0x0000 }, /* R323 */ | ||
422 | { 0x0000, 0x0000, 0x0000 }, /* R324 */ | ||
423 | { 0x0000, 0x0000, 0x0000 }, /* R325 */ | ||
424 | { 0x0000, 0x0000, 0x0000 }, /* R326 */ | ||
425 | { 0x0000, 0x0000, 0x0000 }, /* R327 */ | ||
426 | { 0x0000, 0x0000, 0x0000 }, /* R328 */ | ||
427 | { 0x0000, 0x0000, 0x0000 }, /* R329 */ | ||
428 | { 0x0000, 0x0000, 0x0000 }, /* R330 */ | ||
429 | { 0x0000, 0x0000, 0x0000 }, /* R331 */ | ||
430 | { 0x0000, 0x0000, 0x0000 }, /* R332 */ | ||
431 | { 0x0000, 0x0000, 0x0000 }, /* R333 */ | ||
432 | { 0x0000, 0x0000, 0x0000 }, /* R334 */ | ||
433 | { 0x0000, 0x0000, 0x0000 }, /* R335 */ | ||
434 | { 0x0000, 0x0000, 0x0000 }, /* R336 */ | ||
435 | { 0x0000, 0x0000, 0x0000 }, /* R337 */ | ||
436 | { 0x0000, 0x0000, 0x0000 }, /* R338 */ | ||
437 | { 0x0000, 0x0000, 0x0000 }, /* R339 */ | ||
438 | { 0x0000, 0x0000, 0x0000 }, /* R340 */ | ||
439 | { 0x0000, 0x0000, 0x0000 }, /* R341 */ | ||
440 | { 0x0000, 0x0000, 0x0000 }, /* R342 */ | ||
441 | { 0x0000, 0x0000, 0x0000 }, /* R343 */ | ||
442 | { 0x0000, 0x0000, 0x0000 }, /* R344 */ | ||
443 | { 0x0000, 0x0000, 0x0000 }, /* R345 */ | ||
444 | { 0x0000, 0x0000, 0x0000 }, /* R346 */ | ||
445 | { 0x0000, 0x0000, 0x0000 }, /* R347 */ | ||
446 | { 0x0000, 0x0000, 0x0000 }, /* R348 */ | ||
447 | { 0x0000, 0x0000, 0x0000 }, /* R349 */ | ||
448 | { 0x0000, 0x0000, 0x0000 }, /* R350 */ | ||
449 | { 0x0000, 0x0000, 0x0000 }, /* R351 */ | ||
450 | { 0x0000, 0x0000, 0x0000 }, /* R352 */ | ||
451 | { 0x0000, 0x0000, 0x0000 }, /* R353 */ | ||
452 | { 0x0000, 0x0000, 0x0000 }, /* R354 */ | ||
453 | { 0x0000, 0x0000, 0x0000 }, /* R355 */ | ||
454 | { 0x0000, 0x0000, 0x0000 }, /* R356 */ | ||
455 | { 0x0000, 0x0000, 0x0000 }, /* R357 */ | ||
456 | { 0x0000, 0x0000, 0x0000 }, /* R358 */ | ||
457 | { 0x0000, 0x0000, 0x0000 }, /* R359 */ | ||
458 | { 0x0000, 0x0000, 0x0000 }, /* R360 */ | ||
459 | { 0x0000, 0x0000, 0x0000 }, /* R361 */ | ||
460 | { 0x0000, 0x0000, 0x0000 }, /* R362 */ | ||
461 | { 0x0000, 0x0000, 0x0000 }, /* R363 */ | ||
462 | { 0x0000, 0x0000, 0x0000 }, /* R364 */ | ||
463 | { 0x0000, 0x0000, 0x0000 }, /* R365 */ | ||
464 | { 0x0000, 0x0000, 0x0000 }, /* R366 */ | ||
465 | { 0x0000, 0x0000, 0x0000 }, /* R367 */ | ||
466 | { 0x0000, 0x0000, 0x0000 }, /* R368 */ | ||
467 | { 0x0000, 0x0000, 0x0000 }, /* R369 */ | ||
468 | { 0x0000, 0x0000, 0x0000 }, /* R370 */ | ||
469 | { 0x0000, 0x0000, 0x0000 }, /* R371 */ | ||
470 | { 0x0000, 0x0000, 0x0000 }, /* R372 */ | ||
471 | { 0x0000, 0x0000, 0x0000 }, /* R373 */ | ||
472 | { 0x0000, 0x0000, 0x0000 }, /* R374 */ | ||
473 | { 0x0000, 0x0000, 0x0000 }, /* R375 */ | ||
474 | { 0x0000, 0x0000, 0x0000 }, /* R376 */ | ||
475 | { 0x0000, 0x0000, 0x0000 }, /* R377 */ | ||
476 | { 0x0000, 0x0000, 0x0000 }, /* R378 */ | ||
477 | { 0x0000, 0x0000, 0x0000 }, /* R379 */ | ||
478 | { 0x0000, 0x0000, 0x0000 }, /* R380 */ | ||
479 | { 0x0000, 0x0000, 0x0000 }, /* R381 */ | ||
480 | { 0x0000, 0x0000, 0x0000 }, /* R382 */ | ||
481 | { 0x0000, 0x0000, 0x0000 }, /* R383 */ | ||
482 | { 0x0000, 0x0000, 0x0000 }, /* R384 */ | ||
483 | { 0x0000, 0x0000, 0x0000 }, /* R385 */ | ||
484 | { 0x0000, 0x0000, 0x0000 }, /* R386 */ | ||
485 | { 0x0000, 0x0000, 0x0000 }, /* R387 */ | ||
486 | { 0x0000, 0x0000, 0x0000 }, /* R388 */ | ||
487 | { 0x0000, 0x0000, 0x0000 }, /* R389 */ | ||
488 | { 0x0000, 0x0000, 0x0000 }, /* R390 */ | ||
489 | { 0x0000, 0x0000, 0x0000 }, /* R391 */ | ||
490 | { 0x0000, 0x0000, 0x0000 }, /* R392 */ | ||
491 | { 0x0000, 0x0000, 0x0000 }, /* R393 */ | ||
492 | { 0x0000, 0x0000, 0x0000 }, /* R394 */ | ||
493 | { 0x0000, 0x0000, 0x0000 }, /* R395 */ | ||
494 | { 0x0000, 0x0000, 0x0000 }, /* R396 */ | ||
495 | { 0x0000, 0x0000, 0x0000 }, /* R397 */ | ||
496 | { 0x0000, 0x0000, 0x0000 }, /* R398 */ | ||
497 | { 0x0000, 0x0000, 0x0000 }, /* R399 */ | ||
498 | { 0x0000, 0x0000, 0x0000 }, /* R400 */ | ||
499 | { 0x0000, 0x0000, 0x0000 }, /* R401 */ | ||
500 | { 0x0000, 0x0000, 0x0000 }, /* R402 */ | ||
501 | { 0x0000, 0x0000, 0x0000 }, /* R403 */ | ||
502 | { 0x0000, 0x0000, 0x0000 }, /* R404 */ | ||
503 | { 0x0000, 0x0000, 0x0000 }, /* R405 */ | ||
504 | { 0x0000, 0x0000, 0x0000 }, /* R406 */ | ||
505 | { 0x0000, 0x0000, 0x0000 }, /* R407 */ | ||
506 | { 0x0000, 0x0000, 0x0000 }, /* R408 */ | ||
507 | { 0x0000, 0x0000, 0x0000 }, /* R409 */ | ||
508 | { 0x0000, 0x0000, 0x0000 }, /* R410 */ | ||
509 | { 0x0000, 0x0000, 0x0000 }, /* R411 */ | ||
510 | { 0x0000, 0x0000, 0x0000 }, /* R412 */ | ||
511 | { 0x0000, 0x0000, 0x0000 }, /* R413 */ | ||
512 | { 0x0000, 0x0000, 0x0000 }, /* R414 */ | ||
513 | { 0x0000, 0x0000, 0x0000 }, /* R415 */ | ||
514 | { 0x0000, 0x0000, 0x0000 }, /* R416 */ | ||
515 | { 0x0000, 0x0000, 0x0000 }, /* R417 */ | ||
516 | { 0x0000, 0x0000, 0x0000 }, /* R418 */ | ||
517 | { 0x0000, 0x0000, 0x0000 }, /* R419 */ | ||
518 | { 0x0000, 0x0000, 0x0000 }, /* R420 */ | ||
519 | { 0x0000, 0x0000, 0x0000 }, /* R421 */ | ||
520 | { 0x0000, 0x0000, 0x0000 }, /* R422 */ | ||
521 | { 0x0000, 0x0000, 0x0000 }, /* R423 */ | ||
522 | { 0x0000, 0x0000, 0x0000 }, /* R424 */ | ||
523 | { 0x0000, 0x0000, 0x0000 }, /* R425 */ | ||
524 | { 0x0000, 0x0000, 0x0000 }, /* R426 */ | ||
525 | { 0x0000, 0x0000, 0x0000 }, /* R427 */ | ||
526 | { 0x0000, 0x0000, 0x0000 }, /* R428 */ | ||
527 | { 0x0000, 0x0000, 0x0000 }, /* R429 */ | ||
528 | { 0x0000, 0x0000, 0x0000 }, /* R430 */ | ||
529 | { 0x0000, 0x0000, 0x0000 }, /* R431 */ | ||
530 | { 0x0000, 0x0000, 0x0000 }, /* R432 */ | ||
531 | { 0x0000, 0x0000, 0x0000 }, /* R433 */ | ||
532 | { 0x0000, 0x0000, 0x0000 }, /* R434 */ | ||
533 | { 0x0000, 0x0000, 0x0000 }, /* R435 */ | ||
534 | { 0x0000, 0x0000, 0x0000 }, /* R436 */ | ||
535 | { 0x0000, 0x0000, 0x0000 }, /* R437 */ | ||
536 | { 0x0000, 0x0000, 0x0000 }, /* R438 */ | ||
537 | { 0x0000, 0x0000, 0x0000 }, /* R439 */ | ||
538 | { 0x0000, 0x0000, 0x0000 }, /* R440 */ | ||
539 | { 0x0000, 0x0000, 0x0000 }, /* R441 */ | ||
540 | { 0x0000, 0x0000, 0x0000 }, /* R442 */ | ||
541 | { 0x0000, 0x0000, 0x0000 }, /* R443 */ | ||
542 | { 0x0000, 0x0000, 0x0000 }, /* R444 */ | ||
543 | { 0x0000, 0x0000, 0x0000 }, /* R445 */ | ||
544 | { 0x0000, 0x0000, 0x0000 }, /* R446 */ | ||
545 | { 0x0000, 0x0000, 0x0000 }, /* R447 */ | ||
546 | { 0x0000, 0x0000, 0x0000 }, /* R448 */ | ||
547 | { 0x0000, 0x0000, 0x0000 }, /* R449 */ | ||
548 | { 0x0000, 0x0000, 0x0000 }, /* R450 */ | ||
549 | { 0x0000, 0x0000, 0x0000 }, /* R451 */ | ||
550 | { 0x0000, 0x0000, 0x0000 }, /* R452 */ | ||
551 | { 0x0000, 0x0000, 0x0000 }, /* R453 */ | ||
552 | { 0x0000, 0x0000, 0x0000 }, /* R454 */ | ||
553 | { 0x0000, 0x0000, 0x0000 }, /* R455 */ | ||
554 | { 0x0000, 0x0000, 0x0000 }, /* R456 */ | ||
555 | { 0x0000, 0x0000, 0x0000 }, /* R457 */ | ||
556 | { 0x0000, 0x0000, 0x0000 }, /* R458 */ | ||
557 | { 0x0000, 0x0000, 0x0000 }, /* R459 */ | ||
558 | { 0x0000, 0x0000, 0x0000 }, /* R460 */ | ||
559 | { 0x0000, 0x0000, 0x0000 }, /* R461 */ | ||
560 | { 0x0000, 0x0000, 0x0000 }, /* R462 */ | ||
561 | { 0x0000, 0x0000, 0x0000 }, /* R463 */ | ||
562 | { 0x0000, 0x0000, 0x0000 }, /* R464 */ | ||
563 | { 0x0000, 0x0000, 0x0000 }, /* R465 */ | ||
564 | { 0x0000, 0x0000, 0x0000 }, /* R466 */ | ||
565 | { 0x0000, 0x0000, 0x0000 }, /* R467 */ | ||
566 | { 0x0000, 0x0000, 0x0000 }, /* R468 */ | ||
567 | { 0x0000, 0x0000, 0x0000 }, /* R469 */ | ||
568 | { 0x0000, 0x0000, 0x0000 }, /* R470 */ | ||
569 | { 0x0000, 0x0000, 0x0000 }, /* R471 */ | ||
570 | { 0x0000, 0x0000, 0x0000 }, /* R472 */ | ||
571 | { 0x0000, 0x0000, 0x0000 }, /* R473 */ | ||
572 | { 0x0000, 0x0000, 0x0000 }, /* R474 */ | ||
573 | { 0x0000, 0x0000, 0x0000 }, /* R475 */ | ||
574 | { 0x0000, 0x0000, 0x0000 }, /* R476 */ | ||
575 | { 0x0000, 0x0000, 0x0000 }, /* R477 */ | ||
576 | { 0x0000, 0x0000, 0x0000 }, /* R478 */ | ||
577 | { 0x0000, 0x0000, 0x0000 }, /* R479 */ | ||
578 | { 0x0000, 0x0000, 0x0000 }, /* R480 */ | ||
579 | { 0x0000, 0x0000, 0x0000 }, /* R481 */ | ||
580 | { 0x0000, 0x0000, 0x0000 }, /* R482 */ | ||
581 | { 0x0000, 0x0000, 0x0000 }, /* R483 */ | ||
582 | { 0x0000, 0x0000, 0x0000 }, /* R484 */ | ||
583 | { 0x0000, 0x0000, 0x0000 }, /* R485 */ | ||
584 | { 0x0000, 0x0000, 0x0000 }, /* R486 */ | ||
585 | { 0x0000, 0x0000, 0x0000 }, /* R487 */ | ||
586 | { 0x0000, 0x0000, 0x0000 }, /* R488 */ | ||
587 | { 0x0000, 0x0000, 0x0000 }, /* R489 */ | ||
588 | { 0x0000, 0x0000, 0x0000 }, /* R490 */ | ||
589 | { 0x0000, 0x0000, 0x0000 }, /* R491 */ | ||
590 | { 0x0000, 0x0000, 0x0000 }, /* R492 */ | ||
591 | { 0x0000, 0x0000, 0x0000 }, /* R493 */ | ||
592 | { 0x0000, 0x0000, 0x0000 }, /* R494 */ | ||
593 | { 0x0000, 0x0000, 0x0000 }, /* R495 */ | ||
594 | { 0x0000, 0x0000, 0x0000 }, /* R496 */ | ||
595 | { 0x0000, 0x0000, 0x0000 }, /* R497 */ | ||
596 | { 0x0000, 0x0000, 0x0000 }, /* R498 */ | ||
597 | { 0x0000, 0x0000, 0x0000 }, /* R499 */ | ||
598 | { 0x0000, 0x0000, 0x0000 }, /* R500 */ | ||
599 | { 0x0000, 0x0000, 0x0000 }, /* R501 */ | ||
600 | { 0x0000, 0x0000, 0x0000 }, /* R502 */ | ||
601 | { 0x0000, 0x0000, 0x0000 }, /* R503 */ | ||
602 | { 0x0000, 0x0000, 0x0000 }, /* R504 */ | ||
603 | { 0x0000, 0x0000, 0x0000 }, /* R505 */ | ||
604 | { 0x0000, 0x0000, 0x0000 }, /* R506 */ | ||
605 | { 0x0000, 0x0000, 0x0000 }, /* R507 */ | ||
606 | { 0x0000, 0x0000, 0x0000 }, /* R508 */ | ||
607 | { 0x0000, 0x0000, 0x0000 }, /* R509 */ | ||
608 | { 0x0000, 0x0000, 0x0000 }, /* R510 */ | ||
609 | { 0x0000, 0x0000, 0x0000 }, /* R511 */ | ||
610 | { 0x001F, 0x001F, 0x0000 }, /* R512 - AIF1 Clocking (1) */ | ||
611 | { 0x003F, 0x003F, 0x0000 }, /* R513 - AIF1 Clocking (2) */ | ||
612 | { 0x0000, 0x0000, 0x0000 }, /* R514 */ | ||
613 | { 0x0000, 0x0000, 0x0000 }, /* R515 */ | ||
614 | { 0x001F, 0x001F, 0x0000 }, /* R516 - AIF2 Clocking (1) */ | ||
615 | { 0x003F, 0x003F, 0x0000 }, /* R517 - AIF2 Clocking (2) */ | ||
616 | { 0x0000, 0x0000, 0x0000 }, /* R518 */ | ||
617 | { 0x0000, 0x0000, 0x0000 }, /* R519 */ | ||
618 | { 0x001F, 0x001F, 0x0000 }, /* R520 - Clocking (1) */ | ||
619 | { 0x0777, 0x0777, 0x0000 }, /* R521 - Clocking (2) */ | ||
620 | { 0x0000, 0x0000, 0x0000 }, /* R522 */ | ||
621 | { 0x0000, 0x0000, 0x0000 }, /* R523 */ | ||
622 | { 0x0000, 0x0000, 0x0000 }, /* R524 */ | ||
623 | { 0x0000, 0x0000, 0x0000 }, /* R525 */ | ||
624 | { 0x0000, 0x0000, 0x0000 }, /* R526 */ | ||
625 | { 0x0000, 0x0000, 0x0000 }, /* R527 */ | ||
626 | { 0x00FF, 0x00FF, 0x0000 }, /* R528 - AIF1 Rate */ | ||
627 | { 0x00FF, 0x00FF, 0x0000 }, /* R529 - AIF2 Rate */ | ||
628 | { 0x000F, 0x0000, 0x0000 }, /* R530 - Rate Status */ | ||
629 | { 0x0000, 0x0000, 0x0000 }, /* R531 */ | ||
630 | { 0x0000, 0x0000, 0x0000 }, /* R532 */ | ||
631 | { 0x0000, 0x0000, 0x0000 }, /* R533 */ | ||
632 | { 0x0000, 0x0000, 0x0000 }, /* R534 */ | ||
633 | { 0x0000, 0x0000, 0x0000 }, /* R535 */ | ||
634 | { 0x0000, 0x0000, 0x0000 }, /* R536 */ | ||
635 | { 0x0000, 0x0000, 0x0000 }, /* R537 */ | ||
636 | { 0x0000, 0x0000, 0x0000 }, /* R538 */ | ||
637 | { 0x0000, 0x0000, 0x0000 }, /* R539 */ | ||
638 | { 0x0000, 0x0000, 0x0000 }, /* R540 */ | ||
639 | { 0x0000, 0x0000, 0x0000 }, /* R541 */ | ||
640 | { 0x0000, 0x0000, 0x0000 }, /* R542 */ | ||
641 | { 0x0000, 0x0000, 0x0000 }, /* R543 */ | ||
642 | { 0x0007, 0x0007, 0x0000 }, /* R544 - FLL1 Control (1) */ | ||
643 | { 0x3F77, 0x3F77, 0x0000 }, /* R545 - FLL1 Control (2) */ | ||
644 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R546 - FLL1 Control (3) */ | ||
645 | { 0x7FEF, 0x7FEF, 0x0000 }, /* R547 - FLL1 Control (4) */ | ||
646 | { 0x1FDB, 0x1FDB, 0x0000 }, /* R548 - FLL1 Control (5) */ | ||
647 | { 0x0000, 0x0000, 0x0000 }, /* R549 */ | ||
648 | { 0x0000, 0x0000, 0x0000 }, /* R550 */ | ||
649 | { 0x0000, 0x0000, 0x0000 }, /* R551 */ | ||
650 | { 0x0000, 0x0000, 0x0000 }, /* R552 */ | ||
651 | { 0x0000, 0x0000, 0x0000 }, /* R553 */ | ||
652 | { 0x0000, 0x0000, 0x0000 }, /* R554 */ | ||
653 | { 0x0000, 0x0000, 0x0000 }, /* R555 */ | ||
654 | { 0x0000, 0x0000, 0x0000 }, /* R556 */ | ||
655 | { 0x0000, 0x0000, 0x0000 }, /* R557 */ | ||
656 | { 0x0000, 0x0000, 0x0000 }, /* R558 */ | ||
657 | { 0x0000, 0x0000, 0x0000 }, /* R559 */ | ||
658 | { 0x0000, 0x0000, 0x0000 }, /* R560 */ | ||
659 | { 0x0000, 0x0000, 0x0000 }, /* R561 */ | ||
660 | { 0x0000, 0x0000, 0x0000 }, /* R562 */ | ||
661 | { 0x0000, 0x0000, 0x0000 }, /* R563 */ | ||
662 | { 0x0000, 0x0000, 0x0000 }, /* R564 */ | ||
663 | { 0x0000, 0x0000, 0x0000 }, /* R565 */ | ||
664 | { 0x0000, 0x0000, 0x0000 }, /* R566 */ | ||
665 | { 0x0000, 0x0000, 0x0000 }, /* R567 */ | ||
666 | { 0x0000, 0x0000, 0x0000 }, /* R568 */ | ||
667 | { 0x0000, 0x0000, 0x0000 }, /* R569 */ | ||
668 | { 0x0000, 0x0000, 0x0000 }, /* R570 */ | ||
669 | { 0x0000, 0x0000, 0x0000 }, /* R571 */ | ||
670 | { 0x0000, 0x0000, 0x0000 }, /* R572 */ | ||
671 | { 0x0000, 0x0000, 0x0000 }, /* R573 */ | ||
672 | { 0x0000, 0x0000, 0x0000 }, /* R574 */ | ||
673 | { 0x0000, 0x0000, 0x0000 }, /* R575 */ | ||
674 | { 0x0007, 0x0007, 0x0000 }, /* R576 - FLL2 Control (1) */ | ||
675 | { 0x3F77, 0x3F77, 0x0000 }, /* R577 - FLL2 Control (2) */ | ||
676 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R578 - FLL2 Control (3) */ | ||
677 | { 0x7FEF, 0x7FEF, 0x0000 }, /* R579 - FLL2 Control (4) */ | ||
678 | { 0x1FDB, 0x1FDB, 0x0000 }, /* R580 - FLL2 Control (5) */ | ||
679 | { 0x0000, 0x0000, 0x0000 }, /* R581 */ | ||
680 | { 0x0000, 0x0000, 0x0000 }, /* R582 */ | ||
681 | { 0x0000, 0x0000, 0x0000 }, /* R583 */ | ||
682 | { 0x0000, 0x0000, 0x0000 }, /* R584 */ | ||
683 | { 0x0000, 0x0000, 0x0000 }, /* R585 */ | ||
684 | { 0x0000, 0x0000, 0x0000 }, /* R586 */ | ||
685 | { 0x0000, 0x0000, 0x0000 }, /* R587 */ | ||
686 | { 0x0000, 0x0000, 0x0000 }, /* R588 */ | ||
687 | { 0x0000, 0x0000, 0x0000 }, /* R589 */ | ||
688 | { 0x0000, 0x0000, 0x0000 }, /* R590 */ | ||
689 | { 0x0000, 0x0000, 0x0000 }, /* R591 */ | ||
690 | { 0x0000, 0x0000, 0x0000 }, /* R592 */ | ||
691 | { 0x0000, 0x0000, 0x0000 }, /* R593 */ | ||
692 | { 0x0000, 0x0000, 0x0000 }, /* R594 */ | ||
693 | { 0x0000, 0x0000, 0x0000 }, /* R595 */ | ||
694 | { 0x0000, 0x0000, 0x0000 }, /* R596 */ | ||
695 | { 0x0000, 0x0000, 0x0000 }, /* R597 */ | ||
696 | { 0x0000, 0x0000, 0x0000 }, /* R598 */ | ||
697 | { 0x0000, 0x0000, 0x0000 }, /* R599 */ | ||
698 | { 0x0000, 0x0000, 0x0000 }, /* R600 */ | ||
699 | { 0x0000, 0x0000, 0x0000 }, /* R601 */ | ||
700 | { 0x0000, 0x0000, 0x0000 }, /* R602 */ | ||
701 | { 0x0000, 0x0000, 0x0000 }, /* R603 */ | ||
702 | { 0x0000, 0x0000, 0x0000 }, /* R604 */ | ||
703 | { 0x0000, 0x0000, 0x0000 }, /* R605 */ | ||
704 | { 0x0000, 0x0000, 0x0000 }, /* R606 */ | ||
705 | { 0x0000, 0x0000, 0x0000 }, /* R607 */ | ||
706 | { 0x0000, 0x0000, 0x0000 }, /* R608 */ | ||
707 | { 0x0000, 0x0000, 0x0000 }, /* R609 */ | ||
708 | { 0x0000, 0x0000, 0x0000 }, /* R610 */ | ||
709 | { 0x0000, 0x0000, 0x0000 }, /* R611 */ | ||
710 | { 0x0000, 0x0000, 0x0000 }, /* R612 */ | ||
711 | { 0x0000, 0x0000, 0x0000 }, /* R613 */ | ||
712 | { 0x0000, 0x0000, 0x0000 }, /* R614 */ | ||
713 | { 0x0000, 0x0000, 0x0000 }, /* R615 */ | ||
714 | { 0x0000, 0x0000, 0x0000 }, /* R616 */ | ||
715 | { 0x0000, 0x0000, 0x0000 }, /* R617 */ | ||
716 | { 0x0000, 0x0000, 0x0000 }, /* R618 */ | ||
717 | { 0x0000, 0x0000, 0x0000 }, /* R619 */ | ||
718 | { 0x0000, 0x0000, 0x0000 }, /* R620 */ | ||
719 | { 0x0000, 0x0000, 0x0000 }, /* R621 */ | ||
720 | { 0x0000, 0x0000, 0x0000 }, /* R622 */ | ||
721 | { 0x0000, 0x0000, 0x0000 }, /* R623 */ | ||
722 | { 0x0000, 0x0000, 0x0000 }, /* R624 */ | ||
723 | { 0x0000, 0x0000, 0x0000 }, /* R625 */ | ||
724 | { 0x0000, 0x0000, 0x0000 }, /* R626 */ | ||
725 | { 0x0000, 0x0000, 0x0000 }, /* R627 */ | ||
726 | { 0x0000, 0x0000, 0x0000 }, /* R628 */ | ||
727 | { 0x0000, 0x0000, 0x0000 }, /* R629 */ | ||
728 | { 0x0000, 0x0000, 0x0000 }, /* R630 */ | ||
729 | { 0x0000, 0x0000, 0x0000 }, /* R631 */ | ||
730 | { 0x0000, 0x0000, 0x0000 }, /* R632 */ | ||
731 | { 0x0000, 0x0000, 0x0000 }, /* R633 */ | ||
732 | { 0x0000, 0x0000, 0x0000 }, /* R634 */ | ||
733 | { 0x0000, 0x0000, 0x0000 }, /* R635 */ | ||
734 | { 0x0000, 0x0000, 0x0000 }, /* R636 */ | ||
735 | { 0x0000, 0x0000, 0x0000 }, /* R637 */ | ||
736 | { 0x0000, 0x0000, 0x0000 }, /* R638 */ | ||
737 | { 0x0000, 0x0000, 0x0000 }, /* R639 */ | ||
738 | { 0x0000, 0x0000, 0x0000 }, /* R640 */ | ||
739 | { 0x0000, 0x0000, 0x0000 }, /* R641 */ | ||
740 | { 0x0000, 0x0000, 0x0000 }, /* R642 */ | ||
741 | { 0x0000, 0x0000, 0x0000 }, /* R643 */ | ||
742 | { 0x0000, 0x0000, 0x0000 }, /* R644 */ | ||
743 | { 0x0000, 0x0000, 0x0000 }, /* R645 */ | ||
744 | { 0x0000, 0x0000, 0x0000 }, /* R646 */ | ||
745 | { 0x0000, 0x0000, 0x0000 }, /* R647 */ | ||
746 | { 0x0000, 0x0000, 0x0000 }, /* R648 */ | ||
747 | { 0x0000, 0x0000, 0x0000 }, /* R649 */ | ||
748 | { 0x0000, 0x0000, 0x0000 }, /* R650 */ | ||
749 | { 0x0000, 0x0000, 0x0000 }, /* R651 */ | ||
750 | { 0x0000, 0x0000, 0x0000 }, /* R652 */ | ||
751 | { 0x0000, 0x0000, 0x0000 }, /* R653 */ | ||
752 | { 0x0000, 0x0000, 0x0000 }, /* R654 */ | ||
753 | { 0x0000, 0x0000, 0x0000 }, /* R655 */ | ||
754 | { 0x0000, 0x0000, 0x0000 }, /* R656 */ | ||
755 | { 0x0000, 0x0000, 0x0000 }, /* R657 */ | ||
756 | { 0x0000, 0x0000, 0x0000 }, /* R658 */ | ||
757 | { 0x0000, 0x0000, 0x0000 }, /* R659 */ | ||
758 | { 0x0000, 0x0000, 0x0000 }, /* R660 */ | ||
759 | { 0x0000, 0x0000, 0x0000 }, /* R661 */ | ||
760 | { 0x0000, 0x0000, 0x0000 }, /* R662 */ | ||
761 | { 0x0000, 0x0000, 0x0000 }, /* R663 */ | ||
762 | { 0x0000, 0x0000, 0x0000 }, /* R664 */ | ||
763 | { 0x0000, 0x0000, 0x0000 }, /* R665 */ | ||
764 | { 0x0000, 0x0000, 0x0000 }, /* R666 */ | ||
765 | { 0x0000, 0x0000, 0x0000 }, /* R667 */ | ||
766 | { 0x0000, 0x0000, 0x0000 }, /* R668 */ | ||
767 | { 0x0000, 0x0000, 0x0000 }, /* R669 */ | ||
768 | { 0x0000, 0x0000, 0x0000 }, /* R670 */ | ||
769 | { 0x0000, 0x0000, 0x0000 }, /* R671 */ | ||
770 | { 0x0000, 0x0000, 0x0000 }, /* R672 */ | ||
771 | { 0x0000, 0x0000, 0x0000 }, /* R673 */ | ||
772 | { 0x0000, 0x0000, 0x0000 }, /* R674 */ | ||
773 | { 0x0000, 0x0000, 0x0000 }, /* R675 */ | ||
774 | { 0x0000, 0x0000, 0x0000 }, /* R676 */ | ||
775 | { 0x0000, 0x0000, 0x0000 }, /* R677 */ | ||
776 | { 0x0000, 0x0000, 0x0000 }, /* R678 */ | ||
777 | { 0x0000, 0x0000, 0x0000 }, /* R679 */ | ||
778 | { 0x0000, 0x0000, 0x0000 }, /* R680 */ | ||
779 | { 0x0000, 0x0000, 0x0000 }, /* R681 */ | ||
780 | { 0x0000, 0x0000, 0x0000 }, /* R682 */ | ||
781 | { 0x0000, 0x0000, 0x0000 }, /* R683 */ | ||
782 | { 0x0000, 0x0000, 0x0000 }, /* R684 */ | ||
783 | { 0x0000, 0x0000, 0x0000 }, /* R685 */ | ||
784 | { 0x0000, 0x0000, 0x0000 }, /* R686 */ | ||
785 | { 0x0000, 0x0000, 0x0000 }, /* R687 */ | ||
786 | { 0x0000, 0x0000, 0x0000 }, /* R688 */ | ||
787 | { 0x0000, 0x0000, 0x0000 }, /* R689 */ | ||
788 | { 0x0000, 0x0000, 0x0000 }, /* R690 */ | ||
789 | { 0x0000, 0x0000, 0x0000 }, /* R691 */ | ||
790 | { 0x0000, 0x0000, 0x0000 }, /* R692 */ | ||
791 | { 0x0000, 0x0000, 0x0000 }, /* R693 */ | ||
792 | { 0x0000, 0x0000, 0x0000 }, /* R694 */ | ||
793 | { 0x0000, 0x0000, 0x0000 }, /* R695 */ | ||
794 | { 0x0000, 0x0000, 0x0000 }, /* R696 */ | ||
795 | { 0x0000, 0x0000, 0x0000 }, /* R697 */ | ||
796 | { 0x0000, 0x0000, 0x0000 }, /* R698 */ | ||
797 | { 0x0000, 0x0000, 0x0000 }, /* R699 */ | ||
798 | { 0x0000, 0x0000, 0x0000 }, /* R700 */ | ||
799 | { 0x0000, 0x0000, 0x0000 }, /* R701 */ | ||
800 | { 0x0000, 0x0000, 0x0000 }, /* R702 */ | ||
801 | { 0x0000, 0x0000, 0x0000 }, /* R703 */ | ||
802 | { 0x0000, 0x0000, 0x0000 }, /* R704 */ | ||
803 | { 0x0000, 0x0000, 0x0000 }, /* R705 */ | ||
804 | { 0x0000, 0x0000, 0x0000 }, /* R706 */ | ||
805 | { 0x0000, 0x0000, 0x0000 }, /* R707 */ | ||
806 | { 0x0000, 0x0000, 0x0000 }, /* R708 */ | ||
807 | { 0x0000, 0x0000, 0x0000 }, /* R709 */ | ||
808 | { 0x0000, 0x0000, 0x0000 }, /* R710 */ | ||
809 | { 0x0000, 0x0000, 0x0000 }, /* R711 */ | ||
810 | { 0x0000, 0x0000, 0x0000 }, /* R712 */ | ||
811 | { 0x0000, 0x0000, 0x0000 }, /* R713 */ | ||
812 | { 0x0000, 0x0000, 0x0000 }, /* R714 */ | ||
813 | { 0x0000, 0x0000, 0x0000 }, /* R715 */ | ||
814 | { 0x0000, 0x0000, 0x0000 }, /* R716 */ | ||
815 | { 0x0000, 0x0000, 0x0000 }, /* R717 */ | ||
816 | { 0x0000, 0x0000, 0x0000 }, /* R718 */ | ||
817 | { 0x0000, 0x0000, 0x0000 }, /* R719 */ | ||
818 | { 0x0000, 0x0000, 0x0000 }, /* R720 */ | ||
819 | { 0x0000, 0x0000, 0x0000 }, /* R721 */ | ||
820 | { 0x0000, 0x0000, 0x0000 }, /* R722 */ | ||
821 | { 0x0000, 0x0000, 0x0000 }, /* R723 */ | ||
822 | { 0x0000, 0x0000, 0x0000 }, /* R724 */ | ||
823 | { 0x0000, 0x0000, 0x0000 }, /* R725 */ | ||
824 | { 0x0000, 0x0000, 0x0000 }, /* R726 */ | ||
825 | { 0x0000, 0x0000, 0x0000 }, /* R727 */ | ||
826 | { 0x0000, 0x0000, 0x0000 }, /* R728 */ | ||
827 | { 0x0000, 0x0000, 0x0000 }, /* R729 */ | ||
828 | { 0x0000, 0x0000, 0x0000 }, /* R730 */ | ||
829 | { 0x0000, 0x0000, 0x0000 }, /* R731 */ | ||
830 | { 0x0000, 0x0000, 0x0000 }, /* R732 */ | ||
831 | { 0x0000, 0x0000, 0x0000 }, /* R733 */ | ||
832 | { 0x0000, 0x0000, 0x0000 }, /* R734 */ | ||
833 | { 0x0000, 0x0000, 0x0000 }, /* R735 */ | ||
834 | { 0x0000, 0x0000, 0x0000 }, /* R736 */ | ||
835 | { 0x0000, 0x0000, 0x0000 }, /* R737 */ | ||
836 | { 0x0000, 0x0000, 0x0000 }, /* R738 */ | ||
837 | { 0x0000, 0x0000, 0x0000 }, /* R739 */ | ||
838 | { 0x0000, 0x0000, 0x0000 }, /* R740 */ | ||
839 | { 0x0000, 0x0000, 0x0000 }, /* R741 */ | ||
840 | { 0x0000, 0x0000, 0x0000 }, /* R742 */ | ||
841 | { 0x0000, 0x0000, 0x0000 }, /* R743 */ | ||
842 | { 0x0000, 0x0000, 0x0000 }, /* R744 */ | ||
843 | { 0x0000, 0x0000, 0x0000 }, /* R745 */ | ||
844 | { 0x0000, 0x0000, 0x0000 }, /* R746 */ | ||
845 | { 0x0000, 0x0000, 0x0000 }, /* R747 */ | ||
846 | { 0x0000, 0x0000, 0x0000 }, /* R748 */ | ||
847 | { 0x0000, 0x0000, 0x0000 }, /* R749 */ | ||
848 | { 0x0000, 0x0000, 0x0000 }, /* R750 */ | ||
849 | { 0x0000, 0x0000, 0x0000 }, /* R751 */ | ||
850 | { 0x0000, 0x0000, 0x0000 }, /* R752 */ | ||
851 | { 0x0000, 0x0000, 0x0000 }, /* R753 */ | ||
852 | { 0x0000, 0x0000, 0x0000 }, /* R754 */ | ||
853 | { 0x0000, 0x0000, 0x0000 }, /* R755 */ | ||
854 | { 0x0000, 0x0000, 0x0000 }, /* R756 */ | ||
855 | { 0x0000, 0x0000, 0x0000 }, /* R757 */ | ||
856 | { 0x0000, 0x0000, 0x0000 }, /* R758 */ | ||
857 | { 0x0000, 0x0000, 0x0000 }, /* R759 */ | ||
858 | { 0x0000, 0x0000, 0x0000 }, /* R760 */ | ||
859 | { 0x0000, 0x0000, 0x0000 }, /* R761 */ | ||
860 | { 0x0000, 0x0000, 0x0000 }, /* R762 */ | ||
861 | { 0x0000, 0x0000, 0x0000 }, /* R763 */ | ||
862 | { 0x0000, 0x0000, 0x0000 }, /* R764 */ | ||
863 | { 0x0000, 0x0000, 0x0000 }, /* R765 */ | ||
864 | { 0x0000, 0x0000, 0x0000 }, /* R766 */ | ||
865 | { 0x0000, 0x0000, 0x0000 }, /* R767 */ | ||
866 | { 0xE1F8, 0xE1F8, 0x0000 }, /* R768 - AIF1 Control (1) */ | ||
867 | { 0xCD1F, 0xCD1F, 0x0000 }, /* R769 - AIF1 Control (2) */ | ||
868 | { 0xF000, 0xF000, 0x0000 }, /* R770 - AIF1 Master/Slave */ | ||
869 | { 0x01F0, 0x01F0, 0x0000 }, /* R771 - AIF1 BCLK */ | ||
870 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R772 - AIF1ADC LRCLK */ | ||
871 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R773 - AIF1DAC LRCLK */ | ||
872 | { 0x0003, 0x0003, 0x0000 }, /* R774 - AIF1DAC Data */ | ||
873 | { 0x0003, 0x0003, 0x0000 }, /* R775 - AIF1ADC Data */ | ||
874 | { 0x0000, 0x0000, 0x0000 }, /* R776 */ | ||
875 | { 0x0000, 0x0000, 0x0000 }, /* R777 */ | ||
876 | { 0x0000, 0x0000, 0x0000 }, /* R778 */ | ||
877 | { 0x0000, 0x0000, 0x0000 }, /* R779 */ | ||
878 | { 0x0000, 0x0000, 0x0000 }, /* R780 */ | ||
879 | { 0x0000, 0x0000, 0x0000 }, /* R781 */ | ||
880 | { 0x0000, 0x0000, 0x0000 }, /* R782 */ | ||
881 | { 0x0000, 0x0000, 0x0000 }, /* R783 */ | ||
882 | { 0xF1F8, 0xF1F8, 0x0000 }, /* R784 - AIF2 Control (1) */ | ||
883 | { 0xFD1F, 0xFD1F, 0x0000 }, /* R785 - AIF2 Control (2) */ | ||
884 | { 0xF000, 0xF000, 0x0000 }, /* R786 - AIF2 Master/Slave */ | ||
885 | { 0x01F0, 0x01F0, 0x0000 }, /* R787 - AIF2 BCLK */ | ||
886 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R788 - AIF2ADC LRCLK */ | ||
887 | { 0x0FFF, 0x0FFF, 0x0000 }, /* R789 - AIF2DAC LRCLK */ | ||
888 | { 0x0003, 0x0003, 0x0000 }, /* R790 - AIF2DAC Data */ | ||
889 | { 0x0003, 0x0003, 0x0000 }, /* R791 - AIF2ADC Data */ | ||
890 | { 0x0000, 0x0000, 0x0000 }, /* R792 */ | ||
891 | { 0x0000, 0x0000, 0x0000 }, /* R793 */ | ||
892 | { 0x0000, 0x0000, 0x0000 }, /* R794 */ | ||
893 | { 0x0000, 0x0000, 0x0000 }, /* R795 */ | ||
894 | { 0x0000, 0x0000, 0x0000 }, /* R796 */ | ||
895 | { 0x0000, 0x0000, 0x0000 }, /* R797 */ | ||
896 | { 0x0000, 0x0000, 0x0000 }, /* R798 */ | ||
897 | { 0x0000, 0x0000, 0x0000 }, /* R799 */ | ||
898 | { 0x0000, 0x0000, 0x0000 }, /* R800 */ | ||
899 | { 0x0000, 0x0000, 0x0000 }, /* R801 */ | ||
900 | { 0x0000, 0x0000, 0x0000 }, /* R802 */ | ||
901 | { 0x0000, 0x0000, 0x0000 }, /* R803 */ | ||
902 | { 0x0000, 0x0000, 0x0000 }, /* R804 */ | ||
903 | { 0x0000, 0x0000, 0x0000 }, /* R805 */ | ||
904 | { 0x0000, 0x0000, 0x0000 }, /* R806 */ | ||
905 | { 0x0000, 0x0000, 0x0000 }, /* R807 */ | ||
906 | { 0x0000, 0x0000, 0x0000 }, /* R808 */ | ||
907 | { 0x0000, 0x0000, 0x0000 }, /* R809 */ | ||
908 | { 0x0000, 0x0000, 0x0000 }, /* R810 */ | ||
909 | { 0x0000, 0x0000, 0x0000 }, /* R811 */ | ||
910 | { 0x0000, 0x0000, 0x0000 }, /* R812 */ | ||
911 | { 0x0000, 0x0000, 0x0000 }, /* R813 */ | ||
912 | { 0x0000, 0x0000, 0x0000 }, /* R814 */ | ||
913 | { 0x0000, 0x0000, 0x0000 }, /* R815 */ | ||
914 | { 0x0000, 0x0000, 0x0000 }, /* R816 */ | ||
915 | { 0x0000, 0x0000, 0x0000 }, /* R817 */ | ||
916 | { 0x0000, 0x0000, 0x0000 }, /* R818 */ | ||
917 | { 0x0000, 0x0000, 0x0000 }, /* R819 */ | ||
918 | { 0x0000, 0x0000, 0x0000 }, /* R820 */ | ||
919 | { 0x0000, 0x0000, 0x0000 }, /* R821 */ | ||
920 | { 0x0000, 0x0000, 0x0000 }, /* R822 */ | ||
921 | { 0x0000, 0x0000, 0x0000 }, /* R823 */ | ||
922 | { 0x0000, 0x0000, 0x0000 }, /* R824 */ | ||
923 | { 0x0000, 0x0000, 0x0000 }, /* R825 */ | ||
924 | { 0x0000, 0x0000, 0x0000 }, /* R826 */ | ||
925 | { 0x0000, 0x0000, 0x0000 }, /* R827 */ | ||
926 | { 0x0000, 0x0000, 0x0000 }, /* R828 */ | ||
927 | { 0x0000, 0x0000, 0x0000 }, /* R829 */ | ||
928 | { 0x0000, 0x0000, 0x0000 }, /* R830 */ | ||
929 | { 0x0000, 0x0000, 0x0000 }, /* R831 */ | ||
930 | { 0x0000, 0x0000, 0x0000 }, /* R832 */ | ||
931 | { 0x0000, 0x0000, 0x0000 }, /* R833 */ | ||
932 | { 0x0000, 0x0000, 0x0000 }, /* R834 */ | ||
933 | { 0x0000, 0x0000, 0x0000 }, /* R835 */ | ||
934 | { 0x0000, 0x0000, 0x0000 }, /* R836 */ | ||
935 | { 0x0000, 0x0000, 0x0000 }, /* R837 */ | ||
936 | { 0x0000, 0x0000, 0x0000 }, /* R838 */ | ||
937 | { 0x0000, 0x0000, 0x0000 }, /* R839 */ | ||
938 | { 0x0000, 0x0000, 0x0000 }, /* R840 */ | ||
939 | { 0x0000, 0x0000, 0x0000 }, /* R841 */ | ||
940 | { 0x0000, 0x0000, 0x0000 }, /* R842 */ | ||
941 | { 0x0000, 0x0000, 0x0000 }, /* R843 */ | ||
942 | { 0x0000, 0x0000, 0x0000 }, /* R844 */ | ||
943 | { 0x0000, 0x0000, 0x0000 }, /* R845 */ | ||
944 | { 0x0000, 0x0000, 0x0000 }, /* R846 */ | ||
945 | { 0x0000, 0x0000, 0x0000 }, /* R847 */ | ||
946 | { 0x0000, 0x0000, 0x0000 }, /* R848 */ | ||
947 | { 0x0000, 0x0000, 0x0000 }, /* R849 */ | ||
948 | { 0x0000, 0x0000, 0x0000 }, /* R850 */ | ||
949 | { 0x0000, 0x0000, 0x0000 }, /* R851 */ | ||
950 | { 0x0000, 0x0000, 0x0000 }, /* R852 */ | ||
951 | { 0x0000, 0x0000, 0x0000 }, /* R853 */ | ||
952 | { 0x0000, 0x0000, 0x0000 }, /* R854 */ | ||
953 | { 0x0000, 0x0000, 0x0000 }, /* R855 */ | ||
954 | { 0x0000, 0x0000, 0x0000 }, /* R856 */ | ||
955 | { 0x0000, 0x0000, 0x0000 }, /* R857 */ | ||
956 | { 0x0000, 0x0000, 0x0000 }, /* R858 */ | ||
957 | { 0x0000, 0x0000, 0x0000 }, /* R859 */ | ||
958 | { 0x0000, 0x0000, 0x0000 }, /* R860 */ | ||
959 | { 0x0000, 0x0000, 0x0000 }, /* R861 */ | ||
960 | { 0x0000, 0x0000, 0x0000 }, /* R862 */ | ||
961 | { 0x0000, 0x0000, 0x0000 }, /* R863 */ | ||
962 | { 0x0000, 0x0000, 0x0000 }, /* R864 */ | ||
963 | { 0x0000, 0x0000, 0x0000 }, /* R865 */ | ||
964 | { 0x0000, 0x0000, 0x0000 }, /* R866 */ | ||
965 | { 0x0000, 0x0000, 0x0000 }, /* R867 */ | ||
966 | { 0x0000, 0x0000, 0x0000 }, /* R868 */ | ||
967 | { 0x0000, 0x0000, 0x0000 }, /* R869 */ | ||
968 | { 0x0000, 0x0000, 0x0000 }, /* R870 */ | ||
969 | { 0x0000, 0x0000, 0x0000 }, /* R871 */ | ||
970 | { 0x0000, 0x0000, 0x0000 }, /* R872 */ | ||
971 | { 0x0000, 0x0000, 0x0000 }, /* R873 */ | ||
972 | { 0x0000, 0x0000, 0x0000 }, /* R874 */ | ||
973 | { 0x0000, 0x0000, 0x0000 }, /* R875 */ | ||
974 | { 0x0000, 0x0000, 0x0000 }, /* R876 */ | ||
975 | { 0x0000, 0x0000, 0x0000 }, /* R877 */ | ||
976 | { 0x0000, 0x0000, 0x0000 }, /* R878 */ | ||
977 | { 0x0000, 0x0000, 0x0000 }, /* R879 */ | ||
978 | { 0x0000, 0x0000, 0x0000 }, /* R880 */ | ||
979 | { 0x0000, 0x0000, 0x0000 }, /* R881 */ | ||
980 | { 0x0000, 0x0000, 0x0000 }, /* R882 */ | ||
981 | { 0x0000, 0x0000, 0x0000 }, /* R883 */ | ||
982 | { 0x0000, 0x0000, 0x0000 }, /* R884 */ | ||
983 | { 0x0000, 0x0000, 0x0000 }, /* R885 */ | ||
984 | { 0x0000, 0x0000, 0x0000 }, /* R886 */ | ||
985 | { 0x0000, 0x0000, 0x0000 }, /* R887 */ | ||
986 | { 0x0000, 0x0000, 0x0000 }, /* R888 */ | ||
987 | { 0x0000, 0x0000, 0x0000 }, /* R889 */ | ||
988 | { 0x0000, 0x0000, 0x0000 }, /* R890 */ | ||
989 | { 0x0000, 0x0000, 0x0000 }, /* R891 */ | ||
990 | { 0x0000, 0x0000, 0x0000 }, /* R892 */ | ||
991 | { 0x0000, 0x0000, 0x0000 }, /* R893 */ | ||
992 | { 0x0000, 0x0000, 0x0000 }, /* R894 */ | ||
993 | { 0x0000, 0x0000, 0x0000 }, /* R895 */ | ||
994 | { 0x0000, 0x0000, 0x0000 }, /* R896 */ | ||
995 | { 0x0000, 0x0000, 0x0000 }, /* R897 */ | ||
996 | { 0x0000, 0x0000, 0x0000 }, /* R898 */ | ||
997 | { 0x0000, 0x0000, 0x0000 }, /* R899 */ | ||
998 | { 0x0000, 0x0000, 0x0000 }, /* R900 */ | ||
999 | { 0x0000, 0x0000, 0x0000 }, /* R901 */ | ||
1000 | { 0x0000, 0x0000, 0x0000 }, /* R902 */ | ||
1001 | { 0x0000, 0x0000, 0x0000 }, /* R903 */ | ||
1002 | { 0x0000, 0x0000, 0x0000 }, /* R904 */ | ||
1003 | { 0x0000, 0x0000, 0x0000 }, /* R905 */ | ||
1004 | { 0x0000, 0x0000, 0x0000 }, /* R906 */ | ||
1005 | { 0x0000, 0x0000, 0x0000 }, /* R907 */ | ||
1006 | { 0x0000, 0x0000, 0x0000 }, /* R908 */ | ||
1007 | { 0x0000, 0x0000, 0x0000 }, /* R909 */ | ||
1008 | { 0x0000, 0x0000, 0x0000 }, /* R910 */ | ||
1009 | { 0x0000, 0x0000, 0x0000 }, /* R911 */ | ||
1010 | { 0x0000, 0x0000, 0x0000 }, /* R912 */ | ||
1011 | { 0x0000, 0x0000, 0x0000 }, /* R913 */ | ||
1012 | { 0x0000, 0x0000, 0x0000 }, /* R914 */ | ||
1013 | { 0x0000, 0x0000, 0x0000 }, /* R915 */ | ||
1014 | { 0x0000, 0x0000, 0x0000 }, /* R916 */ | ||
1015 | { 0x0000, 0x0000, 0x0000 }, /* R917 */ | ||
1016 | { 0x0000, 0x0000, 0x0000 }, /* R918 */ | ||
1017 | { 0x0000, 0x0000, 0x0000 }, /* R919 */ | ||
1018 | { 0x0000, 0x0000, 0x0000 }, /* R920 */ | ||
1019 | { 0x0000, 0x0000, 0x0000 }, /* R921 */ | ||
1020 | { 0x0000, 0x0000, 0x0000 }, /* R922 */ | ||
1021 | { 0x0000, 0x0000, 0x0000 }, /* R923 */ | ||
1022 | { 0x0000, 0x0000, 0x0000 }, /* R924 */ | ||
1023 | { 0x0000, 0x0000, 0x0000 }, /* R925 */ | ||
1024 | { 0x0000, 0x0000, 0x0000 }, /* R926 */ | ||
1025 | { 0x0000, 0x0000, 0x0000 }, /* R927 */ | ||
1026 | { 0x0000, 0x0000, 0x0000 }, /* R928 */ | ||
1027 | { 0x0000, 0x0000, 0x0000 }, /* R929 */ | ||
1028 | { 0x0000, 0x0000, 0x0000 }, /* R930 */ | ||
1029 | { 0x0000, 0x0000, 0x0000 }, /* R931 */ | ||
1030 | { 0x0000, 0x0000, 0x0000 }, /* R932 */ | ||
1031 | { 0x0000, 0x0000, 0x0000 }, /* R933 */ | ||
1032 | { 0x0000, 0x0000, 0x0000 }, /* R934 */ | ||
1033 | { 0x0000, 0x0000, 0x0000 }, /* R935 */ | ||
1034 | { 0x0000, 0x0000, 0x0000 }, /* R936 */ | ||
1035 | { 0x0000, 0x0000, 0x0000 }, /* R937 */ | ||
1036 | { 0x0000, 0x0000, 0x0000 }, /* R938 */ | ||
1037 | { 0x0000, 0x0000, 0x0000 }, /* R939 */ | ||
1038 | { 0x0000, 0x0000, 0x0000 }, /* R940 */ | ||
1039 | { 0x0000, 0x0000, 0x0000 }, /* R941 */ | ||
1040 | { 0x0000, 0x0000, 0x0000 }, /* R942 */ | ||
1041 | { 0x0000, 0x0000, 0x0000 }, /* R943 */ | ||
1042 | { 0x0000, 0x0000, 0x0000 }, /* R944 */ | ||
1043 | { 0x0000, 0x0000, 0x0000 }, /* R945 */ | ||
1044 | { 0x0000, 0x0000, 0x0000 }, /* R946 */ | ||
1045 | { 0x0000, 0x0000, 0x0000 }, /* R947 */ | ||
1046 | { 0x0000, 0x0000, 0x0000 }, /* R948 */ | ||
1047 | { 0x0000, 0x0000, 0x0000 }, /* R949 */ | ||
1048 | { 0x0000, 0x0000, 0x0000 }, /* R950 */ | ||
1049 | { 0x0000, 0x0000, 0x0000 }, /* R951 */ | ||
1050 | { 0x0000, 0x0000, 0x0000 }, /* R952 */ | ||
1051 | { 0x0000, 0x0000, 0x0000 }, /* R953 */ | ||
1052 | { 0x0000, 0x0000, 0x0000 }, /* R954 */ | ||
1053 | { 0x0000, 0x0000, 0x0000 }, /* R955 */ | ||
1054 | { 0x0000, 0x0000, 0x0000 }, /* R956 */ | ||
1055 | { 0x0000, 0x0000, 0x0000 }, /* R957 */ | ||
1056 | { 0x0000, 0x0000, 0x0000 }, /* R958 */ | ||
1057 | { 0x0000, 0x0000, 0x0000 }, /* R959 */ | ||
1058 | { 0x0000, 0x0000, 0x0000 }, /* R960 */ | ||
1059 | { 0x0000, 0x0000, 0x0000 }, /* R961 */ | ||
1060 | { 0x0000, 0x0000, 0x0000 }, /* R962 */ | ||
1061 | { 0x0000, 0x0000, 0x0000 }, /* R963 */ | ||
1062 | { 0x0000, 0x0000, 0x0000 }, /* R964 */ | ||
1063 | { 0x0000, 0x0000, 0x0000 }, /* R965 */ | ||
1064 | { 0x0000, 0x0000, 0x0000 }, /* R966 */ | ||
1065 | { 0x0000, 0x0000, 0x0000 }, /* R967 */ | ||
1066 | { 0x0000, 0x0000, 0x0000 }, /* R968 */ | ||
1067 | { 0x0000, 0x0000, 0x0000 }, /* R969 */ | ||
1068 | { 0x0000, 0x0000, 0x0000 }, /* R970 */ | ||
1069 | { 0x0000, 0x0000, 0x0000 }, /* R971 */ | ||
1070 | { 0x0000, 0x0000, 0x0000 }, /* R972 */ | ||
1071 | { 0x0000, 0x0000, 0x0000 }, /* R973 */ | ||
1072 | { 0x0000, 0x0000, 0x0000 }, /* R974 */ | ||
1073 | { 0x0000, 0x0000, 0x0000 }, /* R975 */ | ||
1074 | { 0x0000, 0x0000, 0x0000 }, /* R976 */ | ||
1075 | { 0x0000, 0x0000, 0x0000 }, /* R977 */ | ||
1076 | { 0x0000, 0x0000, 0x0000 }, /* R978 */ | ||
1077 | { 0x0000, 0x0000, 0x0000 }, /* R979 */ | ||
1078 | { 0x0000, 0x0000, 0x0000 }, /* R980 */ | ||
1079 | { 0x0000, 0x0000, 0x0000 }, /* R981 */ | ||
1080 | { 0x0000, 0x0000, 0x0000 }, /* R982 */ | ||
1081 | { 0x0000, 0x0000, 0x0000 }, /* R983 */ | ||
1082 | { 0x0000, 0x0000, 0x0000 }, /* R984 */ | ||
1083 | { 0x0000, 0x0000, 0x0000 }, /* R985 */ | ||
1084 | { 0x0000, 0x0000, 0x0000 }, /* R986 */ | ||
1085 | { 0x0000, 0x0000, 0x0000 }, /* R987 */ | ||
1086 | { 0x0000, 0x0000, 0x0000 }, /* R988 */ | ||
1087 | { 0x0000, 0x0000, 0x0000 }, /* R989 */ | ||
1088 | { 0x0000, 0x0000, 0x0000 }, /* R990 */ | ||
1089 | { 0x0000, 0x0000, 0x0000 }, /* R991 */ | ||
1090 | { 0x0000, 0x0000, 0x0000 }, /* R992 */ | ||
1091 | { 0x0000, 0x0000, 0x0000 }, /* R993 */ | ||
1092 | { 0x0000, 0x0000, 0x0000 }, /* R994 */ | ||
1093 | { 0x0000, 0x0000, 0x0000 }, /* R995 */ | ||
1094 | { 0x0000, 0x0000, 0x0000 }, /* R996 */ | ||
1095 | { 0x0000, 0x0000, 0x0000 }, /* R997 */ | ||
1096 | { 0x0000, 0x0000, 0x0000 }, /* R998 */ | ||
1097 | { 0x0000, 0x0000, 0x0000 }, /* R999 */ | ||
1098 | { 0x0000, 0x0000, 0x0000 }, /* R1000 */ | ||
1099 | { 0x0000, 0x0000, 0x0000 }, /* R1001 */ | ||
1100 | { 0x0000, 0x0000, 0x0000 }, /* R1002 */ | ||
1101 | { 0x0000, 0x0000, 0x0000 }, /* R1003 */ | ||
1102 | { 0x0000, 0x0000, 0x0000 }, /* R1004 */ | ||
1103 | { 0x0000, 0x0000, 0x0000 }, /* R1005 */ | ||
1104 | { 0x0000, 0x0000, 0x0000 }, /* R1006 */ | ||
1105 | { 0x0000, 0x0000, 0x0000 }, /* R1007 */ | ||
1106 | { 0x0000, 0x0000, 0x0000 }, /* R1008 */ | ||
1107 | { 0x0000, 0x0000, 0x0000 }, /* R1009 */ | ||
1108 | { 0x0000, 0x0000, 0x0000 }, /* R1010 */ | ||
1109 | { 0x0000, 0x0000, 0x0000 }, /* R1011 */ | ||
1110 | { 0x0000, 0x0000, 0x0000 }, /* R1012 */ | ||
1111 | { 0x0000, 0x0000, 0x0000 }, /* R1013 */ | ||
1112 | { 0x0000, 0x0000, 0x0000 }, /* R1014 */ | ||
1113 | { 0x0000, 0x0000, 0x0000 }, /* R1015 */ | ||
1114 | { 0x0000, 0x0000, 0x0000 }, /* R1016 */ | ||
1115 | { 0x0000, 0x0000, 0x0000 }, /* R1017 */ | ||
1116 | { 0x0000, 0x0000, 0x0000 }, /* R1018 */ | ||
1117 | { 0x0000, 0x0000, 0x0000 }, /* R1019 */ | ||
1118 | { 0x0000, 0x0000, 0x0000 }, /* R1020 */ | ||
1119 | { 0x0000, 0x0000, 0x0000 }, /* R1021 */ | ||
1120 | { 0x0000, 0x0000, 0x0000 }, /* R1022 */ | ||
1121 | { 0x0000, 0x0000, 0x0000 }, /* R1023 */ | ||
1122 | { 0x00FF, 0x01FF, 0x0000 }, /* R1024 - AIF1 ADC1 Left Volume */ | ||
1123 | { 0x00FF, 0x01FF, 0x0000 }, /* R1025 - AIF1 ADC1 Right Volume */ | ||
1124 | { 0x00FF, 0x01FF, 0x0000 }, /* R1026 - AIF1 DAC1 Left Volume */ | ||
1125 | { 0x00FF, 0x01FF, 0x0000 }, /* R1027 - AIF1 DAC1 Right Volume */ | ||
1126 | { 0x00FF, 0x01FF, 0x0000 }, /* R1028 - AIF1 ADC2 Left Volume */ | ||
1127 | { 0x00FF, 0x01FF, 0x0000 }, /* R1029 - AIF1 ADC2 Right Volume */ | ||
1128 | { 0x00FF, 0x01FF, 0x0000 }, /* R1030 - AIF1 DAC2 Left Volume */ | ||
1129 | { 0x00FF, 0x01FF, 0x0000 }, /* R1031 - AIF1 DAC2 Right Volume */ | ||
1130 | { 0x0000, 0x0000, 0x0000 }, /* R1032 */ | ||
1131 | { 0x0000, 0x0000, 0x0000 }, /* R1033 */ | ||
1132 | { 0x0000, 0x0000, 0x0000 }, /* R1034 */ | ||
1133 | { 0x0000, 0x0000, 0x0000 }, /* R1035 */ | ||
1134 | { 0x0000, 0x0000, 0x0000 }, /* R1036 */ | ||
1135 | { 0x0000, 0x0000, 0x0000 }, /* R1037 */ | ||
1136 | { 0x0000, 0x0000, 0x0000 }, /* R1038 */ | ||
1137 | { 0x0000, 0x0000, 0x0000 }, /* R1039 */ | ||
1138 | { 0xF800, 0xF800, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */ | ||
1139 | { 0x7800, 0x7800, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */ | ||
1140 | { 0x0000, 0x0000, 0x0000 }, /* R1042 */ | ||
1141 | { 0x0000, 0x0000, 0x0000 }, /* R1043 */ | ||
1142 | { 0x0000, 0x0000, 0x0000 }, /* R1044 */ | ||
1143 | { 0x0000, 0x0000, 0x0000 }, /* R1045 */ | ||
1144 | { 0x0000, 0x0000, 0x0000 }, /* R1046 */ | ||
1145 | { 0x0000, 0x0000, 0x0000 }, /* R1047 */ | ||
1146 | { 0x0000, 0x0000, 0x0000 }, /* R1048 */ | ||
1147 | { 0x0000, 0x0000, 0x0000 }, /* R1049 */ | ||
1148 | { 0x0000, 0x0000, 0x0000 }, /* R1050 */ | ||
1149 | { 0x0000, 0x0000, 0x0000 }, /* R1051 */ | ||
1150 | { 0x0000, 0x0000, 0x0000 }, /* R1052 */ | ||
1151 | { 0x0000, 0x0000, 0x0000 }, /* R1053 */ | ||
1152 | { 0x0000, 0x0000, 0x0000 }, /* R1054 */ | ||
1153 | { 0x0000, 0x0000, 0x0000 }, /* R1055 */ | ||
1154 | { 0x02B6, 0x02B6, 0x0000 }, /* R1056 - AIF1 DAC1 Filters (1) */ | ||
1155 | { 0x3F00, 0x3F00, 0x0000 }, /* R1057 - AIF1 DAC1 Filters (2) */ | ||
1156 | { 0x02B6, 0x02B6, 0x0000 }, /* R1058 - AIF1 DAC2 Filters (1) */ | ||
1157 | { 0x3F00, 0x3F00, 0x0000 }, /* R1059 - AIF1 DAC2 Filters (2) */ | ||
1158 | { 0x0000, 0x0000, 0x0000 }, /* R1060 */ | ||
1159 | { 0x0000, 0x0000, 0x0000 }, /* R1061 */ | ||
1160 | { 0x0000, 0x0000, 0x0000 }, /* R1062 */ | ||
1161 | { 0x0000, 0x0000, 0x0000 }, /* R1063 */ | ||
1162 | { 0x0000, 0x0000, 0x0000 }, /* R1064 */ | ||
1163 | { 0x0000, 0x0000, 0x0000 }, /* R1065 */ | ||
1164 | { 0x0000, 0x0000, 0x0000 }, /* R1066 */ | ||
1165 | { 0x0000, 0x0000, 0x0000 }, /* R1067 */ | ||
1166 | { 0x0000, 0x0000, 0x0000 }, /* R1068 */ | ||
1167 | { 0x0000, 0x0000, 0x0000 }, /* R1069 */ | ||
1168 | { 0x0000, 0x0000, 0x0000 }, /* R1070 */ | ||
1169 | { 0x0000, 0x0000, 0x0000 }, /* R1071 */ | ||
1170 | { 0x0000, 0x0000, 0x0000 }, /* R1072 */ | ||
1171 | { 0x0000, 0x0000, 0x0000 }, /* R1073 */ | ||
1172 | { 0x0000, 0x0000, 0x0000 }, /* R1074 */ | ||
1173 | { 0x0000, 0x0000, 0x0000 }, /* R1075 */ | ||
1174 | { 0x0000, 0x0000, 0x0000 }, /* R1076 */ | ||
1175 | { 0x0000, 0x0000, 0x0000 }, /* R1077 */ | ||
1176 | { 0x0000, 0x0000, 0x0000 }, /* R1078 */ | ||
1177 | { 0x0000, 0x0000, 0x0000 }, /* R1079 */ | ||
1178 | { 0x0000, 0x0000, 0x0000 }, /* R1080 */ | ||
1179 | { 0x0000, 0x0000, 0x0000 }, /* R1081 */ | ||
1180 | { 0x0000, 0x0000, 0x0000 }, /* R1082 */ | ||
1181 | { 0x0000, 0x0000, 0x0000 }, /* R1083 */ | ||
1182 | { 0x0000, 0x0000, 0x0000 }, /* R1084 */ | ||
1183 | { 0x0000, 0x0000, 0x0000 }, /* R1085 */ | ||
1184 | { 0x0000, 0x0000, 0x0000 }, /* R1086 */ | ||
1185 | { 0x0000, 0x0000, 0x0000 }, /* R1087 */ | ||
1186 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1088 - AIF1 DRC1 (1) */ | ||
1187 | { 0x1FFF, 0x1FFF, 0x0000 }, /* R1089 - AIF1 DRC1 (2) */ | ||
1188 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */ | ||
1189 | { 0x07FF, 0x07FF, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */ | ||
1190 | { 0x03FF, 0x03FF, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */ | ||
1191 | { 0x0000, 0x0000, 0x0000 }, /* R1093 */ | ||
1192 | { 0x0000, 0x0000, 0x0000 }, /* R1094 */ | ||
1193 | { 0x0000, 0x0000, 0x0000 }, /* R1095 */ | ||
1194 | { 0x0000, 0x0000, 0x0000 }, /* R1096 */ | ||
1195 | { 0x0000, 0x0000, 0x0000 }, /* R1097 */ | ||
1196 | { 0x0000, 0x0000, 0x0000 }, /* R1098 */ | ||
1197 | { 0x0000, 0x0000, 0x0000 }, /* R1099 */ | ||
1198 | { 0x0000, 0x0000, 0x0000 }, /* R1100 */ | ||
1199 | { 0x0000, 0x0000, 0x0000 }, /* R1101 */ | ||
1200 | { 0x0000, 0x0000, 0x0000 }, /* R1102 */ | ||
1201 | { 0x0000, 0x0000, 0x0000 }, /* R1103 */ | ||
1202 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1104 - AIF1 DRC2 (1) */ | ||
1203 | { 0x1FFF, 0x1FFF, 0x0000 }, /* R1105 - AIF1 DRC2 (2) */ | ||
1204 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */ | ||
1205 | { 0x07FF, 0x07FF, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */ | ||
1206 | { 0x03FF, 0x03FF, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */ | ||
1207 | { 0x0000, 0x0000, 0x0000 }, /* R1109 */ | ||
1208 | { 0x0000, 0x0000, 0x0000 }, /* R1110 */ | ||
1209 | { 0x0000, 0x0000, 0x0000 }, /* R1111 */ | ||
1210 | { 0x0000, 0x0000, 0x0000 }, /* R1112 */ | ||
1211 | { 0x0000, 0x0000, 0x0000 }, /* R1113 */ | ||
1212 | { 0x0000, 0x0000, 0x0000 }, /* R1114 */ | ||
1213 | { 0x0000, 0x0000, 0x0000 }, /* R1115 */ | ||
1214 | { 0x0000, 0x0000, 0x0000 }, /* R1116 */ | ||
1215 | { 0x0000, 0x0000, 0x0000 }, /* R1117 */ | ||
1216 | { 0x0000, 0x0000, 0x0000 }, /* R1118 */ | ||
1217 | { 0x0000, 0x0000, 0x0000 }, /* R1119 */ | ||
1218 | { 0x0000, 0x0000, 0x0000 }, /* R1120 */ | ||
1219 | { 0x0000, 0x0000, 0x0000 }, /* R1121 */ | ||
1220 | { 0x0000, 0x0000, 0x0000 }, /* R1122 */ | ||
1221 | { 0x0000, 0x0000, 0x0000 }, /* R1123 */ | ||
1222 | { 0x0000, 0x0000, 0x0000 }, /* R1124 */ | ||
1223 | { 0x0000, 0x0000, 0x0000 }, /* R1125 */ | ||
1224 | { 0x0000, 0x0000, 0x0000 }, /* R1126 */ | ||
1225 | { 0x0000, 0x0000, 0x0000 }, /* R1127 */ | ||
1226 | { 0x0000, 0x0000, 0x0000 }, /* R1128 */ | ||
1227 | { 0x0000, 0x0000, 0x0000 }, /* R1129 */ | ||
1228 | { 0x0000, 0x0000, 0x0000 }, /* R1130 */ | ||
1229 | { 0x0000, 0x0000, 0x0000 }, /* R1131 */ | ||
1230 | { 0x0000, 0x0000, 0x0000 }, /* R1132 */ | ||
1231 | { 0x0000, 0x0000, 0x0000 }, /* R1133 */ | ||
1232 | { 0x0000, 0x0000, 0x0000 }, /* R1134 */ | ||
1233 | { 0x0000, 0x0000, 0x0000 }, /* R1135 */ | ||
1234 | { 0x0000, 0x0000, 0x0000 }, /* R1136 */ | ||
1235 | { 0x0000, 0x0000, 0x0000 }, /* R1137 */ | ||
1236 | { 0x0000, 0x0000, 0x0000 }, /* R1138 */ | ||
1237 | { 0x0000, 0x0000, 0x0000 }, /* R1139 */ | ||
1238 | { 0x0000, 0x0000, 0x0000 }, /* R1140 */ | ||
1239 | { 0x0000, 0x0000, 0x0000 }, /* R1141 */ | ||
1240 | { 0x0000, 0x0000, 0x0000 }, /* R1142 */ | ||
1241 | { 0x0000, 0x0000, 0x0000 }, /* R1143 */ | ||
1242 | { 0x0000, 0x0000, 0x0000 }, /* R1144 */ | ||
1243 | { 0x0000, 0x0000, 0x0000 }, /* R1145 */ | ||
1244 | { 0x0000, 0x0000, 0x0000 }, /* R1146 */ | ||
1245 | { 0x0000, 0x0000, 0x0000 }, /* R1147 */ | ||
1246 | { 0x0000, 0x0000, 0x0000 }, /* R1148 */ | ||
1247 | { 0x0000, 0x0000, 0x0000 }, /* R1149 */ | ||
1248 | { 0x0000, 0x0000, 0x0000 }, /* R1150 */ | ||
1249 | { 0x0000, 0x0000, 0x0000 }, /* R1151 */ | ||
1250 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */ | ||
1251 | { 0xFFC0, 0xFFC0, 0x0000 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */ | ||
1252 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1154 - AIF1 DAC1 EQ Band 1 A */ | ||
1253 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */ | ||
1254 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */ | ||
1255 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */ | ||
1256 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */ | ||
1257 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */ | ||
1258 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */ | ||
1259 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */ | ||
1260 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */ | ||
1261 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */ | ||
1262 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */ | ||
1263 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1165 - AIF1 DAC1 EQ Band 4 A */ | ||
1264 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */ | ||
1265 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1167 - AIF1 DAC1 EQ Band 4 C */ | ||
1266 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */ | ||
1267 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */ | ||
1268 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */ | ||
1269 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */ | ||
1270 | { 0x0000, 0x0000, 0x0000 }, /* R1172 */ | ||
1271 | { 0x0000, 0x0000, 0x0000 }, /* R1173 */ | ||
1272 | { 0x0000, 0x0000, 0x0000 }, /* R1174 */ | ||
1273 | { 0x0000, 0x0000, 0x0000 }, /* R1175 */ | ||
1274 | { 0x0000, 0x0000, 0x0000 }, /* R1176 */ | ||
1275 | { 0x0000, 0x0000, 0x0000 }, /* R1177 */ | ||
1276 | { 0x0000, 0x0000, 0x0000 }, /* R1178 */ | ||
1277 | { 0x0000, 0x0000, 0x0000 }, /* R1179 */ | ||
1278 | { 0x0000, 0x0000, 0x0000 }, /* R1180 */ | ||
1279 | { 0x0000, 0x0000, 0x0000 }, /* R1181 */ | ||
1280 | { 0x0000, 0x0000, 0x0000 }, /* R1182 */ | ||
1281 | { 0x0000, 0x0000, 0x0000 }, /* R1183 */ | ||
1282 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */ | ||
1283 | { 0xFFC0, 0xFFC0, 0x0000 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */ | ||
1284 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1186 - AIF1 DAC2 EQ Band 1 A */ | ||
1285 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */ | ||
1286 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */ | ||
1287 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */ | ||
1288 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */ | ||
1289 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */ | ||
1290 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */ | ||
1291 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */ | ||
1292 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */ | ||
1293 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */ | ||
1294 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */ | ||
1295 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1197 - AIF1 DAC2 EQ Band 4 A */ | ||
1296 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */ | ||
1297 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1199 - AIF1 DAC2 EQ Band 4 C */ | ||
1298 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */ | ||
1299 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */ | ||
1300 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */ | ||
1301 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */ | ||
1302 | { 0x0000, 0x0000, 0x0000 }, /* R1204 */ | ||
1303 | { 0x0000, 0x0000, 0x0000 }, /* R1205 */ | ||
1304 | { 0x0000, 0x0000, 0x0000 }, /* R1206 */ | ||
1305 | { 0x0000, 0x0000, 0x0000 }, /* R1207 */ | ||
1306 | { 0x0000, 0x0000, 0x0000 }, /* R1208 */ | ||
1307 | { 0x0000, 0x0000, 0x0000 }, /* R1209 */ | ||
1308 | { 0x0000, 0x0000, 0x0000 }, /* R1210 */ | ||
1309 | { 0x0000, 0x0000, 0x0000 }, /* R1211 */ | ||
1310 | { 0x0000, 0x0000, 0x0000 }, /* R1212 */ | ||
1311 | { 0x0000, 0x0000, 0x0000 }, /* R1213 */ | ||
1312 | { 0x0000, 0x0000, 0x0000 }, /* R1214 */ | ||
1313 | { 0x0000, 0x0000, 0x0000 }, /* R1215 */ | ||
1314 | { 0x0000, 0x0000, 0x0000 }, /* R1216 */ | ||
1315 | { 0x0000, 0x0000, 0x0000 }, /* R1217 */ | ||
1316 | { 0x0000, 0x0000, 0x0000 }, /* R1218 */ | ||
1317 | { 0x0000, 0x0000, 0x0000 }, /* R1219 */ | ||
1318 | { 0x0000, 0x0000, 0x0000 }, /* R1220 */ | ||
1319 | { 0x0000, 0x0000, 0x0000 }, /* R1221 */ | ||
1320 | { 0x0000, 0x0000, 0x0000 }, /* R1222 */ | ||
1321 | { 0x0000, 0x0000, 0x0000 }, /* R1223 */ | ||
1322 | { 0x0000, 0x0000, 0x0000 }, /* R1224 */ | ||
1323 | { 0x0000, 0x0000, 0x0000 }, /* R1225 */ | ||
1324 | { 0x0000, 0x0000, 0x0000 }, /* R1226 */ | ||
1325 | { 0x0000, 0x0000, 0x0000 }, /* R1227 */ | ||
1326 | { 0x0000, 0x0000, 0x0000 }, /* R1228 */ | ||
1327 | { 0x0000, 0x0000, 0x0000 }, /* R1229 */ | ||
1328 | { 0x0000, 0x0000, 0x0000 }, /* R1230 */ | ||
1329 | { 0x0000, 0x0000, 0x0000 }, /* R1231 */ | ||
1330 | { 0x0000, 0x0000, 0x0000 }, /* R1232 */ | ||
1331 | { 0x0000, 0x0000, 0x0000 }, /* R1233 */ | ||
1332 | { 0x0000, 0x0000, 0x0000 }, /* R1234 */ | ||
1333 | { 0x0000, 0x0000, 0x0000 }, /* R1235 */ | ||
1334 | { 0x0000, 0x0000, 0x0000 }, /* R1236 */ | ||
1335 | { 0x0000, 0x0000, 0x0000 }, /* R1237 */ | ||
1336 | { 0x0000, 0x0000, 0x0000 }, /* R1238 */ | ||
1337 | { 0x0000, 0x0000, 0x0000 }, /* R1239 */ | ||
1338 | { 0x0000, 0x0000, 0x0000 }, /* R1240 */ | ||
1339 | { 0x0000, 0x0000, 0x0000 }, /* R1241 */ | ||
1340 | { 0x0000, 0x0000, 0x0000 }, /* R1242 */ | ||
1341 | { 0x0000, 0x0000, 0x0000 }, /* R1243 */ | ||
1342 | { 0x0000, 0x0000, 0x0000 }, /* R1244 */ | ||
1343 | { 0x0000, 0x0000, 0x0000 }, /* R1245 */ | ||
1344 | { 0x0000, 0x0000, 0x0000 }, /* R1246 */ | ||
1345 | { 0x0000, 0x0000, 0x0000 }, /* R1247 */ | ||
1346 | { 0x0000, 0x0000, 0x0000 }, /* R1248 */ | ||
1347 | { 0x0000, 0x0000, 0x0000 }, /* R1249 */ | ||
1348 | { 0x0000, 0x0000, 0x0000 }, /* R1250 */ | ||
1349 | { 0x0000, 0x0000, 0x0000 }, /* R1251 */ | ||
1350 | { 0x0000, 0x0000, 0x0000 }, /* R1252 */ | ||
1351 | { 0x0000, 0x0000, 0x0000 }, /* R1253 */ | ||
1352 | { 0x0000, 0x0000, 0x0000 }, /* R1254 */ | ||
1353 | { 0x0000, 0x0000, 0x0000 }, /* R1255 */ | ||
1354 | { 0x0000, 0x0000, 0x0000 }, /* R1256 */ | ||
1355 | { 0x0000, 0x0000, 0x0000 }, /* R1257 */ | ||
1356 | { 0x0000, 0x0000, 0x0000 }, /* R1258 */ | ||
1357 | { 0x0000, 0x0000, 0x0000 }, /* R1259 */ | ||
1358 | { 0x0000, 0x0000, 0x0000 }, /* R1260 */ | ||
1359 | { 0x0000, 0x0000, 0x0000 }, /* R1261 */ | ||
1360 | { 0x0000, 0x0000, 0x0000 }, /* R1262 */ | ||
1361 | { 0x0000, 0x0000, 0x0000 }, /* R1263 */ | ||
1362 | { 0x0000, 0x0000, 0x0000 }, /* R1264 */ | ||
1363 | { 0x0000, 0x0000, 0x0000 }, /* R1265 */ | ||
1364 | { 0x0000, 0x0000, 0x0000 }, /* R1266 */ | ||
1365 | { 0x0000, 0x0000, 0x0000 }, /* R1267 */ | ||
1366 | { 0x0000, 0x0000, 0x0000 }, /* R1268 */ | ||
1367 | { 0x0000, 0x0000, 0x0000 }, /* R1269 */ | ||
1368 | { 0x0000, 0x0000, 0x0000 }, /* R1270 */ | ||
1369 | { 0x0000, 0x0000, 0x0000 }, /* R1271 */ | ||
1370 | { 0x0000, 0x0000, 0x0000 }, /* R1272 */ | ||
1371 | { 0x0000, 0x0000, 0x0000 }, /* R1273 */ | ||
1372 | { 0x0000, 0x0000, 0x0000 }, /* R1274 */ | ||
1373 | { 0x0000, 0x0000, 0x0000 }, /* R1275 */ | ||
1374 | { 0x0000, 0x0000, 0x0000 }, /* R1276 */ | ||
1375 | { 0x0000, 0x0000, 0x0000 }, /* R1277 */ | ||
1376 | { 0x0000, 0x0000, 0x0000 }, /* R1278 */ | ||
1377 | { 0x0000, 0x0000, 0x0000 }, /* R1279 */ | ||
1378 | { 0x00FF, 0x01FF, 0x0000 }, /* R1280 - AIF2 ADC Left Volume */ | ||
1379 | { 0x00FF, 0x01FF, 0x0000 }, /* R1281 - AIF2 ADC Right Volume */ | ||
1380 | { 0x00FF, 0x01FF, 0x0000 }, /* R1282 - AIF2 DAC Left Volume */ | ||
1381 | { 0x00FF, 0x01FF, 0x0000 }, /* R1283 - AIF2 DAC Right Volume */ | ||
1382 | { 0x0000, 0x0000, 0x0000 }, /* R1284 */ | ||
1383 | { 0x0000, 0x0000, 0x0000 }, /* R1285 */ | ||
1384 | { 0x0000, 0x0000, 0x0000 }, /* R1286 */ | ||
1385 | { 0x0000, 0x0000, 0x0000 }, /* R1287 */ | ||
1386 | { 0x0000, 0x0000, 0x0000 }, /* R1288 */ | ||
1387 | { 0x0000, 0x0000, 0x0000 }, /* R1289 */ | ||
1388 | { 0x0000, 0x0000, 0x0000 }, /* R1290 */ | ||
1389 | { 0x0000, 0x0000, 0x0000 }, /* R1291 */ | ||
1390 | { 0x0000, 0x0000, 0x0000 }, /* R1292 */ | ||
1391 | { 0x0000, 0x0000, 0x0000 }, /* R1293 */ | ||
1392 | { 0x0000, 0x0000, 0x0000 }, /* R1294 */ | ||
1393 | { 0x0000, 0x0000, 0x0000 }, /* R1295 */ | ||
1394 | { 0xF800, 0xF800, 0x0000 }, /* R1296 - AIF2 ADC Filters */ | ||
1395 | { 0x0000, 0x0000, 0x0000 }, /* R1297 */ | ||
1396 | { 0x0000, 0x0000, 0x0000 }, /* R1298 */ | ||
1397 | { 0x0000, 0x0000, 0x0000 }, /* R1299 */ | ||
1398 | { 0x0000, 0x0000, 0x0000 }, /* R1300 */ | ||
1399 | { 0x0000, 0x0000, 0x0000 }, /* R1301 */ | ||
1400 | { 0x0000, 0x0000, 0x0000 }, /* R1302 */ | ||
1401 | { 0x0000, 0x0000, 0x0000 }, /* R1303 */ | ||
1402 | { 0x0000, 0x0000, 0x0000 }, /* R1304 */ | ||
1403 | { 0x0000, 0x0000, 0x0000 }, /* R1305 */ | ||
1404 | { 0x0000, 0x0000, 0x0000 }, /* R1306 */ | ||
1405 | { 0x0000, 0x0000, 0x0000 }, /* R1307 */ | ||
1406 | { 0x0000, 0x0000, 0x0000 }, /* R1308 */ | ||
1407 | { 0x0000, 0x0000, 0x0000 }, /* R1309 */ | ||
1408 | { 0x0000, 0x0000, 0x0000 }, /* R1310 */ | ||
1409 | { 0x0000, 0x0000, 0x0000 }, /* R1311 */ | ||
1410 | { 0x02B6, 0x02B6, 0x0000 }, /* R1312 - AIF2 DAC Filters (1) */ | ||
1411 | { 0x3F00, 0x3F00, 0x0000 }, /* R1313 - AIF2 DAC Filters (2) */ | ||
1412 | { 0x0000, 0x0000, 0x0000 }, /* R1314 */ | ||
1413 | { 0x0000, 0x0000, 0x0000 }, /* R1315 */ | ||
1414 | { 0x0000, 0x0000, 0x0000 }, /* R1316 */ | ||
1415 | { 0x0000, 0x0000, 0x0000 }, /* R1317 */ | ||
1416 | { 0x0000, 0x0000, 0x0000 }, /* R1318 */ | ||
1417 | { 0x0000, 0x0000, 0x0000 }, /* R1319 */ | ||
1418 | { 0x0000, 0x0000, 0x0000 }, /* R1320 */ | ||
1419 | { 0x0000, 0x0000, 0x0000 }, /* R1321 */ | ||
1420 | { 0x0000, 0x0000, 0x0000 }, /* R1322 */ | ||
1421 | { 0x0000, 0x0000, 0x0000 }, /* R1323 */ | ||
1422 | { 0x0000, 0x0000, 0x0000 }, /* R1324 */ | ||
1423 | { 0x0000, 0x0000, 0x0000 }, /* R1325 */ | ||
1424 | { 0x0000, 0x0000, 0x0000 }, /* R1326 */ | ||
1425 | { 0x0000, 0x0000, 0x0000 }, /* R1327 */ | ||
1426 | { 0x0000, 0x0000, 0x0000 }, /* R1328 */ | ||
1427 | { 0x0000, 0x0000, 0x0000 }, /* R1329 */ | ||
1428 | { 0x0000, 0x0000, 0x0000 }, /* R1330 */ | ||
1429 | { 0x0000, 0x0000, 0x0000 }, /* R1331 */ | ||
1430 | { 0x0000, 0x0000, 0x0000 }, /* R1332 */ | ||
1431 | { 0x0000, 0x0000, 0x0000 }, /* R1333 */ | ||
1432 | { 0x0000, 0x0000, 0x0000 }, /* R1334 */ | ||
1433 | { 0x0000, 0x0000, 0x0000 }, /* R1335 */ | ||
1434 | { 0x0000, 0x0000, 0x0000 }, /* R1336 */ | ||
1435 | { 0x0000, 0x0000, 0x0000 }, /* R1337 */ | ||
1436 | { 0x0000, 0x0000, 0x0000 }, /* R1338 */ | ||
1437 | { 0x0000, 0x0000, 0x0000 }, /* R1339 */ | ||
1438 | { 0x0000, 0x0000, 0x0000 }, /* R1340 */ | ||
1439 | { 0x0000, 0x0000, 0x0000 }, /* R1341 */ | ||
1440 | { 0x0000, 0x0000, 0x0000 }, /* R1342 */ | ||
1441 | { 0x0000, 0x0000, 0x0000 }, /* R1343 */ | ||
1442 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1344 - AIF2 DRC (1) */ | ||
1443 | { 0x1FFF, 0x1FFF, 0x0000 }, /* R1345 - AIF2 DRC (2) */ | ||
1444 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1346 - AIF2 DRC (3) */ | ||
1445 | { 0x07FF, 0x07FF, 0x0000 }, /* R1347 - AIF2 DRC (4) */ | ||
1446 | { 0x03FF, 0x03FF, 0x0000 }, /* R1348 - AIF2 DRC (5) */ | ||
1447 | { 0x0000, 0x0000, 0x0000 }, /* R1349 */ | ||
1448 | { 0x0000, 0x0000, 0x0000 }, /* R1350 */ | ||
1449 | { 0x0000, 0x0000, 0x0000 }, /* R1351 */ | ||
1450 | { 0x0000, 0x0000, 0x0000 }, /* R1352 */ | ||
1451 | { 0x0000, 0x0000, 0x0000 }, /* R1353 */ | ||
1452 | { 0x0000, 0x0000, 0x0000 }, /* R1354 */ | ||
1453 | { 0x0000, 0x0000, 0x0000 }, /* R1355 */ | ||
1454 | { 0x0000, 0x0000, 0x0000 }, /* R1356 */ | ||
1455 | { 0x0000, 0x0000, 0x0000 }, /* R1357 */ | ||
1456 | { 0x0000, 0x0000, 0x0000 }, /* R1358 */ | ||
1457 | { 0x0000, 0x0000, 0x0000 }, /* R1359 */ | ||
1458 | { 0x0000, 0x0000, 0x0000 }, /* R1360 */ | ||
1459 | { 0x0000, 0x0000, 0x0000 }, /* R1361 */ | ||
1460 | { 0x0000, 0x0000, 0x0000 }, /* R1362 */ | ||
1461 | { 0x0000, 0x0000, 0x0000 }, /* R1363 */ | ||
1462 | { 0x0000, 0x0000, 0x0000 }, /* R1364 */ | ||
1463 | { 0x0000, 0x0000, 0x0000 }, /* R1365 */ | ||
1464 | { 0x0000, 0x0000, 0x0000 }, /* R1366 */ | ||
1465 | { 0x0000, 0x0000, 0x0000 }, /* R1367 */ | ||
1466 | { 0x0000, 0x0000, 0x0000 }, /* R1368 */ | ||
1467 | { 0x0000, 0x0000, 0x0000 }, /* R1369 */ | ||
1468 | { 0x0000, 0x0000, 0x0000 }, /* R1370 */ | ||
1469 | { 0x0000, 0x0000, 0x0000 }, /* R1371 */ | ||
1470 | { 0x0000, 0x0000, 0x0000 }, /* R1372 */ | ||
1471 | { 0x0000, 0x0000, 0x0000 }, /* R1373 */ | ||
1472 | { 0x0000, 0x0000, 0x0000 }, /* R1374 */ | ||
1473 | { 0x0000, 0x0000, 0x0000 }, /* R1375 */ | ||
1474 | { 0x0000, 0x0000, 0x0000 }, /* R1376 */ | ||
1475 | { 0x0000, 0x0000, 0x0000 }, /* R1377 */ | ||
1476 | { 0x0000, 0x0000, 0x0000 }, /* R1378 */ | ||
1477 | { 0x0000, 0x0000, 0x0000 }, /* R1379 */ | ||
1478 | { 0x0000, 0x0000, 0x0000 }, /* R1380 */ | ||
1479 | { 0x0000, 0x0000, 0x0000 }, /* R1381 */ | ||
1480 | { 0x0000, 0x0000, 0x0000 }, /* R1382 */ | ||
1481 | { 0x0000, 0x0000, 0x0000 }, /* R1383 */ | ||
1482 | { 0x0000, 0x0000, 0x0000 }, /* R1384 */ | ||
1483 | { 0x0000, 0x0000, 0x0000 }, /* R1385 */ | ||
1484 | { 0x0000, 0x0000, 0x0000 }, /* R1386 */ | ||
1485 | { 0x0000, 0x0000, 0x0000 }, /* R1387 */ | ||
1486 | { 0x0000, 0x0000, 0x0000 }, /* R1388 */ | ||
1487 | { 0x0000, 0x0000, 0x0000 }, /* R1389 */ | ||
1488 | { 0x0000, 0x0000, 0x0000 }, /* R1390 */ | ||
1489 | { 0x0000, 0x0000, 0x0000 }, /* R1391 */ | ||
1490 | { 0x0000, 0x0000, 0x0000 }, /* R1392 */ | ||
1491 | { 0x0000, 0x0000, 0x0000 }, /* R1393 */ | ||
1492 | { 0x0000, 0x0000, 0x0000 }, /* R1394 */ | ||
1493 | { 0x0000, 0x0000, 0x0000 }, /* R1395 */ | ||
1494 | { 0x0000, 0x0000, 0x0000 }, /* R1396 */ | ||
1495 | { 0x0000, 0x0000, 0x0000 }, /* R1397 */ | ||
1496 | { 0x0000, 0x0000, 0x0000 }, /* R1398 */ | ||
1497 | { 0x0000, 0x0000, 0x0000 }, /* R1399 */ | ||
1498 | { 0x0000, 0x0000, 0x0000 }, /* R1400 */ | ||
1499 | { 0x0000, 0x0000, 0x0000 }, /* R1401 */ | ||
1500 | { 0x0000, 0x0000, 0x0000 }, /* R1402 */ | ||
1501 | { 0x0000, 0x0000, 0x0000 }, /* R1403 */ | ||
1502 | { 0x0000, 0x0000, 0x0000 }, /* R1404 */ | ||
1503 | { 0x0000, 0x0000, 0x0000 }, /* R1405 */ | ||
1504 | { 0x0000, 0x0000, 0x0000 }, /* R1406 */ | ||
1505 | { 0x0000, 0x0000, 0x0000 }, /* R1407 */ | ||
1506 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1408 - AIF2 EQ Gains (1) */ | ||
1507 | { 0xFFC0, 0xFFC0, 0x0000 }, /* R1409 - AIF2 EQ Gains (2) */ | ||
1508 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1410 - AIF2 EQ Band 1 A */ | ||
1509 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1411 - AIF2 EQ Band 1 B */ | ||
1510 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1412 - AIF2 EQ Band 1 PG */ | ||
1511 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1413 - AIF2 EQ Band 2 A */ | ||
1512 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1414 - AIF2 EQ Band 2 B */ | ||
1513 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1415 - AIF2 EQ Band 2 C */ | ||
1514 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1416 - AIF2 EQ Band 2 PG */ | ||
1515 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1417 - AIF2 EQ Band 3 A */ | ||
1516 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1418 - AIF2 EQ Band 3 B */ | ||
1517 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1419 - AIF2 EQ Band 3 C */ | ||
1518 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1420 - AIF2 EQ Band 3 PG */ | ||
1519 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1421 - AIF2 EQ Band 4 A */ | ||
1520 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1422 - AIF2 EQ Band 4 B */ | ||
1521 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1423 - AIF2 EQ Band 4 C */ | ||
1522 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1424 - AIF2 EQ Band 4 PG */ | ||
1523 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1425 - AIF2 EQ Band 5 A */ | ||
1524 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1426 - AIF2 EQ Band 5 B */ | ||
1525 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R1427 - AIF2 EQ Band 5 PG */ | ||
1526 | { 0x0000, 0x0000, 0x0000 }, /* R1428 */ | ||
1527 | { 0x0000, 0x0000, 0x0000 }, /* R1429 */ | ||
1528 | { 0x0000, 0x0000, 0x0000 }, /* R1430 */ | ||
1529 | { 0x0000, 0x0000, 0x0000 }, /* R1431 */ | ||
1530 | { 0x0000, 0x0000, 0x0000 }, /* R1432 */ | ||
1531 | { 0x0000, 0x0000, 0x0000 }, /* R1433 */ | ||
1532 | { 0x0000, 0x0000, 0x0000 }, /* R1434 */ | ||
1533 | { 0x0000, 0x0000, 0x0000 }, /* R1435 */ | ||
1534 | { 0x0000, 0x0000, 0x0000 }, /* R1436 */ | ||
1535 | { 0x0000, 0x0000, 0x0000 }, /* R1437 */ | ||
1536 | { 0x0000, 0x0000, 0x0000 }, /* R1438 */ | ||
1537 | { 0x0000, 0x0000, 0x0000 }, /* R1439 */ | ||
1538 | { 0x0000, 0x0000, 0x0000 }, /* R1440 */ | ||
1539 | { 0x0000, 0x0000, 0x0000 }, /* R1441 */ | ||
1540 | { 0x0000, 0x0000, 0x0000 }, /* R1442 */ | ||
1541 | { 0x0000, 0x0000, 0x0000 }, /* R1443 */ | ||
1542 | { 0x0000, 0x0000, 0x0000 }, /* R1444 */ | ||
1543 | { 0x0000, 0x0000, 0x0000 }, /* R1445 */ | ||
1544 | { 0x0000, 0x0000, 0x0000 }, /* R1446 */ | ||
1545 | { 0x0000, 0x0000, 0x0000 }, /* R1447 */ | ||
1546 | { 0x0000, 0x0000, 0x0000 }, /* R1448 */ | ||
1547 | { 0x0000, 0x0000, 0x0000 }, /* R1449 */ | ||
1548 | { 0x0000, 0x0000, 0x0000 }, /* R1450 */ | ||
1549 | { 0x0000, 0x0000, 0x0000 }, /* R1451 */ | ||
1550 | { 0x0000, 0x0000, 0x0000 }, /* R1452 */ | ||
1551 | { 0x0000, 0x0000, 0x0000 }, /* R1453 */ | ||
1552 | { 0x0000, 0x0000, 0x0000 }, /* R1454 */ | ||
1553 | { 0x0000, 0x0000, 0x0000 }, /* R1455 */ | ||
1554 | { 0x0000, 0x0000, 0x0000 }, /* R1456 */ | ||
1555 | { 0x0000, 0x0000, 0x0000 }, /* R1457 */ | ||
1556 | { 0x0000, 0x0000, 0x0000 }, /* R1458 */ | ||
1557 | { 0x0000, 0x0000, 0x0000 }, /* R1459 */ | ||
1558 | { 0x0000, 0x0000, 0x0000 }, /* R1460 */ | ||
1559 | { 0x0000, 0x0000, 0x0000 }, /* R1461 */ | ||
1560 | { 0x0000, 0x0000, 0x0000 }, /* R1462 */ | ||
1561 | { 0x0000, 0x0000, 0x0000 }, /* R1463 */ | ||
1562 | { 0x0000, 0x0000, 0x0000 }, /* R1464 */ | ||
1563 | { 0x0000, 0x0000, 0x0000 }, /* R1465 */ | ||
1564 | { 0x0000, 0x0000, 0x0000 }, /* R1466 */ | ||
1565 | { 0x0000, 0x0000, 0x0000 }, /* R1467 */ | ||
1566 | { 0x0000, 0x0000, 0x0000 }, /* R1468 */ | ||
1567 | { 0x0000, 0x0000, 0x0000 }, /* R1469 */ | ||
1568 | { 0x0000, 0x0000, 0x0000 }, /* R1470 */ | ||
1569 | { 0x0000, 0x0000, 0x0000 }, /* R1471 */ | ||
1570 | { 0x0000, 0x0000, 0x0000 }, /* R1472 */ | ||
1571 | { 0x0000, 0x0000, 0x0000 }, /* R1473 */ | ||
1572 | { 0x0000, 0x0000, 0x0000 }, /* R1474 */ | ||
1573 | { 0x0000, 0x0000, 0x0000 }, /* R1475 */ | ||
1574 | { 0x0000, 0x0000, 0x0000 }, /* R1476 */ | ||
1575 | { 0x0000, 0x0000, 0x0000 }, /* R1477 */ | ||
1576 | { 0x0000, 0x0000, 0x0000 }, /* R1478 */ | ||
1577 | { 0x0000, 0x0000, 0x0000 }, /* R1479 */ | ||
1578 | { 0x0000, 0x0000, 0x0000 }, /* R1480 */ | ||
1579 | { 0x0000, 0x0000, 0x0000 }, /* R1481 */ | ||
1580 | { 0x0000, 0x0000, 0x0000 }, /* R1482 */ | ||
1581 | { 0x0000, 0x0000, 0x0000 }, /* R1483 */ | ||
1582 | { 0x0000, 0x0000, 0x0000 }, /* R1484 */ | ||
1583 | { 0x0000, 0x0000, 0x0000 }, /* R1485 */ | ||
1584 | { 0x0000, 0x0000, 0x0000 }, /* R1486 */ | ||
1585 | { 0x0000, 0x0000, 0x0000 }, /* R1487 */ | ||
1586 | { 0x0000, 0x0000, 0x0000 }, /* R1488 */ | ||
1587 | { 0x0000, 0x0000, 0x0000 }, /* R1489 */ | ||
1588 | { 0x0000, 0x0000, 0x0000 }, /* R1490 */ | ||
1589 | { 0x0000, 0x0000, 0x0000 }, /* R1491 */ | ||
1590 | { 0x0000, 0x0000, 0x0000 }, /* R1492 */ | ||
1591 | { 0x0000, 0x0000, 0x0000 }, /* R1493 */ | ||
1592 | { 0x0000, 0x0000, 0x0000 }, /* R1494 */ | ||
1593 | { 0x0000, 0x0000, 0x0000 }, /* R1495 */ | ||
1594 | { 0x0000, 0x0000, 0x0000 }, /* R1496 */ | ||
1595 | { 0x0000, 0x0000, 0x0000 }, /* R1497 */ | ||
1596 | { 0x0000, 0x0000, 0x0000 }, /* R1498 */ | ||
1597 | { 0x0000, 0x0000, 0x0000 }, /* R1499 */ | ||
1598 | { 0x0000, 0x0000, 0x0000 }, /* R1500 */ | ||
1599 | { 0x0000, 0x0000, 0x0000 }, /* R1501 */ | ||
1600 | { 0x0000, 0x0000, 0x0000 }, /* R1502 */ | ||
1601 | { 0x0000, 0x0000, 0x0000 }, /* R1503 */ | ||
1602 | { 0x0000, 0x0000, 0x0000 }, /* R1504 */ | ||
1603 | { 0x0000, 0x0000, 0x0000 }, /* R1505 */ | ||
1604 | { 0x0000, 0x0000, 0x0000 }, /* R1506 */ | ||
1605 | { 0x0000, 0x0000, 0x0000 }, /* R1507 */ | ||
1606 | { 0x0000, 0x0000, 0x0000 }, /* R1508 */ | ||
1607 | { 0x0000, 0x0000, 0x0000 }, /* R1509 */ | ||
1608 | { 0x0000, 0x0000, 0x0000 }, /* R1510 */ | ||
1609 | { 0x0000, 0x0000, 0x0000 }, /* R1511 */ | ||
1610 | { 0x0000, 0x0000, 0x0000 }, /* R1512 */ | ||
1611 | { 0x0000, 0x0000, 0x0000 }, /* R1513 */ | ||
1612 | { 0x0000, 0x0000, 0x0000 }, /* R1514 */ | ||
1613 | { 0x0000, 0x0000, 0x0000 }, /* R1515 */ | ||
1614 | { 0x0000, 0x0000, 0x0000 }, /* R1516 */ | ||
1615 | { 0x0000, 0x0000, 0x0000 }, /* R1517 */ | ||
1616 | { 0x0000, 0x0000, 0x0000 }, /* R1518 */ | ||
1617 | { 0x0000, 0x0000, 0x0000 }, /* R1519 */ | ||
1618 | { 0x0000, 0x0000, 0x0000 }, /* R1520 */ | ||
1619 | { 0x0000, 0x0000, 0x0000 }, /* R1521 */ | ||
1620 | { 0x0000, 0x0000, 0x0000 }, /* R1522 */ | ||
1621 | { 0x0000, 0x0000, 0x0000 }, /* R1523 */ | ||
1622 | { 0x0000, 0x0000, 0x0000 }, /* R1524 */ | ||
1623 | { 0x0000, 0x0000, 0x0000 }, /* R1525 */ | ||
1624 | { 0x0000, 0x0000, 0x0000 }, /* R1526 */ | ||
1625 | { 0x0000, 0x0000, 0x0000 }, /* R1527 */ | ||
1626 | { 0x0000, 0x0000, 0x0000 }, /* R1528 */ | ||
1627 | { 0x0000, 0x0000, 0x0000 }, /* R1529 */ | ||
1628 | { 0x0000, 0x0000, 0x0000 }, /* R1530 */ | ||
1629 | { 0x0000, 0x0000, 0x0000 }, /* R1531 */ | ||
1630 | { 0x0000, 0x0000, 0x0000 }, /* R1532 */ | ||
1631 | { 0x0000, 0x0000, 0x0000 }, /* R1533 */ | ||
1632 | { 0x0000, 0x0000, 0x0000 }, /* R1534 */ | ||
1633 | { 0x0000, 0x0000, 0x0000 }, /* R1535 */ | ||
1634 | { 0x01EF, 0x01EF, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */ | ||
1635 | { 0x0037, 0x0037, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */ | ||
1636 | { 0x0037, 0x0037, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */ | ||
1637 | { 0x01EF, 0x01EF, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */ | ||
1638 | { 0x0037, 0x0037, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */ | ||
1639 | { 0x0037, 0x0037, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */ | ||
1640 | { 0x0003, 0x0003, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */ | ||
1641 | { 0x0003, 0x0003, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */ | ||
1642 | { 0x0003, 0x0003, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */ | ||
1643 | { 0x0003, 0x0003, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */ | ||
1644 | { 0x0000, 0x0000, 0x0000 }, /* R1546 */ | ||
1645 | { 0x0000, 0x0000, 0x0000 }, /* R1547 */ | ||
1646 | { 0x0000, 0x0000, 0x0000 }, /* R1548 */ | ||
1647 | { 0x0000, 0x0000, 0x0000 }, /* R1549 */ | ||
1648 | { 0x0000, 0x0000, 0x0000 }, /* R1550 */ | ||
1649 | { 0x0000, 0x0000, 0x0000 }, /* R1551 */ | ||
1650 | { 0x02FF, 0x03FF, 0x0000 }, /* R1552 - DAC1 Left Volume */ | ||
1651 | { 0x02FF, 0x03FF, 0x0000 }, /* R1553 - DAC1 Right Volume */ | ||
1652 | { 0x02FF, 0x03FF, 0x0000 }, /* R1554 - DAC2 Left Volume */ | ||
1653 | { 0x02FF, 0x03FF, 0x0000 }, /* R1555 - DAC2 Right Volume */ | ||
1654 | { 0x0003, 0x0003, 0x0000 }, /* R1556 - DAC Softmute */ | ||
1655 | { 0x0000, 0x0000, 0x0000 }, /* R1557 */ | ||
1656 | { 0x0000, 0x0000, 0x0000 }, /* R1558 */ | ||
1657 | { 0x0000, 0x0000, 0x0000 }, /* R1559 */ | ||
1658 | { 0x0000, 0x0000, 0x0000 }, /* R1560 */ | ||
1659 | { 0x0000, 0x0000, 0x0000 }, /* R1561 */ | ||
1660 | { 0x0000, 0x0000, 0x0000 }, /* R1562 */ | ||
1661 | { 0x0000, 0x0000, 0x0000 }, /* R1563 */ | ||
1662 | { 0x0000, 0x0000, 0x0000 }, /* R1564 */ | ||
1663 | { 0x0000, 0x0000, 0x0000 }, /* R1565 */ | ||
1664 | { 0x0000, 0x0000, 0x0000 }, /* R1566 */ | ||
1665 | { 0x0000, 0x0000, 0x0000 }, /* R1567 */ | ||
1666 | { 0x0003, 0x0003, 0x0000 }, /* R1568 - Oversampling */ | ||
1667 | { 0x03C3, 0x03C3, 0x0000 }, /* R1569 - Sidetone */ | ||
1668 | }; | ||
1669 | |||
1670 | static int wm8994_readable(unsigned int reg) | ||
1671 | { | ||
1672 | if (reg >= ARRAY_SIZE(access_masks)) | ||
1673 | return 0; | ||
1674 | return access_masks[reg].readable != 0; | ||
1675 | } | ||
1676 | |||
1677 | static int wm8994_volatile(unsigned int reg) | ||
1678 | { | ||
1679 | if (reg >= WM8994_REG_CACHE_SIZE) | ||
1680 | return 1; | ||
1681 | |||
1682 | switch (reg) { | ||
1683 | case WM8994_SOFTWARE_RESET: | ||
1684 | case WM8994_CHIP_REVISION: | ||
1685 | case WM8994_DC_SERVO_1: | ||
1686 | case WM8994_DC_SERVO_READBACK: | ||
1687 | case WM8994_RATE_STATUS: | ||
1688 | case WM8994_LDO_1: | ||
1689 | case WM8994_LDO_2: | ||
1690 | return 1; | ||
1691 | default: | ||
1692 | return 0; | ||
1693 | } | ||
1694 | } | ||
1695 | |||
1696 | static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, | ||
1697 | unsigned int value) | ||
1698 | { | ||
1699 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1700 | |||
1701 | BUG_ON(reg > WM8994_MAX_REGISTER); | ||
1702 | |||
1703 | if (!wm8994_volatile(reg)) | ||
1704 | wm8994->reg_cache[reg] = value; | ||
1705 | |||
1706 | return wm8994_reg_write(codec->control_data, reg, value); | ||
1707 | } | ||
1708 | |||
1709 | static unsigned int wm8994_read(struct snd_soc_codec *codec, | ||
1710 | unsigned int reg) | ||
1711 | { | ||
1712 | u16 *reg_cache = codec->reg_cache; | ||
1713 | |||
1714 | BUG_ON(reg > WM8994_MAX_REGISTER); | ||
1715 | |||
1716 | if (wm8994_volatile(reg)) | ||
1717 | return wm8994_reg_read(codec->control_data, reg); | ||
1718 | else | ||
1719 | return reg_cache[reg]; | ||
1720 | } | ||
1721 | |||
1722 | static int configure_aif_clock(struct snd_soc_codec *codec, int aif) | ||
1723 | { | ||
1724 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1725 | int rate; | ||
1726 | int reg1 = 0; | ||
1727 | int offset; | ||
1728 | |||
1729 | if (aif) | ||
1730 | offset = 4; | ||
1731 | else | ||
1732 | offset = 0; | ||
1733 | |||
1734 | switch (wm8994->sysclk[aif]) { | ||
1735 | case WM8994_SYSCLK_MCLK1: | ||
1736 | rate = wm8994->mclk[0]; | ||
1737 | break; | ||
1738 | |||
1739 | case WM8994_SYSCLK_MCLK2: | ||
1740 | reg1 |= 0x8; | ||
1741 | rate = wm8994->mclk[1]; | ||
1742 | break; | ||
1743 | |||
1744 | case WM8994_SYSCLK_FLL1: | ||
1745 | reg1 |= 0x10; | ||
1746 | rate = wm8994->fll[0].out; | ||
1747 | break; | ||
1748 | |||
1749 | case WM8994_SYSCLK_FLL2: | ||
1750 | reg1 |= 0x18; | ||
1751 | rate = wm8994->fll[1].out; | ||
1752 | break; | ||
1753 | |||
1754 | default: | ||
1755 | return -EINVAL; | ||
1756 | } | ||
1757 | |||
1758 | if (rate >= 13500000) { | ||
1759 | rate /= 2; | ||
1760 | reg1 |= WM8994_AIF1CLK_DIV; | ||
1761 | |||
1762 | dev_dbg(codec->dev, "Dividing AIF%d clock to %dHz\n", | ||
1763 | aif + 1, rate); | ||
1764 | } | ||
1765 | wm8994->aifclk[aif] = rate; | ||
1766 | |||
1767 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, | ||
1768 | WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV, | ||
1769 | reg1); | ||
1770 | |||
1771 | return 0; | ||
1772 | } | ||
1773 | |||
1774 | static int configure_clock(struct snd_soc_codec *codec) | ||
1775 | { | ||
1776 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1777 | int old, new; | ||
1778 | |||
1779 | /* Bring up the AIF clocks first */ | ||
1780 | configure_aif_clock(codec, 0); | ||
1781 | configure_aif_clock(codec, 1); | ||
1782 | |||
1783 | /* Then switch CLK_SYS over to the higher of them; a change | ||
1784 | * can only happen as a result of a clocking change which can | ||
1785 | * only be made outside of DAPM so we can safely redo the | ||
1786 | * clocking. | ||
1787 | */ | ||
1788 | |||
1789 | /* If they're equal it doesn't matter which is used */ | ||
1790 | if (wm8994->aifclk[0] == wm8994->aifclk[1]) | ||
1791 | return 0; | ||
1792 | |||
1793 | if (wm8994->aifclk[0] < wm8994->aifclk[1]) | ||
1794 | new = WM8994_SYSCLK_SRC; | ||
1795 | else | ||
1796 | new = 0; | ||
1797 | |||
1798 | old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC; | ||
1799 | |||
1800 | /* If there's no change then we're done. */ | ||
1801 | if (old == new) | ||
1802 | return 0; | ||
1803 | |||
1804 | snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new); | ||
1805 | |||
1806 | snd_soc_dapm_sync(codec); | ||
1807 | |||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1811 | static int check_clk_sys(struct snd_soc_dapm_widget *source, | ||
1812 | struct snd_soc_dapm_widget *sink) | ||
1813 | { | ||
1814 | int reg = snd_soc_read(source->codec, WM8994_CLOCKING_1); | ||
1815 | const char *clk; | ||
1816 | |||
1817 | /* Check what we're currently using for CLK_SYS */ | ||
1818 | if (reg & WM8994_SYSCLK_SRC) | ||
1819 | clk = "AIF2CLK"; | ||
1820 | else | ||
1821 | clk = "AIF1CLK"; | ||
1822 | |||
1823 | return strcmp(source->name, clk) == 0; | ||
1824 | } | ||
1825 | |||
1826 | static const char *sidetone_hpf_text[] = { | ||
1827 | "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz" | ||
1828 | }; | ||
1829 | |||
1830 | static const struct soc_enum sidetone_hpf = | ||
1831 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text); | ||
1832 | |||
1833 | static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); | ||
1834 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | ||
1835 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); | ||
1836 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); | ||
1837 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
1838 | |||
1839 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | ||
1840 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
1841 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | ||
1842 | .put = wm8994_put_drc_sw, \ | ||
1843 | .private_value = SOC_SINGLE_VALUE(reg, shift, 1, 0) } | ||
1844 | |||
1845 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | ||
1846 | struct snd_ctl_elem_value *ucontrol) | ||
1847 | { | ||
1848 | struct soc_mixer_control *mc = | ||
1849 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1850 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1851 | int mask, ret; | ||
1852 | |||
1853 | /* Can't enable both ADC and DAC paths simultaneously */ | ||
1854 | if (mc->shift == WM8994_AIF1DAC1_DRC_ENA_SHIFT) | ||
1855 | mask = WM8994_AIF1ADC1L_DRC_ENA_MASK | | ||
1856 | WM8994_AIF1ADC1R_DRC_ENA_MASK; | ||
1857 | else | ||
1858 | mask = WM8994_AIF1DAC1_DRC_ENA_MASK; | ||
1859 | |||
1860 | ret = snd_soc_read(codec, mc->reg); | ||
1861 | if (ret < 0) | ||
1862 | return ret; | ||
1863 | if (ret & mask) | ||
1864 | return -EINVAL; | ||
1865 | |||
1866 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
1867 | } | ||
1868 | |||
1869 | |||
1870 | |||
1871 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) | ||
1872 | { | ||
1873 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1874 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
1875 | int base = wm8994_drc_base[drc]; | ||
1876 | int cfg = wm8994->drc_cfg[drc]; | ||
1877 | int save, i; | ||
1878 | |||
1879 | /* Save any enables; the configuration should clear them. */ | ||
1880 | save = snd_soc_read(codec, base); | ||
1881 | save &= WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | | ||
1882 | WM8994_AIF1ADC1R_DRC_ENA; | ||
1883 | |||
1884 | for (i = 0; i < WM8994_DRC_REGS; i++) | ||
1885 | snd_soc_update_bits(codec, base + i, 0xffff, | ||
1886 | pdata->drc_cfgs[cfg].regs[i]); | ||
1887 | |||
1888 | snd_soc_update_bits(codec, base, WM8994_AIF1DAC1_DRC_ENA | | ||
1889 | WM8994_AIF1ADC1L_DRC_ENA | | ||
1890 | WM8994_AIF1ADC1R_DRC_ENA, save); | ||
1891 | } | ||
1892 | |||
1893 | /* Icky as hell but saves code duplication */ | ||
1894 | static int wm8994_get_drc(const char *name) | ||
1895 | { | ||
1896 | if (strcmp(name, "AIF1DRC1 Mode") == 0) | ||
1897 | return 0; | ||
1898 | if (strcmp(name, "AIF1DRC2 Mode") == 0) | ||
1899 | return 1; | ||
1900 | if (strcmp(name, "AIF2DRC Mode") == 0) | ||
1901 | return 2; | ||
1902 | return -EINVAL; | ||
1903 | } | ||
1904 | |||
1905 | static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, | ||
1906 | struct snd_ctl_elem_value *ucontrol) | ||
1907 | { | ||
1908 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1909 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1910 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
1911 | int drc = wm8994_get_drc(kcontrol->id.name); | ||
1912 | int value = ucontrol->value.integer.value[0]; | ||
1913 | |||
1914 | if (drc < 0) | ||
1915 | return drc; | ||
1916 | |||
1917 | if (value >= pdata->num_drc_cfgs) | ||
1918 | return -EINVAL; | ||
1919 | |||
1920 | wm8994->drc_cfg[drc] = value; | ||
1921 | |||
1922 | wm8994_set_drc(codec, drc); | ||
1923 | |||
1924 | return 0; | ||
1925 | } | ||
1926 | |||
1927 | static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol, | ||
1928 | struct snd_ctl_elem_value *ucontrol) | ||
1929 | { | ||
1930 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1931 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1932 | int drc = wm8994_get_drc(kcontrol->id.name); | ||
1933 | |||
1934 | ucontrol->value.enumerated.item[0] = wm8994->drc_cfg[drc]; | ||
1935 | |||
1936 | return 0; | ||
1937 | } | ||
1938 | |||
1939 | static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block) | ||
1940 | { | ||
1941 | struct wm8994_priv *wm8994 = codec->private_data; | ||
1942 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
1943 | int base = wm8994_retune_mobile_base[block]; | ||
1944 | int iface, best, best_val, save, i, cfg; | ||
1945 | |||
1946 | if (!pdata || !wm8994->num_retune_mobile_texts) | ||
1947 | return; | ||
1948 | |||
1949 | switch (block) { | ||
1950 | case 0: | ||
1951 | case 1: | ||
1952 | iface = 0; | ||
1953 | break; | ||
1954 | case 2: | ||
1955 | iface = 1; | ||
1956 | break; | ||
1957 | default: | ||
1958 | return; | ||
1959 | } | ||
1960 | |||
1961 | /* Find the version of the currently selected configuration | ||
1962 | * with the nearest sample rate. */ | ||
1963 | cfg = wm8994->retune_mobile_cfg[block]; | ||
1964 | best = 0; | ||
1965 | best_val = INT_MAX; | ||
1966 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
1967 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
1968 | wm8994->retune_mobile_texts[cfg]) == 0 && | ||
1969 | abs(pdata->retune_mobile_cfgs[i].rate | ||
1970 | - wm8994->dac_rates[iface]) < best_val) { | ||
1971 | best = i; | ||
1972 | best_val = abs(pdata->retune_mobile_cfgs[i].rate | ||
1973 | - wm8994->dac_rates[iface]); | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n", | ||
1978 | block, | ||
1979 | pdata->retune_mobile_cfgs[best].name, | ||
1980 | pdata->retune_mobile_cfgs[best].rate, | ||
1981 | wm8994->dac_rates[iface]); | ||
1982 | |||
1983 | /* The EQ will be disabled while reconfiguring it, remember the | ||
1984 | * current configuration. | ||
1985 | */ | ||
1986 | save = snd_soc_read(codec, base); | ||
1987 | save &= WM8994_AIF1DAC1_EQ_ENA; | ||
1988 | |||
1989 | for (i = 0; i < WM8994_EQ_REGS; i++) | ||
1990 | snd_soc_update_bits(codec, base + i, 0xffff, | ||
1991 | pdata->retune_mobile_cfgs[best].regs[i]); | ||
1992 | |||
1993 | snd_soc_update_bits(codec, base, WM8994_AIF1DAC1_EQ_ENA, save); | ||
1994 | } | ||
1995 | |||
1996 | /* Icky as hell but saves code duplication */ | ||
1997 | static int wm8994_get_retune_mobile_block(const char *name) | ||
1998 | { | ||
1999 | if (strcmp(name, "AIF1.1 EQ Mode") == 0) | ||
2000 | return 0; | ||
2001 | if (strcmp(name, "AIF1.2 EQ Mode") == 0) | ||
2002 | return 1; | ||
2003 | if (strcmp(name, "AIF2 EQ Mode") == 0) | ||
2004 | return 2; | ||
2005 | return -EINVAL; | ||
2006 | } | ||
2007 | |||
2008 | static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
2009 | struct snd_ctl_elem_value *ucontrol) | ||
2010 | { | ||
2011 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2012 | struct wm8994_priv *wm8994 = codec->private_data; | ||
2013 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
2014 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | ||
2015 | int value = ucontrol->value.integer.value[0]; | ||
2016 | |||
2017 | if (block < 0) | ||
2018 | return block; | ||
2019 | |||
2020 | if (value >= pdata->num_retune_mobile_cfgs) | ||
2021 | return -EINVAL; | ||
2022 | |||
2023 | wm8994->retune_mobile_cfg[block] = value; | ||
2024 | |||
2025 | wm8994_set_retune_mobile(codec, block); | ||
2026 | |||
2027 | return 0; | ||
2028 | } | ||
2029 | |||
2030 | static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | ||
2031 | struct snd_ctl_elem_value *ucontrol) | ||
2032 | { | ||
2033 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2034 | struct wm8994_priv *wm8994 = codec->private_data; | ||
2035 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | ||
2036 | |||
2037 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | ||
2038 | |||
2039 | return 0; | ||
2040 | } | ||
2041 | |||
2042 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { | ||
2043 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, | ||
2044 | WM8994_AIF1_ADC1_RIGHT_VOLUME, | ||
2045 | 1, 119, 0, digital_tlv), | ||
2046 | SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME, | ||
2047 | WM8994_AIF1_ADC2_RIGHT_VOLUME, | ||
2048 | 1, 119, 0, digital_tlv), | ||
2049 | SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME, | ||
2050 | WM8994_AIF2_ADC_RIGHT_VOLUME, | ||
2051 | 1, 119, 0, digital_tlv), | ||
2052 | |||
2053 | SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME, | ||
2054 | WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
2055 | SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME, | ||
2056 | WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
2057 | SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME, | ||
2058 | WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
2059 | |||
2060 | SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv), | ||
2061 | SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv), | ||
2062 | |||
2063 | SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0), | ||
2064 | SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0), | ||
2065 | SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0), | ||
2066 | |||
2067 | WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2), | ||
2068 | WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1), | ||
2069 | WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0), | ||
2070 | |||
2071 | WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2), | ||
2072 | WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1), | ||
2073 | WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0), | ||
2074 | |||
2075 | WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2), | ||
2076 | WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1), | ||
2077 | WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0), | ||
2078 | |||
2079 | SOC_SINGLE_TLV("DAC1 Right Sidetone Volume", WM8994_DAC1_MIXER_VOLUMES, | ||
2080 | 5, 12, 0, st_tlv), | ||
2081 | SOC_SINGLE_TLV("DAC1 Left Sidetone Volume", WM8994_DAC1_MIXER_VOLUMES, | ||
2082 | 0, 12, 0, st_tlv), | ||
2083 | SOC_SINGLE_TLV("DAC2 Right Sidetone Volume", WM8994_DAC2_MIXER_VOLUMES, | ||
2084 | 5, 12, 0, st_tlv), | ||
2085 | SOC_SINGLE_TLV("DAC2 Left Sidetone Volume", WM8994_DAC2_MIXER_VOLUMES, | ||
2086 | 0, 12, 0, st_tlv), | ||
2087 | SOC_ENUM("Sidetone HPF Mux", sidetone_hpf), | ||
2088 | SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0), | ||
2089 | |||
2090 | SOC_DOUBLE_R_TLV("DAC1 Volume", WM8994_DAC1_LEFT_VOLUME, | ||
2091 | WM8994_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
2092 | SOC_DOUBLE_R("DAC1 Switch", WM8994_DAC1_LEFT_VOLUME, | ||
2093 | WM8994_DAC1_RIGHT_VOLUME, 9, 1, 1), | ||
2094 | |||
2095 | SOC_DOUBLE_R_TLV("DAC2 Volume", WM8994_DAC2_LEFT_VOLUME, | ||
2096 | WM8994_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), | ||
2097 | SOC_DOUBLE_R("DAC2 Switch", WM8994_DAC2_LEFT_VOLUME, | ||
2098 | WM8994_DAC2_RIGHT_VOLUME, 9, 1, 1), | ||
2099 | |||
2100 | SOC_SINGLE_TLV("SPKL DAC2 Volume", WM8994_SPKMIXL_ATTENUATION, | ||
2101 | 6, 1, 1, wm_hubs_spkmix_tlv), | ||
2102 | SOC_SINGLE_TLV("SPKL DAC1 Volume", WM8994_SPKMIXL_ATTENUATION, | ||
2103 | 2, 1, 1, wm_hubs_spkmix_tlv), | ||
2104 | |||
2105 | SOC_SINGLE_TLV("SPKR DAC2 Volume", WM8994_SPKMIXR_ATTENUATION, | ||
2106 | 6, 1, 1, wm_hubs_spkmix_tlv), | ||
2107 | SOC_SINGLE_TLV("SPKR DAC1 Volume", WM8994_SPKMIXR_ATTENUATION, | ||
2108 | 2, 1, 1, wm_hubs_spkmix_tlv), | ||
2109 | |||
2110 | SOC_SINGLE_TLV("AIF1DAC1 3D Stereo Volume", WM8994_AIF1_DAC1_FILTERS_2, | ||
2111 | 10, 15, 0, wm8994_3d_tlv), | ||
2112 | SOC_SINGLE("AIF1DAC1 3D Stereo Switch", WM8994_AIF1_DAC2_FILTERS_2, | ||
2113 | 8, 1, 0), | ||
2114 | SOC_SINGLE_TLV("AIF1DAC2 3D Stereo Volume", WM8994_AIF1_DAC2_FILTERS_2, | ||
2115 | 10, 15, 0, wm8994_3d_tlv), | ||
2116 | SOC_SINGLE("AIF1DAC2 3D Stereo Switch", WM8994_AIF1_DAC2_FILTERS_2, | ||
2117 | 8, 1, 0), | ||
2118 | SOC_SINGLE_TLV("AIF2DAC 3D Stereo Volume", WM8994_AIF1_DAC1_FILTERS_2, | ||
2119 | 10, 15, 0, wm8994_3d_tlv), | ||
2120 | SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF1_DAC2_FILTERS_2, | ||
2121 | 8, 1, 0), | ||
2122 | }; | ||
2123 | |||
2124 | static const struct snd_kcontrol_new wm8994_eq_controls[] = { | ||
2125 | SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0, | ||
2126 | eq_tlv), | ||
2127 | SOC_SINGLE_TLV("AIF1DAC1 EQ2 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 6, 31, 0, | ||
2128 | eq_tlv), | ||
2129 | SOC_SINGLE_TLV("AIF1DAC1 EQ3 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 1, 31, 0, | ||
2130 | eq_tlv), | ||
2131 | SOC_SINGLE_TLV("AIF1DAC1 EQ4 Volume", WM8994_AIF1_DAC1_EQ_GAINS_2, 11, 31, 0, | ||
2132 | eq_tlv), | ||
2133 | SOC_SINGLE_TLV("AIF1DAC1 EQ5 Volume", WM8994_AIF1_DAC1_EQ_GAINS_2, 6, 31, 0, | ||
2134 | eq_tlv), | ||
2135 | |||
2136 | SOC_SINGLE_TLV("AIF1DAC2 EQ1 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 11, 31, 0, | ||
2137 | eq_tlv), | ||
2138 | SOC_SINGLE_TLV("AIF1DAC2 EQ2 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 6, 31, 0, | ||
2139 | eq_tlv), | ||
2140 | SOC_SINGLE_TLV("AIF1DAC2 EQ3 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 1, 31, 0, | ||
2141 | eq_tlv), | ||
2142 | SOC_SINGLE_TLV("AIF1DAC2 EQ4 Volume", WM8994_AIF1_DAC2_EQ_GAINS_2, 11, 31, 0, | ||
2143 | eq_tlv), | ||
2144 | SOC_SINGLE_TLV("AIF1DAC2 EQ5 Volume", WM8994_AIF1_DAC2_EQ_GAINS_2, 6, 31, 0, | ||
2145 | eq_tlv), | ||
2146 | |||
2147 | SOC_SINGLE_TLV("AIF2 EQ1 Volume", WM8994_AIF2_EQ_GAINS_1, 11, 31, 0, | ||
2148 | eq_tlv), | ||
2149 | SOC_SINGLE_TLV("AIF2 EQ2 Volume", WM8994_AIF2_EQ_GAINS_1, 6, 31, 0, | ||
2150 | eq_tlv), | ||
2151 | SOC_SINGLE_TLV("AIF2 EQ3 Volume", WM8994_AIF2_EQ_GAINS_1, 1, 31, 0, | ||
2152 | eq_tlv), | ||
2153 | SOC_SINGLE_TLV("AIF2 EQ4 Volume", WM8994_AIF2_EQ_GAINS_2, 11, 31, 0, | ||
2154 | eq_tlv), | ||
2155 | SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | ||
2156 | eq_tlv), | ||
2157 | }; | ||
2158 | |||
2159 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | ||
2160 | struct snd_kcontrol *kcontrol, int event) | ||
2161 | { | ||
2162 | struct snd_soc_codec *codec = w->codec; | ||
2163 | |||
2164 | switch (event) { | ||
2165 | case SND_SOC_DAPM_PRE_PMU: | ||
2166 | return configure_clock(codec); | ||
2167 | |||
2168 | case SND_SOC_DAPM_POST_PMD: | ||
2169 | configure_clock(codec); | ||
2170 | break; | ||
2171 | } | ||
2172 | |||
2173 | return 0; | ||
2174 | } | ||
2175 | |||
2176 | static void wm8994_update_class_w(struct snd_soc_codec *codec) | ||
2177 | { | ||
2178 | int enable = 1; | ||
2179 | int source = 0; /* GCC flow analysis can't track enable */ | ||
2180 | int reg, reg_r; | ||
2181 | |||
2182 | /* Only support direct DAC->headphone paths */ | ||
2183 | reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_1); | ||
2184 | if (!(reg & WM8994_DAC1L_TO_HPOUT1L)) { | ||
2185 | dev_dbg(codec->dev, "HPL connected to output mixer\n"); | ||
2186 | enable = 0; | ||
2187 | } | ||
2188 | |||
2189 | reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_2); | ||
2190 | if (!(reg & WM8994_DAC1R_TO_HPOUT1R)) { | ||
2191 | dev_dbg(codec->dev, "HPR connected to output mixer\n"); | ||
2192 | enable = 0; | ||
2193 | } | ||
2194 | |||
2195 | /* We also need the same setting for L/R and only one path */ | ||
2196 | reg = snd_soc_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); | ||
2197 | switch (reg) { | ||
2198 | case WM8994_AIF2DACL_TO_DAC1L: | ||
2199 | dev_dbg(codec->dev, "Class W source AIF2DAC\n"); | ||
2200 | source = 2 << WM8994_CP_DYN_SRC_SEL_SHIFT; | ||
2201 | break; | ||
2202 | case WM8994_AIF1DAC2L_TO_DAC1L: | ||
2203 | dev_dbg(codec->dev, "Class W source AIF1DAC2\n"); | ||
2204 | source = 1 << WM8994_CP_DYN_SRC_SEL_SHIFT; | ||
2205 | break; | ||
2206 | case WM8994_AIF1DAC1L_TO_DAC1L: | ||
2207 | dev_dbg(codec->dev, "Class W source AIF1DAC1\n"); | ||
2208 | source = 0 << WM8994_CP_DYN_SRC_SEL_SHIFT; | ||
2209 | break; | ||
2210 | default: | ||
2211 | dev_dbg(codec->dev, "DAC mixer setting: %x\n", reg); | ||
2212 | enable = 0; | ||
2213 | break; | ||
2214 | } | ||
2215 | |||
2216 | reg_r = snd_soc_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); | ||
2217 | if (reg_r != reg) { | ||
2218 | dev_dbg(codec->dev, "Left and right DAC mixers different\n"); | ||
2219 | enable = 0; | ||
2220 | } | ||
2221 | |||
2222 | if (enable) { | ||
2223 | dev_dbg(codec->dev, "Class W enabled\n"); | ||
2224 | snd_soc_update_bits(codec, WM8994_CLASS_W_1, | ||
2225 | WM8994_CP_DYN_PWR | | ||
2226 | WM8994_CP_DYN_SRC_SEL_MASK, | ||
2227 | source | WM8994_CP_DYN_PWR); | ||
2228 | |||
2229 | } else { | ||
2230 | dev_dbg(codec->dev, "Class W disabled\n"); | ||
2231 | snd_soc_update_bits(codec, WM8994_CLASS_W_1, | ||
2232 | WM8994_CP_DYN_PWR, 0); | ||
2233 | } | ||
2234 | } | ||
2235 | |||
2236 | static const char *hp_mux_text[] = { | ||
2237 | "Mixer", | ||
2238 | "DAC", | ||
2239 | }; | ||
2240 | |||
2241 | #define WM8994_HP_ENUM(xname, xenum) \ | ||
2242 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2243 | .info = snd_soc_info_enum_double, \ | ||
2244 | .get = snd_soc_dapm_get_enum_double, \ | ||
2245 | .put = wm8994_put_hp_enum, \ | ||
2246 | .private_value = (unsigned long)&xenum } | ||
2247 | |||
2248 | static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol, | ||
2249 | struct snd_ctl_elem_value *ucontrol) | ||
2250 | { | ||
2251 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | ||
2252 | struct snd_soc_codec *codec = w->codec; | ||
2253 | int ret; | ||
2254 | |||
2255 | ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); | ||
2256 | |||
2257 | wm8994_update_class_w(codec); | ||
2258 | |||
2259 | return ret; | ||
2260 | } | ||
2261 | |||
2262 | static const struct soc_enum hpl_enum = | ||
2263 | SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_1, 8, 2, hp_mux_text); | ||
2264 | |||
2265 | static const struct snd_kcontrol_new hpl_mux = | ||
2266 | WM8994_HP_ENUM("Left Headphone Mux", hpl_enum); | ||
2267 | |||
2268 | static const struct soc_enum hpr_enum = | ||
2269 | SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_2, 8, 2, hp_mux_text); | ||
2270 | |||
2271 | static const struct snd_kcontrol_new hpr_mux = | ||
2272 | WM8994_HP_ENUM("Right Headphone Mux", hpr_enum); | ||
2273 | |||
2274 | static const char *adc_mux_text[] = { | ||
2275 | "ADC", | ||
2276 | "DMIC", | ||
2277 | }; | ||
2278 | |||
2279 | static const struct soc_enum adc_enum = | ||
2280 | SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); | ||
2281 | |||
2282 | static const struct snd_kcontrol_new adcl_mux = | ||
2283 | SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); | ||
2284 | |||
2285 | static const struct snd_kcontrol_new adcr_mux = | ||
2286 | SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum); | ||
2287 | |||
2288 | static const struct snd_kcontrol_new left_speaker_mixer[] = { | ||
2289 | SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 9, 1, 0), | ||
2290 | SOC_DAPM_SINGLE("Input Switch", WM8994_SPEAKER_MIXER, 7, 1, 0), | ||
2291 | SOC_DAPM_SINGLE("IN1LP Switch", WM8994_SPEAKER_MIXER, 5, 1, 0), | ||
2292 | SOC_DAPM_SINGLE("Output Switch", WM8994_SPEAKER_MIXER, 3, 1, 0), | ||
2293 | SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 1, 1, 0), | ||
2294 | }; | ||
2295 | |||
2296 | static const struct snd_kcontrol_new right_speaker_mixer[] = { | ||
2297 | SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 8, 1, 0), | ||
2298 | SOC_DAPM_SINGLE("Input Switch", WM8994_SPEAKER_MIXER, 6, 1, 0), | ||
2299 | SOC_DAPM_SINGLE("IN1RP Switch", WM8994_SPEAKER_MIXER, 4, 1, 0), | ||
2300 | SOC_DAPM_SINGLE("Output Switch", WM8994_SPEAKER_MIXER, 2, 1, 0), | ||
2301 | SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 0, 1, 0), | ||
2302 | }; | ||
2303 | |||
2304 | /* Debugging; dump chip status after DAPM transitions */ | ||
2305 | static int post_ev(struct snd_soc_dapm_widget *w, | ||
2306 | struct snd_kcontrol *kcontrol, int event) | ||
2307 | { | ||
2308 | struct snd_soc_codec *codec = w->codec; | ||
2309 | dev_dbg(codec->dev, "SRC status: %x\n", | ||
2310 | snd_soc_read(codec, | ||
2311 | WM8994_RATE_STATUS)); | ||
2312 | return 0; | ||
2313 | } | ||
2314 | |||
2315 | static const struct snd_kcontrol_new aif1adc1l_mix[] = { | ||
2316 | SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, | ||
2317 | 1, 1, 0), | ||
2318 | SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, | ||
2319 | 0, 1, 0), | ||
2320 | }; | ||
2321 | |||
2322 | static const struct snd_kcontrol_new aif1adc1r_mix[] = { | ||
2323 | SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, | ||
2324 | 1, 1, 0), | ||
2325 | SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, | ||
2326 | 0, 1, 0), | ||
2327 | }; | ||
2328 | |||
2329 | static const struct snd_kcontrol_new aif2dac2l_mix[] = { | ||
2330 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, | ||
2331 | 5, 1, 0), | ||
2332 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, | ||
2333 | 4, 1, 0), | ||
2334 | SOC_DAPM_SINGLE("AIF2 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, | ||
2335 | 2, 1, 0), | ||
2336 | SOC_DAPM_SINGLE("AIF1.2 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, | ||
2337 | 1, 1, 0), | ||
2338 | SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, | ||
2339 | 0, 1, 0), | ||
2340 | }; | ||
2341 | |||
2342 | static const struct snd_kcontrol_new aif2dac2r_mix[] = { | ||
2343 | SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | ||
2344 | 5, 1, 0), | ||
2345 | SOC_DAPM_SINGLE("Left Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | ||
2346 | 4, 1, 0), | ||
2347 | SOC_DAPM_SINGLE("AIF2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | ||
2348 | 2, 1, 0), | ||
2349 | SOC_DAPM_SINGLE("AIF1.2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | ||
2350 | 1, 1, 0), | ||
2351 | SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | ||
2352 | 0, 1, 0), | ||
2353 | }; | ||
2354 | |||
2355 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ | ||
2356 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2357 | .info = snd_soc_info_volsw, \ | ||
2358 | .get = snd_soc_dapm_get_volsw, .put = wm8994_put_class_w, \ | ||
2359 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
2360 | |||
2361 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, | ||
2362 | struct snd_ctl_elem_value *ucontrol) | ||
2363 | { | ||
2364 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | ||
2365 | struct snd_soc_codec *codec = w->codec; | ||
2366 | int ret; | ||
2367 | |||
2368 | ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); | ||
2369 | |||
2370 | wm8994_update_class_w(codec); | ||
2371 | |||
2372 | return ret; | ||
2373 | } | ||
2374 | |||
2375 | static const struct snd_kcontrol_new dac1l_mix[] = { | ||
2376 | WM8994_CLASS_W_SWITCH("Right Sidetone Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, | ||
2377 | 5, 1, 0), | ||
2378 | WM8994_CLASS_W_SWITCH("Left Sidetone Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, | ||
2379 | 4, 1, 0), | ||
2380 | WM8994_CLASS_W_SWITCH("AIF2 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, | ||
2381 | 2, 1, 0), | ||
2382 | WM8994_CLASS_W_SWITCH("AIF1.2 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, | ||
2383 | 1, 1, 0), | ||
2384 | WM8994_CLASS_W_SWITCH("AIF1.1 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, | ||
2385 | 0, 1, 0), | ||
2386 | }; | ||
2387 | |||
2388 | static const struct snd_kcontrol_new dac1r_mix[] = { | ||
2389 | WM8994_CLASS_W_SWITCH("Right Sidetone Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, | ||
2390 | 5, 1, 0), | ||
2391 | WM8994_CLASS_W_SWITCH("Left Sidetone Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, | ||
2392 | 4, 1, 0), | ||
2393 | WM8994_CLASS_W_SWITCH("AIF2 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, | ||
2394 | 2, 1, 0), | ||
2395 | WM8994_CLASS_W_SWITCH("AIF1.2 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, | ||
2396 | 1, 1, 0), | ||
2397 | WM8994_CLASS_W_SWITCH("AIF1.1 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, | ||
2398 | 0, 1, 0), | ||
2399 | }; | ||
2400 | |||
2401 | static const char *sidetone_text[] = { | ||
2402 | "ADC/DMIC1", "DMIC2", | ||
2403 | }; | ||
2404 | |||
2405 | static const struct soc_enum sidetone1_enum = | ||
2406 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text); | ||
2407 | |||
2408 | static const struct snd_kcontrol_new sidetone1_mux = | ||
2409 | SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); | ||
2410 | |||
2411 | static const struct soc_enum sidetone2_enum = | ||
2412 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text); | ||
2413 | |||
2414 | static const struct snd_kcontrol_new sidetone2_mux = | ||
2415 | SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); | ||
2416 | |||
2417 | static const char *aif1dac_text[] = { | ||
2418 | "AIF1DACDAT", "AIF3DACDAT", | ||
2419 | }; | ||
2420 | |||
2421 | static const struct soc_enum aif1dac_enum = | ||
2422 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); | ||
2423 | |||
2424 | static const struct snd_kcontrol_new aif1dac_mux = | ||
2425 | SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum); | ||
2426 | |||
2427 | static const char *aif2dac_text[] = { | ||
2428 | "AIF2DACDAT", "AIF3DACDAT", | ||
2429 | }; | ||
2430 | |||
2431 | static const struct soc_enum aif2dac_enum = | ||
2432 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text); | ||
2433 | |||
2434 | static const struct snd_kcontrol_new aif2dac_mux = | ||
2435 | SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum); | ||
2436 | |||
2437 | static const char *aif2adc_text[] = { | ||
2438 | "AIF2ADCDAT", "AIF3DACDAT", | ||
2439 | }; | ||
2440 | |||
2441 | static const struct soc_enum aif2adc_enum = | ||
2442 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text); | ||
2443 | |||
2444 | static const struct snd_kcontrol_new aif2adc_mux = | ||
2445 | SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum); | ||
2446 | |||
2447 | static const char *aif3adc_text[] = { | ||
2448 | "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", | ||
2449 | }; | ||
2450 | |||
2451 | static const struct soc_enum aif3adc_enum = | ||
2452 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text); | ||
2453 | |||
2454 | static const struct snd_kcontrol_new aif3adc_mux = | ||
2455 | SOC_DAPM_ENUM("AIF3ADC Mux", aif3adc_enum); | ||
2456 | |||
2457 | static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { | ||
2458 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | ||
2459 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | ||
2460 | |||
2461 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | ||
2462 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
2463 | |||
2464 | SND_SOC_DAPM_SUPPLY("DSP1CLK", WM8994_CLOCKING_1, 3, 0, NULL, 0), | ||
2465 | SND_SOC_DAPM_SUPPLY("DSP2CLK", WM8994_CLOCKING_1, 2, 0, NULL, 0), | ||
2466 | SND_SOC_DAPM_SUPPLY("DSPINTCLK", WM8994_CLOCKING_1, 1, 0, NULL, 0), | ||
2467 | |||
2468 | SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), | ||
2469 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), | ||
2470 | |||
2471 | SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", "AIF1 Capture", | ||
2472 | 0, WM8994_POWER_MANAGEMENT_4, 9, 0), | ||
2473 | SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", "AIF1 Capture", | ||
2474 | 0, WM8994_POWER_MANAGEMENT_4, 8, 0), | ||
2475 | SND_SOC_DAPM_AIF_IN("AIF1DAC1L", NULL, 0, | ||
2476 | WM8994_POWER_MANAGEMENT_5, 9, 0), | ||
2477 | SND_SOC_DAPM_AIF_IN("AIF1DAC1R", NULL, 0, | ||
2478 | WM8994_POWER_MANAGEMENT_5, 8, 0), | ||
2479 | |||
2480 | SND_SOC_DAPM_AIF_OUT("AIF1ADC2L", "AIF1 Capture", | ||
2481 | 0, WM8994_POWER_MANAGEMENT_4, 11, 0), | ||
2482 | SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", "AIF1 Capture", | ||
2483 | 0, WM8994_POWER_MANAGEMENT_4, 10, 0), | ||
2484 | SND_SOC_DAPM_AIF_IN("AIF1DAC2L", NULL, 0, | ||
2485 | WM8994_POWER_MANAGEMENT_5, 11, 0), | ||
2486 | SND_SOC_DAPM_AIF_IN("AIF1DAC2R", NULL, 0, | ||
2487 | WM8994_POWER_MANAGEMENT_5, 10, 0), | ||
2488 | |||
2489 | SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, | ||
2490 | aif1adc1l_mix, ARRAY_SIZE(aif1adc1l_mix)), | ||
2491 | SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, | ||
2492 | aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), | ||
2493 | |||
2494 | SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, | ||
2495 | aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), | ||
2496 | SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, | ||
2497 | aif2dac2r_mix, ARRAY_SIZE(aif2dac2r_mix)), | ||
2498 | |||
2499 | SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &sidetone1_mux), | ||
2500 | SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &sidetone2_mux), | ||
2501 | |||
2502 | SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0, | ||
2503 | dac1l_mix, ARRAY_SIZE(dac1l_mix)), | ||
2504 | SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0, | ||
2505 | dac1r_mix, ARRAY_SIZE(dac1r_mix)), | ||
2506 | |||
2507 | SND_SOC_DAPM_AIF_OUT("AIF2ADCL", NULL, 0, | ||
2508 | WM8994_POWER_MANAGEMENT_4, 13, 0), | ||
2509 | SND_SOC_DAPM_AIF_OUT("AIF2ADCR", NULL, 0, | ||
2510 | WM8994_POWER_MANAGEMENT_4, 12, 0), | ||
2511 | SND_SOC_DAPM_AIF_IN("AIF2DACL", NULL, 0, | ||
2512 | WM8994_POWER_MANAGEMENT_5, 13, 0), | ||
2513 | SND_SOC_DAPM_AIF_IN("AIF2DACR", NULL, 0, | ||
2514 | WM8994_POWER_MANAGEMENT_5, 12, 0), | ||
2515 | |||
2516 | SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
2517 | SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
2518 | SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
2519 | |||
2520 | SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux), | ||
2521 | SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux), | ||
2522 | SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux), | ||
2523 | SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &aif3adc_mux), | ||
2524 | |||
2525 | SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
2526 | SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
2527 | |||
2528 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0), | ||
2529 | |||
2530 | SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8994_POWER_MANAGEMENT_4, 5, 0), | ||
2531 | SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8994_POWER_MANAGEMENT_4, 4, 0), | ||
2532 | SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8994_POWER_MANAGEMENT_4, 3, 0), | ||
2533 | SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), | ||
2534 | |||
2535 | /* Power is done with the muxes since the ADC power also controls the | ||
2536 | * downsampling chain, the chip will automatically manage the analogue | ||
2537 | * specific portions. | ||
2538 | */ | ||
2539 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | ||
2540 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | ||
2541 | |||
2542 | SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), | ||
2543 | SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), | ||
2544 | |||
2545 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), | ||
2546 | SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), | ||
2547 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), | ||
2548 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), | ||
2549 | |||
2550 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
2551 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
2552 | |||
2553 | SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
2554 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | ||
2555 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
2556 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | ||
2557 | |||
2558 | SND_SOC_DAPM_POST("Debug log", post_ev), | ||
2559 | }; | ||
2560 | |||
2561 | static const struct snd_soc_dapm_route intercon[] = { | ||
2562 | |||
2563 | { "CLK_SYS", NULL, "AIF1CLK", check_clk_sys }, | ||
2564 | { "CLK_SYS", NULL, "AIF2CLK", check_clk_sys }, | ||
2565 | |||
2566 | { "DSP1CLK", NULL, "CLK_SYS" }, | ||
2567 | { "DSP2CLK", NULL, "CLK_SYS" }, | ||
2568 | { "DSPINTCLK", NULL, "CLK_SYS" }, | ||
2569 | |||
2570 | { "AIF1ADC1L", NULL, "AIF1CLK" }, | ||
2571 | { "AIF1ADC1L", NULL, "DSP1CLK" }, | ||
2572 | { "AIF1ADC1R", NULL, "AIF1CLK" }, | ||
2573 | { "AIF1ADC1R", NULL, "DSP1CLK" }, | ||
2574 | { "AIF1ADC1R", NULL, "DSPINTCLK" }, | ||
2575 | |||
2576 | { "AIF1DAC1L", NULL, "AIF1CLK" }, | ||
2577 | { "AIF1DAC1L", NULL, "DSP1CLK" }, | ||
2578 | { "AIF1DAC1R", NULL, "AIF1CLK" }, | ||
2579 | { "AIF1DAC1R", NULL, "DSP1CLK" }, | ||
2580 | { "AIF1DAC1R", NULL, "DSPINTCLK" }, | ||
2581 | |||
2582 | { "AIF1ADC2L", NULL, "AIF1CLK" }, | ||
2583 | { "AIF1ADC2L", NULL, "DSP1CLK" }, | ||
2584 | { "AIF1ADC2R", NULL, "AIF1CLK" }, | ||
2585 | { "AIF1ADC2R", NULL, "DSP1CLK" }, | ||
2586 | { "AIF1ADC2R", NULL, "DSPINTCLK" }, | ||
2587 | |||
2588 | { "AIF1DAC2L", NULL, "AIF1CLK" }, | ||
2589 | { "AIF1DAC2L", NULL, "DSP1CLK" }, | ||
2590 | { "AIF1DAC2R", NULL, "AIF1CLK" }, | ||
2591 | { "AIF1DAC2R", NULL, "DSP1CLK" }, | ||
2592 | { "AIF1DAC2R", NULL, "DSPINTCLK" }, | ||
2593 | |||
2594 | { "AIF2ADCL", NULL, "AIF2CLK" }, | ||
2595 | { "AIF2ADCL", NULL, "DSP2CLK" }, | ||
2596 | { "AIF2ADCR", NULL, "AIF2CLK" }, | ||
2597 | { "AIF2ADCR", NULL, "DSP2CLK" }, | ||
2598 | { "AIF2ADCR", NULL, "DSPINTCLK" }, | ||
2599 | |||
2600 | { "AIF2DACL", NULL, "AIF2CLK" }, | ||
2601 | { "AIF2DACL", NULL, "DSP2CLK" }, | ||
2602 | { "AIF2DACR", NULL, "AIF2CLK" }, | ||
2603 | { "AIF2DACR", NULL, "DSP2CLK" }, | ||
2604 | { "AIF2DACR", NULL, "DSPINTCLK" }, | ||
2605 | |||
2606 | { "DMIC1L", NULL, "DMIC1DAT" }, | ||
2607 | { "DMIC1L", NULL, "CLK_SYS" }, | ||
2608 | { "DMIC1R", NULL, "DMIC1DAT" }, | ||
2609 | { "DMIC1R", NULL, "CLK_SYS" }, | ||
2610 | { "DMIC2L", NULL, "DMIC2DAT" }, | ||
2611 | { "DMIC2L", NULL, "CLK_SYS" }, | ||
2612 | { "DMIC2R", NULL, "DMIC2DAT" }, | ||
2613 | { "DMIC2R", NULL, "CLK_SYS" }, | ||
2614 | |||
2615 | { "ADCL", NULL, "AIF1CLK" }, | ||
2616 | { "ADCL", NULL, "DSP1CLK" }, | ||
2617 | { "ADCL", NULL, "DSPINTCLK" }, | ||
2618 | |||
2619 | { "ADCR", NULL, "AIF1CLK" }, | ||
2620 | { "ADCR", NULL, "DSP1CLK" }, | ||
2621 | { "ADCR", NULL, "DSPINTCLK" }, | ||
2622 | |||
2623 | { "ADCL Mux", "ADC", "ADCL" }, | ||
2624 | { "ADCL Mux", "DMIC", "DMIC1L" }, | ||
2625 | { "ADCR Mux", "ADC", "ADCR" }, | ||
2626 | { "ADCR Mux", "DMIC", "DMIC1R" }, | ||
2627 | |||
2628 | { "DAC1L", NULL, "AIF1CLK" }, | ||
2629 | { "DAC1L", NULL, "DSP1CLK" }, | ||
2630 | { "DAC1L", NULL, "DSPINTCLK" }, | ||
2631 | |||
2632 | { "DAC1R", NULL, "AIF1CLK" }, | ||
2633 | { "DAC1R", NULL, "DSP1CLK" }, | ||
2634 | { "DAC1R", NULL, "DSPINTCLK" }, | ||
2635 | |||
2636 | { "DAC2L", NULL, "AIF2CLK" }, | ||
2637 | { "DAC2L", NULL, "DSP2CLK" }, | ||
2638 | { "DAC2L", NULL, "DSPINTCLK" }, | ||
2639 | |||
2640 | { "DAC2R", NULL, "AIF2DACR" }, | ||
2641 | { "DAC2R", NULL, "AIF2CLK" }, | ||
2642 | { "DAC2R", NULL, "DSP2CLK" }, | ||
2643 | { "DAC2R", NULL, "DSPINTCLK" }, | ||
2644 | |||
2645 | { "TOCLK", NULL, "CLK_SYS" }, | ||
2646 | |||
2647 | /* AIF1 outputs */ | ||
2648 | { "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" }, | ||
2649 | { "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" }, | ||
2650 | { "AIF1ADC1L Mixer", "AIF2 Switch", "AIF2DACL" }, | ||
2651 | |||
2652 | { "AIF1ADC1R", NULL, "AIF1ADC1R Mixer" }, | ||
2653 | { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, | ||
2654 | { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" }, | ||
2655 | |||
2656 | /* Pin level routing for AIF3 */ | ||
2657 | { "AIF1DAC1L", NULL, "AIF1DAC Mux" }, | ||
2658 | { "AIF1DAC1R", NULL, "AIF1DAC Mux" }, | ||
2659 | { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, | ||
2660 | { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, | ||
2661 | |||
2662 | { "AIF2DACL", NULL, "AIF2DAC Mux" }, | ||
2663 | { "AIF2DACR", NULL, "AIF2DAC Mux" }, | ||
2664 | |||
2665 | { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, | ||
2666 | { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | ||
2667 | { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, | ||
2668 | { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, | ||
2669 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, | ||
2670 | { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, | ||
2671 | { "AIF2ADC Mux", "AIF3DACDAT", "AIF3ADCDAT" }, | ||
2672 | |||
2673 | /* DAC1 inputs */ | ||
2674 | { "DAC1L", NULL, "DAC1L Mixer" }, | ||
2675 | { "DAC1L Mixer", "AIF2 Switch", "AIF2DACL" }, | ||
2676 | { "DAC1L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, | ||
2677 | { "DAC1L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, | ||
2678 | { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
2679 | { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
2680 | |||
2681 | { "DAC1R", NULL, "DAC1R Mixer" }, | ||
2682 | { "DAC1R Mixer", "AIF2 Switch", "AIF2DACR" }, | ||
2683 | { "DAC1R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, | ||
2684 | { "DAC1R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, | ||
2685 | { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
2686 | { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
2687 | |||
2688 | /* DAC2/AIF2 outputs */ | ||
2689 | { "AIF2ADCL", NULL, "AIF2DAC2L Mixer" }, | ||
2690 | { "DAC2L", NULL, "AIF2DAC2L Mixer" }, | ||
2691 | { "AIF2DAC2L Mixer", "AIF2 Switch", "AIF2DACL" }, | ||
2692 | { "AIF2DAC2L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, | ||
2693 | { "AIF2DAC2L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, | ||
2694 | { "AIF2DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
2695 | { "AIF2DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
2696 | |||
2697 | { "AIF2ADCR", NULL, "AIF2DAC2R Mixer" }, | ||
2698 | { "DAC2R", NULL, "AIF2DAC2R Mixer" }, | ||
2699 | { "AIF2DAC2R Mixer", "AIF2 Switch", "AIF2DACR" }, | ||
2700 | { "AIF2DAC2R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, | ||
2701 | { "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, | ||
2702 | { "AIF2DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" }, | ||
2703 | { "AIF2DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" }, | ||
2704 | |||
2705 | { "AIF2ADCDAT", NULL, "AIF2ADC Mux" }, | ||
2706 | |||
2707 | /* AIF3 output */ | ||
2708 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1L" }, | ||
2709 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1R" }, | ||
2710 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2L" }, | ||
2711 | { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2R" }, | ||
2712 | { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCL" }, | ||
2713 | { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCR" }, | ||
2714 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, | ||
2715 | { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, | ||
2716 | |||
2717 | /* Sidetone */ | ||
2718 | { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, | ||
2719 | { "Left Sidetone", "DMIC2", "DMIC2L" }, | ||
2720 | { "Right Sidetone", "ADC/DMIC1", "ADCR Mux" }, | ||
2721 | { "Right Sidetone", "DMIC2", "DMIC2R" }, | ||
2722 | |||
2723 | /* Output stages */ | ||
2724 | { "Left Output Mixer", "DAC Switch", "DAC1L" }, | ||
2725 | { "Right Output Mixer", "DAC Switch", "DAC1R" }, | ||
2726 | |||
2727 | { "SPKL", "DAC1 Switch", "DAC1L" }, | ||
2728 | { "SPKL", "DAC2 Switch", "DAC2L" }, | ||
2729 | |||
2730 | { "SPKR", "DAC1 Switch", "DAC1R" }, | ||
2731 | { "SPKR", "DAC2 Switch", "DAC2R" }, | ||
2732 | |||
2733 | { "Left Headphone Mux", "DAC", "DAC1L" }, | ||
2734 | { "Right Headphone Mux", "DAC", "DAC1R" }, | ||
2735 | }; | ||
2736 | |||
2737 | /* The size in bits of the FLL divide multiplied by 10 | ||
2738 | * to allow rounding later */ | ||
2739 | #define FIXED_FLL_SIZE ((1 << 16) * 10) | ||
2740 | |||
2741 | struct fll_div { | ||
2742 | u16 outdiv; | ||
2743 | u16 n; | ||
2744 | u16 k; | ||
2745 | u16 clk_ref_div; | ||
2746 | u16 fll_fratio; | ||
2747 | }; | ||
2748 | |||
2749 | static int wm8994_get_fll_config(struct fll_div *fll, | ||
2750 | int freq_in, int freq_out) | ||
2751 | { | ||
2752 | u64 Kpart; | ||
2753 | unsigned int K, Ndiv, Nmod; | ||
2754 | |||
2755 | pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); | ||
2756 | |||
2757 | /* Scale the input frequency down to <= 13.5MHz */ | ||
2758 | fll->clk_ref_div = 0; | ||
2759 | while (freq_in > 13500000) { | ||
2760 | fll->clk_ref_div++; | ||
2761 | freq_in /= 2; | ||
2762 | |||
2763 | if (fll->clk_ref_div > 3) | ||
2764 | return -EINVAL; | ||
2765 | } | ||
2766 | pr_debug("CLK_REF_DIV=%d, Fref=%dHz\n", fll->clk_ref_div, freq_in); | ||
2767 | |||
2768 | /* Scale the output to give 90MHz<=Fvco<=100MHz */ | ||
2769 | fll->outdiv = 3; | ||
2770 | while (freq_out * (fll->outdiv + 1) < 90000000) { | ||
2771 | fll->outdiv++; | ||
2772 | if (fll->outdiv > 63) | ||
2773 | return -EINVAL; | ||
2774 | } | ||
2775 | freq_out *= fll->outdiv + 1; | ||
2776 | pr_debug("OUTDIV=%d, Fvco=%dHz\n", fll->outdiv, freq_out); | ||
2777 | |||
2778 | if (freq_in > 1000000) { | ||
2779 | fll->fll_fratio = 0; | ||
2780 | } else { | ||
2781 | fll->fll_fratio = 3; | ||
2782 | freq_in *= 8; | ||
2783 | } | ||
2784 | pr_debug("FLL_FRATIO=%d, Fref=%dHz\n", fll->fll_fratio, freq_in); | ||
2785 | |||
2786 | /* Now, calculate N.K */ | ||
2787 | Ndiv = freq_out / freq_in; | ||
2788 | |||
2789 | fll->n = Ndiv; | ||
2790 | Nmod = freq_out % freq_in; | ||
2791 | pr_debug("Nmod=%d\n", Nmod); | ||
2792 | |||
2793 | /* Calculate fractional part - scale up so we can round. */ | ||
2794 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
2795 | |||
2796 | do_div(Kpart, freq_in); | ||
2797 | |||
2798 | K = Kpart & 0xFFFFFFFF; | ||
2799 | |||
2800 | if ((K % 10) >= 5) | ||
2801 | K += 5; | ||
2802 | |||
2803 | /* Move down to proper range now rounding is done */ | ||
2804 | fll->k = K / 10; | ||
2805 | |||
2806 | pr_debug("N=%x K=%x\n", fll->n, fll->k); | ||
2807 | |||
2808 | return 0; | ||
2809 | } | ||
2810 | |||
2811 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | ||
2812 | unsigned int freq_in, unsigned int freq_out) | ||
2813 | { | ||
2814 | struct snd_soc_codec *codec = dai->codec; | ||
2815 | struct wm8994_priv *wm8994 = codec->private_data; | ||
2816 | int reg_offset, ret; | ||
2817 | struct fll_div fll; | ||
2818 | u16 reg, aif1, aif2; | ||
2819 | |||
2820 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | ||
2821 | & WM8994_AIF1CLK_ENA; | ||
2822 | |||
2823 | aif2 = snd_soc_read(codec, WM8994_AIF2_CLOCKING_1) | ||
2824 | & WM8994_AIF2CLK_ENA; | ||
2825 | |||
2826 | switch (id) { | ||
2827 | case WM8994_FLL1: | ||
2828 | reg_offset = 0; | ||
2829 | id = 0; | ||
2830 | break; | ||
2831 | case WM8994_FLL2: | ||
2832 | reg_offset = 0x20; | ||
2833 | id = 1; | ||
2834 | break; | ||
2835 | default: | ||
2836 | return -EINVAL; | ||
2837 | } | ||
2838 | |||
2839 | /* Are we changing anything? */ | ||
2840 | if (wm8994->fll[id].src == src && | ||
2841 | wm8994->fll[id].in == freq_in && wm8994->fll[id].out == freq_out) | ||
2842 | return 0; | ||
2843 | |||
2844 | /* If we're stopping the FLL redo the old config - no | ||
2845 | * registers will actually be written but we avoid GCC flow | ||
2846 | * analysis bugs spewing warnings. | ||
2847 | */ | ||
2848 | if (freq_out) | ||
2849 | ret = wm8994_get_fll_config(&fll, freq_in, freq_out); | ||
2850 | else | ||
2851 | ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, | ||
2852 | wm8994->fll[id].out); | ||
2853 | if (ret < 0) | ||
2854 | return ret; | ||
2855 | |||
2856 | /* Gate the AIF clocks while we reclock */ | ||
2857 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, | ||
2858 | WM8994_AIF1CLK_ENA, 0); | ||
2859 | snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, | ||
2860 | WM8994_AIF2CLK_ENA, 0); | ||
2861 | |||
2862 | /* We always need to disable the FLL while reconfiguring */ | ||
2863 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | ||
2864 | WM8994_FLL1_ENA, 0); | ||
2865 | |||
2866 | reg = (fll.outdiv << WM8994_FLL1_OUTDIV_SHIFT) | | ||
2867 | (fll.fll_fratio << WM8994_FLL1_FRATIO_SHIFT); | ||
2868 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_2 + reg_offset, | ||
2869 | WM8994_FLL1_OUTDIV_MASK | | ||
2870 | WM8994_FLL1_FRATIO_MASK, reg); | ||
2871 | |||
2872 | snd_soc_write(codec, WM8994_FLL1_CONTROL_3 + reg_offset, fll.k); | ||
2873 | |||
2874 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, | ||
2875 | WM8994_FLL1_N_MASK, | ||
2876 | fll.n << WM8994_FLL1_N_SHIFT); | ||
2877 | |||
2878 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | ||
2879 | WM8994_FLL1_REFCLK_DIV_MASK, | ||
2880 | fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT); | ||
2881 | |||
2882 | /* Enable (with fractional mode if required) */ | ||
2883 | if (freq_out) { | ||
2884 | if (fll.k) | ||
2885 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | ||
2886 | else | ||
2887 | reg = WM8994_FLL1_ENA; | ||
2888 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | ||
2889 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | ||
2890 | reg); | ||
2891 | } | ||
2892 | |||
2893 | wm8994->fll[id].in = freq_in; | ||
2894 | wm8994->fll[id].out = freq_out; | ||
2895 | |||
2896 | /* Enable any gated AIF clocks */ | ||
2897 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, | ||
2898 | WM8994_AIF1CLK_ENA, aif1); | ||
2899 | snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, | ||
2900 | WM8994_AIF2CLK_ENA, aif2); | ||
2901 | |||
2902 | configure_clock(codec); | ||
2903 | |||
2904 | return 0; | ||
2905 | } | ||
2906 | |||
2907 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | ||
2908 | int clk_id, unsigned int freq, int dir) | ||
2909 | { | ||
2910 | struct snd_soc_codec *codec = dai->codec; | ||
2911 | struct wm8994_priv *wm8994 = codec->private_data; | ||
2912 | |||
2913 | switch (dai->id) { | ||
2914 | case 1: | ||
2915 | case 2: | ||
2916 | break; | ||
2917 | |||
2918 | default: | ||
2919 | /* AIF3 shares clocking with AIF1/2 */ | ||
2920 | return -EINVAL; | ||
2921 | } | ||
2922 | |||
2923 | switch (clk_id) { | ||
2924 | case WM8994_SYSCLK_MCLK1: | ||
2925 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1; | ||
2926 | wm8994->mclk[0] = freq; | ||
2927 | dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n", | ||
2928 | dai->id, freq); | ||
2929 | break; | ||
2930 | |||
2931 | case WM8994_SYSCLK_MCLK2: | ||
2932 | /* TODO: Set GPIO AF */ | ||
2933 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2; | ||
2934 | wm8994->mclk[1] = freq; | ||
2935 | dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", | ||
2936 | dai->id, freq); | ||
2937 | break; | ||
2938 | |||
2939 | case WM8994_SYSCLK_FLL1: | ||
2940 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL1; | ||
2941 | dev_dbg(dai->dev, "AIF%d using FLL1\n", dai->id); | ||
2942 | break; | ||
2943 | |||
2944 | case WM8994_SYSCLK_FLL2: | ||
2945 | wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL2; | ||
2946 | dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id); | ||
2947 | break; | ||
2948 | |||
2949 | default: | ||
2950 | return -EINVAL; | ||
2951 | } | ||
2952 | |||
2953 | configure_clock(codec); | ||
2954 | |||
2955 | return 0; | ||
2956 | } | ||
2957 | |||
2958 | static int wm8994_set_bias_level(struct snd_soc_codec *codec, | ||
2959 | enum snd_soc_bias_level level) | ||
2960 | { | ||
2961 | switch (level) { | ||
2962 | case SND_SOC_BIAS_ON: | ||
2963 | break; | ||
2964 | |||
2965 | case SND_SOC_BIAS_PREPARE: | ||
2966 | /* VMID=2x40k */ | ||
2967 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
2968 | WM8994_VMID_SEL_MASK, 0x2); | ||
2969 | break; | ||
2970 | |||
2971 | case SND_SOC_BIAS_STANDBY: | ||
2972 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
2973 | /* Tweak DC servo configuration for improved | ||
2974 | * performance. */ | ||
2975 | snd_soc_write(codec, 0x102, 0x3); | ||
2976 | snd_soc_write(codec, 0x56, 0x3); | ||
2977 | snd_soc_write(codec, 0x102, 0); | ||
2978 | |||
2979 | /* Discharge LINEOUT1 & 2 */ | ||
2980 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
2981 | WM8994_LINEOUT1_DISCH | | ||
2982 | WM8994_LINEOUT2_DISCH, | ||
2983 | WM8994_LINEOUT1_DISCH | | ||
2984 | WM8994_LINEOUT2_DISCH); | ||
2985 | |||
2986 | /* Startup bias, VMID ramp & buffer */ | ||
2987 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
2988 | WM8994_STARTUP_BIAS_ENA | | ||
2989 | WM8994_VMID_BUF_ENA | | ||
2990 | WM8994_VMID_RAMP_MASK, | ||
2991 | WM8994_STARTUP_BIAS_ENA | | ||
2992 | WM8994_VMID_BUF_ENA | | ||
2993 | (0x11 << WM8994_VMID_RAMP_SHIFT)); | ||
2994 | |||
2995 | /* Main bias enable, VMID=2x40k */ | ||
2996 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
2997 | WM8994_BIAS_ENA | | ||
2998 | WM8994_VMID_SEL_MASK, | ||
2999 | WM8994_BIAS_ENA | 0x2); | ||
3000 | |||
3001 | msleep(20); | ||
3002 | } | ||
3003 | |||
3004 | /* VMID=2x500k */ | ||
3005 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
3006 | WM8994_VMID_SEL_MASK, 0x4); | ||
3007 | |||
3008 | break; | ||
3009 | |||
3010 | case SND_SOC_BIAS_OFF: | ||
3011 | if (codec->bias_level == SND_SOC_BIAS_STANDBY) { | ||
3012 | /* Switch over to startup biases */ | ||
3013 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
3014 | WM8994_BIAS_SRC | | ||
3015 | WM8994_STARTUP_BIAS_ENA | | ||
3016 | WM8994_VMID_BUF_ENA | | ||
3017 | WM8994_VMID_RAMP_MASK, | ||
3018 | WM8994_BIAS_SRC | | ||
3019 | WM8994_STARTUP_BIAS_ENA | | ||
3020 | WM8994_VMID_BUF_ENA | | ||
3021 | (1 << WM8994_VMID_RAMP_SHIFT)); | ||
3022 | |||
3023 | /* Disable main biases */ | ||
3024 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
3025 | WM8994_BIAS_ENA | | ||
3026 | WM8994_VMID_SEL_MASK, 0); | ||
3027 | |||
3028 | /* Discharge line */ | ||
3029 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
3030 | WM8994_LINEOUT1_DISCH | | ||
3031 | WM8994_LINEOUT2_DISCH, | ||
3032 | WM8994_LINEOUT1_DISCH | | ||
3033 | WM8994_LINEOUT2_DISCH); | ||
3034 | |||
3035 | msleep(5); | ||
3036 | |||
3037 | /* Switch off startup biases */ | ||
3038 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
3039 | WM8994_BIAS_SRC | | ||
3040 | WM8994_STARTUP_BIAS_ENA | | ||
3041 | WM8994_VMID_BUF_ENA | | ||
3042 | WM8994_VMID_RAMP_MASK, 0); | ||
3043 | } | ||
3044 | break; | ||
3045 | } | ||
3046 | codec->bias_level = level; | ||
3047 | return 0; | ||
3048 | } | ||
3049 | |||
3050 | static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
3051 | { | ||
3052 | struct snd_soc_codec *codec = dai->codec; | ||
3053 | int ms_reg; | ||
3054 | int aif1_reg; | ||
3055 | int ms = 0; | ||
3056 | int aif1 = 0; | ||
3057 | |||
3058 | switch (dai->id) { | ||
3059 | case 1: | ||
3060 | ms_reg = WM8994_AIF1_MASTER_SLAVE; | ||
3061 | aif1_reg = WM8994_AIF1_CONTROL_1; | ||
3062 | break; | ||
3063 | case 2: | ||
3064 | ms_reg = WM8994_AIF2_MASTER_SLAVE; | ||
3065 | aif1_reg = WM8994_AIF2_CONTROL_1; | ||
3066 | break; | ||
3067 | default: | ||
3068 | return -EINVAL; | ||
3069 | } | ||
3070 | |||
3071 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
3072 | case SND_SOC_DAIFMT_CBS_CFS: | ||
3073 | break; | ||
3074 | case SND_SOC_DAIFMT_CBM_CFM: | ||
3075 | ms = WM8994_AIF1_MSTR; | ||
3076 | break; | ||
3077 | default: | ||
3078 | return -EINVAL; | ||
3079 | } | ||
3080 | |||
3081 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
3082 | case SND_SOC_DAIFMT_DSP_B: | ||
3083 | aif1 |= WM8994_AIF1_LRCLK_INV; | ||
3084 | case SND_SOC_DAIFMT_DSP_A: | ||
3085 | aif1 |= 0x18; | ||
3086 | break; | ||
3087 | case SND_SOC_DAIFMT_I2S: | ||
3088 | aif1 |= 0x10; | ||
3089 | break; | ||
3090 | case SND_SOC_DAIFMT_RIGHT_J: | ||
3091 | break; | ||
3092 | case SND_SOC_DAIFMT_LEFT_J: | ||
3093 | aif1 |= 0x8; | ||
3094 | break; | ||
3095 | default: | ||
3096 | return -EINVAL; | ||
3097 | } | ||
3098 | |||
3099 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
3100 | case SND_SOC_DAIFMT_DSP_A: | ||
3101 | case SND_SOC_DAIFMT_DSP_B: | ||
3102 | /* frame inversion not valid for DSP modes */ | ||
3103 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
3104 | case SND_SOC_DAIFMT_NB_NF: | ||
3105 | break; | ||
3106 | case SND_SOC_DAIFMT_IB_NF: | ||
3107 | aif1 |= WM8994_AIF1_BCLK_INV; | ||
3108 | break; | ||
3109 | default: | ||
3110 | return -EINVAL; | ||
3111 | } | ||
3112 | break; | ||
3113 | |||
3114 | case SND_SOC_DAIFMT_I2S: | ||
3115 | case SND_SOC_DAIFMT_RIGHT_J: | ||
3116 | case SND_SOC_DAIFMT_LEFT_J: | ||
3117 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
3118 | case SND_SOC_DAIFMT_NB_NF: | ||
3119 | break; | ||
3120 | case SND_SOC_DAIFMT_IB_IF: | ||
3121 | aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; | ||
3122 | break; | ||
3123 | case SND_SOC_DAIFMT_IB_NF: | ||
3124 | aif1 |= WM8994_AIF1_BCLK_INV; | ||
3125 | break; | ||
3126 | case SND_SOC_DAIFMT_NB_IF: | ||
3127 | aif1 |= WM8994_AIF1_LRCLK_INV; | ||
3128 | break; | ||
3129 | default: | ||
3130 | return -EINVAL; | ||
3131 | } | ||
3132 | break; | ||
3133 | default: | ||
3134 | return -EINVAL; | ||
3135 | } | ||
3136 | |||
3137 | snd_soc_update_bits(codec, aif1_reg, | ||
3138 | WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | | ||
3139 | WM8994_AIF1_FMT_MASK, | ||
3140 | aif1); | ||
3141 | snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, | ||
3142 | ms); | ||
3143 | |||
3144 | return 0; | ||
3145 | } | ||
3146 | |||
3147 | static struct { | ||
3148 | int val, rate; | ||
3149 | } srs[] = { | ||
3150 | { 0, 8000 }, | ||
3151 | { 1, 11025 }, | ||
3152 | { 2, 12000 }, | ||
3153 | { 3, 16000 }, | ||
3154 | { 4, 22050 }, | ||
3155 | { 5, 24000 }, | ||
3156 | { 6, 32000 }, | ||
3157 | { 7, 44100 }, | ||
3158 | { 8, 48000 }, | ||
3159 | { 9, 88200 }, | ||
3160 | { 10, 96000 }, | ||
3161 | }; | ||
3162 | |||
3163 | static int fs_ratios[] = { | ||
3164 | 64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536 | ||
3165 | }; | ||
3166 | |||
3167 | static int bclk_divs[] = { | ||
3168 | 10, 15, 20, 30, 40, 50, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480, | ||
3169 | 640, 880, 960, 1280, 1760, 1920 | ||
3170 | }; | ||
3171 | |||
3172 | static int wm8994_hw_params(struct snd_pcm_substream *substream, | ||
3173 | struct snd_pcm_hw_params *params, | ||
3174 | struct snd_soc_dai *dai) | ||
3175 | { | ||
3176 | struct snd_soc_codec *codec = dai->codec; | ||
3177 | struct wm8994_priv *wm8994 = codec->private_data; | ||
3178 | int aif1_reg; | ||
3179 | int bclk_reg; | ||
3180 | int lrclk_reg; | ||
3181 | int rate_reg; | ||
3182 | int aif1 = 0; | ||
3183 | int bclk = 0; | ||
3184 | int lrclk = 0; | ||
3185 | int rate_val = 0; | ||
3186 | int id = dai->id - 1; | ||
3187 | |||
3188 | int i, cur_val, best_val, bclk_rate, best; | ||
3189 | |||
3190 | switch (dai->id) { | ||
3191 | case 1: | ||
3192 | aif1_reg = WM8994_AIF1_CONTROL_1; | ||
3193 | bclk_reg = WM8994_AIF1_BCLK; | ||
3194 | rate_reg = WM8994_AIF1_RATE; | ||
3195 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || | ||
3196 | wm8994->lrclk_shared[0]) | ||
3197 | lrclk_reg = WM8994_AIF1DAC_LRCLK; | ||
3198 | else | ||
3199 | lrclk_reg = WM8994_AIF1ADC_LRCLK; | ||
3200 | break; | ||
3201 | case 2: | ||
3202 | aif1_reg = WM8994_AIF2_CONTROL_1; | ||
3203 | bclk_reg = WM8994_AIF2_BCLK; | ||
3204 | rate_reg = WM8994_AIF2_RATE; | ||
3205 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || | ||
3206 | wm8994->lrclk_shared[1]) | ||
3207 | lrclk_reg = WM8994_AIF2DAC_LRCLK; | ||
3208 | else | ||
3209 | lrclk_reg = WM8994_AIF2ADC_LRCLK; | ||
3210 | break; | ||
3211 | default: | ||
3212 | return -EINVAL; | ||
3213 | } | ||
3214 | |||
3215 | bclk_rate = params_rate(params) * 2; | ||
3216 | switch (params_format(params)) { | ||
3217 | case SNDRV_PCM_FORMAT_S16_LE: | ||
3218 | bclk_rate *= 16; | ||
3219 | break; | ||
3220 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
3221 | bclk_rate *= 20; | ||
3222 | aif1 |= 0x20; | ||
3223 | break; | ||
3224 | case SNDRV_PCM_FORMAT_S24_LE: | ||
3225 | bclk_rate *= 24; | ||
3226 | aif1 |= 0x40; | ||
3227 | break; | ||
3228 | case SNDRV_PCM_FORMAT_S32_LE: | ||
3229 | bclk_rate *= 32; | ||
3230 | aif1 |= 0x60; | ||
3231 | break; | ||
3232 | default: | ||
3233 | return -EINVAL; | ||
3234 | } | ||
3235 | |||
3236 | /* Try to find an appropriate sample rate; look for an exact match. */ | ||
3237 | for (i = 0; i < ARRAY_SIZE(srs); i++) | ||
3238 | if (srs[i].rate == params_rate(params)) | ||
3239 | break; | ||
3240 | if (i == ARRAY_SIZE(srs)) | ||
3241 | return -EINVAL; | ||
3242 | rate_val |= srs[i].val << WM8994_AIF1_SR_SHIFT; | ||
3243 | |||
3244 | dev_dbg(dai->dev, "Sample rate is %dHz\n", srs[i].rate); | ||
3245 | dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", | ||
3246 | dai->id, wm8994->aifclk[id], bclk_rate); | ||
3247 | |||
3248 | if (wm8994->aifclk[id] == 0) { | ||
3249 | dev_err(dai->dev, "AIF%dCLK not configured\n", dai->id); | ||
3250 | return -EINVAL; | ||
3251 | } | ||
3252 | |||
3253 | /* AIFCLK/fs ratio; look for a close match in either direction */ | ||
3254 | best = 0; | ||
3255 | best_val = abs((fs_ratios[0] * params_rate(params)) | ||
3256 | - wm8994->aifclk[id]); | ||
3257 | for (i = 1; i < ARRAY_SIZE(fs_ratios); i++) { | ||
3258 | cur_val = abs((fs_ratios[i] * params_rate(params)) | ||
3259 | - wm8994->aifclk[id]); | ||
3260 | if (cur_val >= best_val) | ||
3261 | continue; | ||
3262 | best = i; | ||
3263 | best_val = cur_val; | ||
3264 | } | ||
3265 | dev_dbg(dai->dev, "Selected AIF%dCLK/fs = %d\n", | ||
3266 | dai->id, fs_ratios[best]); | ||
3267 | rate_val |= best; | ||
3268 | |||
3269 | /* We may not get quite the right frequency if using | ||
3270 | * approximate clocks so look for the closest match that is | ||
3271 | * higher than the target (we need to ensure that there enough | ||
3272 | * BCLKs to clock out the samples). | ||
3273 | */ | ||
3274 | best = 0; | ||
3275 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
3276 | cur_val = (wm8994->aifclk[id] * 10 / bclk_divs[i]) - bclk_rate; | ||
3277 | if (cur_val < 0) /* BCLK table is sorted */ | ||
3278 | break; | ||
3279 | best = i; | ||
3280 | } | ||
3281 | bclk_rate = wm8994->aifclk[id] * 10 / bclk_divs[best]; | ||
3282 | dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
3283 | bclk_divs[best], bclk_rate); | ||
3284 | bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; | ||
3285 | |||
3286 | lrclk = bclk_rate / params_rate(params); | ||
3287 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", | ||
3288 | lrclk, bclk_rate / lrclk); | ||
3289 | |||
3290 | snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); | ||
3291 | snd_soc_update_bits(codec, bclk_reg, WM8994_AIF1_BCLK_DIV_MASK, bclk); | ||
3292 | snd_soc_update_bits(codec, lrclk_reg, WM8994_AIF1DAC_RATE_MASK, | ||
3293 | lrclk); | ||
3294 | snd_soc_update_bits(codec, rate_reg, WM8994_AIF1_SR_MASK | | ||
3295 | WM8994_AIF1CLK_RATE_MASK, rate_val); | ||
3296 | |||
3297 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
3298 | switch (dai->id) { | ||
3299 | case 1: | ||
3300 | wm8994->dac_rates[0] = params_rate(params); | ||
3301 | wm8994_set_retune_mobile(codec, 0); | ||
3302 | wm8994_set_retune_mobile(codec, 1); | ||
3303 | break; | ||
3304 | case 2: | ||
3305 | wm8994->dac_rates[1] = params_rate(params); | ||
3306 | wm8994_set_retune_mobile(codec, 2); | ||
3307 | break; | ||
3308 | } | ||
3309 | } | ||
3310 | |||
3311 | return 0; | ||
3312 | } | ||
3313 | |||
3314 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) | ||
3315 | { | ||
3316 | struct snd_soc_codec *codec = codec_dai->codec; | ||
3317 | int mute_reg; | ||
3318 | int reg; | ||
3319 | |||
3320 | switch (codec_dai->id) { | ||
3321 | case 1: | ||
3322 | mute_reg = WM8994_AIF1_DAC1_FILTERS_1; | ||
3323 | break; | ||
3324 | case 2: | ||
3325 | mute_reg = WM8994_AIF2_DAC_FILTERS_1; | ||
3326 | break; | ||
3327 | default: | ||
3328 | return -EINVAL; | ||
3329 | } | ||
3330 | |||
3331 | if (mute) | ||
3332 | reg = WM8994_AIF1DAC1_MUTE; | ||
3333 | else | ||
3334 | reg = 0; | ||
3335 | |||
3336 | snd_soc_update_bits(codec, mute_reg, WM8994_AIF1DAC1_MUTE, reg); | ||
3337 | |||
3338 | return 0; | ||
3339 | } | ||
3340 | |||
3341 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 | ||
3342 | |||
3343 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
3344 | SNDRV_PCM_FMTBIT_S24_LE) | ||
3345 | |||
3346 | static struct snd_soc_dai_ops wm8994_aif1_dai_ops = { | ||
3347 | .set_sysclk = wm8994_set_dai_sysclk, | ||
3348 | .set_fmt = wm8994_set_dai_fmt, | ||
3349 | .hw_params = wm8994_hw_params, | ||
3350 | .digital_mute = wm8994_aif_mute, | ||
3351 | .set_pll = wm8994_set_fll, | ||
3352 | }; | ||
3353 | |||
3354 | static struct snd_soc_dai_ops wm8994_aif2_dai_ops = { | ||
3355 | .set_sysclk = wm8994_set_dai_sysclk, | ||
3356 | .set_fmt = wm8994_set_dai_fmt, | ||
3357 | .hw_params = wm8994_hw_params, | ||
3358 | .digital_mute = wm8994_aif_mute, | ||
3359 | .set_pll = wm8994_set_fll, | ||
3360 | }; | ||
3361 | |||
3362 | struct snd_soc_dai wm8994_dai[] = { | ||
3363 | { | ||
3364 | .name = "WM8994 AIF1", | ||
3365 | .id = 1, | ||
3366 | .playback = { | ||
3367 | .stream_name = "AIF1 Playback", | ||
3368 | .channels_min = 2, | ||
3369 | .channels_max = 2, | ||
3370 | .rates = WM8994_RATES, | ||
3371 | .formats = WM8994_FORMATS, | ||
3372 | }, | ||
3373 | .capture = { | ||
3374 | .stream_name = "AIF1 Capture", | ||
3375 | .channels_min = 2, | ||
3376 | .channels_max = 2, | ||
3377 | .rates = WM8994_RATES, | ||
3378 | .formats = WM8994_FORMATS, | ||
3379 | }, | ||
3380 | .ops = &wm8994_aif1_dai_ops, | ||
3381 | }, | ||
3382 | { | ||
3383 | .name = "WM8994 AIF2", | ||
3384 | .id = 2, | ||
3385 | .playback = { | ||
3386 | .stream_name = "AIF2 Playback", | ||
3387 | .channels_min = 2, | ||
3388 | .channels_max = 2, | ||
3389 | .rates = WM8994_RATES, | ||
3390 | .formats = WM8994_FORMATS, | ||
3391 | }, | ||
3392 | .capture = { | ||
3393 | .stream_name = "AIF2 Capture", | ||
3394 | .channels_min = 2, | ||
3395 | .channels_max = 2, | ||
3396 | .rates = WM8994_RATES, | ||
3397 | .formats = WM8994_FORMATS, | ||
3398 | }, | ||
3399 | .ops = &wm8994_aif2_dai_ops, | ||
3400 | }, | ||
3401 | { | ||
3402 | .name = "WM8994 AIF3", | ||
3403 | .playback = { | ||
3404 | .stream_name = "AIF3 Playback", | ||
3405 | .channels_min = 2, | ||
3406 | .channels_max = 2, | ||
3407 | .rates = WM8994_RATES, | ||
3408 | .formats = WM8994_FORMATS, | ||
3409 | }, | ||
3410 | .capture = { | ||
3411 | .stream_name = "AIF3 Capture", | ||
3412 | .channels_min = 2, | ||
3413 | .channels_max = 2, | ||
3414 | .rates = WM8994_RATES, | ||
3415 | .formats = WM8994_FORMATS, | ||
3416 | }, | ||
3417 | } | ||
3418 | }; | ||
3419 | EXPORT_SYMBOL_GPL(wm8994_dai); | ||
3420 | |||
3421 | #ifdef CONFIG_PM | ||
3422 | static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | ||
3423 | { | ||
3424 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3425 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3426 | struct wm8994_priv *wm8994 = codec->private_data; | ||
3427 | int i, ret; | ||
3428 | |||
3429 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | ||
3430 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | ||
3431 | sizeof(struct fll_config)); | ||
3432 | ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); | ||
3433 | if (ret < 0) | ||
3434 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", | ||
3435 | i + 1, ret); | ||
3436 | } | ||
3437 | |||
3438 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
3439 | |||
3440 | return 0; | ||
3441 | } | ||
3442 | |||
3443 | static int wm8994_resume(struct platform_device *pdev) | ||
3444 | { | ||
3445 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3446 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3447 | struct wm8994_priv *wm8994 = codec->private_data; | ||
3448 | u16 *reg_cache = codec->reg_cache; | ||
3449 | int i, ret; | ||
3450 | |||
3451 | /* Restore the registers */ | ||
3452 | for (i = 1; i < ARRAY_SIZE(wm8994->reg_cache); i++) { | ||
3453 | switch (i) { | ||
3454 | case WM8994_LDO_1: | ||
3455 | case WM8994_LDO_2: | ||
3456 | case WM8994_SOFTWARE_RESET: | ||
3457 | /* Handled by other MFD drivers */ | ||
3458 | continue; | ||
3459 | default: | ||
3460 | break; | ||
3461 | } | ||
3462 | |||
3463 | if (!access_masks[i].writable) | ||
3464 | continue; | ||
3465 | |||
3466 | wm8994_reg_write(codec->control_data, i, reg_cache[i]); | ||
3467 | } | ||
3468 | |||
3469 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
3470 | |||
3471 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | ||
3472 | ret = wm8994_set_fll(&codec->dai[0], i + 1, | ||
3473 | wm8994->fll_suspend[i].src, | ||
3474 | wm8994->fll_suspend[i].in, | ||
3475 | wm8994->fll_suspend[i].out); | ||
3476 | if (ret < 0) | ||
3477 | dev_warn(codec->dev, "Failed to restore FLL%d: %d\n", | ||
3478 | i + 1, ret); | ||
3479 | } | ||
3480 | |||
3481 | return 0; | ||
3482 | } | ||
3483 | #else | ||
3484 | #define wm8994_suspend NULL | ||
3485 | #define wm8994_resume NULL | ||
3486 | #endif | ||
3487 | |||
3488 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | ||
3489 | { | ||
3490 | struct snd_soc_codec *codec = &wm8994->codec; | ||
3491 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
3492 | struct snd_kcontrol_new controls[] = { | ||
3493 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | ||
3494 | wm8994->retune_mobile_enum, | ||
3495 | wm8994_get_retune_mobile_enum, | ||
3496 | wm8994_put_retune_mobile_enum), | ||
3497 | SOC_ENUM_EXT("AIF1.2 EQ Mode", | ||
3498 | wm8994->retune_mobile_enum, | ||
3499 | wm8994_get_retune_mobile_enum, | ||
3500 | wm8994_put_retune_mobile_enum), | ||
3501 | SOC_ENUM_EXT("AIF2 EQ Mode", | ||
3502 | wm8994->retune_mobile_enum, | ||
3503 | wm8994_get_retune_mobile_enum, | ||
3504 | wm8994_put_retune_mobile_enum), | ||
3505 | }; | ||
3506 | int ret, i, j; | ||
3507 | const char **t; | ||
3508 | |||
3509 | /* We need an array of texts for the enum API but the number | ||
3510 | * of texts is likely to be less than the number of | ||
3511 | * configurations due to the sample rate dependency of the | ||
3512 | * configurations. */ | ||
3513 | wm8994->num_retune_mobile_texts = 0; | ||
3514 | wm8994->retune_mobile_texts = NULL; | ||
3515 | for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { | ||
3516 | for (j = 0; j < wm8994->num_retune_mobile_texts; j++) { | ||
3517 | if (strcmp(pdata->retune_mobile_cfgs[i].name, | ||
3518 | wm8994->retune_mobile_texts[j]) == 0) | ||
3519 | break; | ||
3520 | } | ||
3521 | |||
3522 | if (j != wm8994->num_retune_mobile_texts) | ||
3523 | continue; | ||
3524 | |||
3525 | /* Expand the array... */ | ||
3526 | t = krealloc(wm8994->retune_mobile_texts, | ||
3527 | sizeof(char *) * | ||
3528 | (wm8994->num_retune_mobile_texts + 1), | ||
3529 | GFP_KERNEL); | ||
3530 | if (t == NULL) | ||
3531 | continue; | ||
3532 | |||
3533 | /* ...store the new entry... */ | ||
3534 | t[wm8994->num_retune_mobile_texts] = | ||
3535 | pdata->retune_mobile_cfgs[i].name; | ||
3536 | |||
3537 | /* ...and remember the new version. */ | ||
3538 | wm8994->num_retune_mobile_texts++; | ||
3539 | wm8994->retune_mobile_texts = t; | ||
3540 | } | ||
3541 | |||
3542 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | ||
3543 | wm8994->num_retune_mobile_texts); | ||
3544 | |||
3545 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | ||
3546 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | ||
3547 | |||
3548 | ret = snd_soc_add_controls(&wm8994->codec, controls, | ||
3549 | ARRAY_SIZE(controls)); | ||
3550 | if (ret != 0) | ||
3551 | dev_err(wm8994->codec.dev, | ||
3552 | "Failed to add ReTune Mobile controls: %d\n", ret); | ||
3553 | } | ||
3554 | |||
3555 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | ||
3556 | { | ||
3557 | struct snd_soc_codec *codec = &wm8994->codec; | ||
3558 | struct wm8994_pdata *pdata = wm8994->pdata; | ||
3559 | int ret, i; | ||
3560 | |||
3561 | if (!pdata) | ||
3562 | return; | ||
3563 | |||
3564 | wm_hubs_handle_analogue_pdata(codec, pdata->lineout1_diff, | ||
3565 | pdata->lineout2_diff, | ||
3566 | pdata->lineout1fb, | ||
3567 | pdata->lineout2fb, | ||
3568 | pdata->jd_scthr, | ||
3569 | pdata->jd_thr, | ||
3570 | pdata->micbias1_lvl, | ||
3571 | pdata->micbias2_lvl); | ||
3572 | |||
3573 | dev_dbg(codec->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); | ||
3574 | |||
3575 | if (pdata->num_drc_cfgs) { | ||
3576 | struct snd_kcontrol_new controls[] = { | ||
3577 | SOC_ENUM_EXT("AIF1DRC1 Mode", wm8994->drc_enum, | ||
3578 | wm8994_get_drc_enum, wm8994_put_drc_enum), | ||
3579 | SOC_ENUM_EXT("AIF1DRC2 Mode", wm8994->drc_enum, | ||
3580 | wm8994_get_drc_enum, wm8994_put_drc_enum), | ||
3581 | SOC_ENUM_EXT("AIF2DRC Mode", wm8994->drc_enum, | ||
3582 | wm8994_get_drc_enum, wm8994_put_drc_enum), | ||
3583 | }; | ||
3584 | |||
3585 | /* We need an array of texts for the enum API */ | ||
3586 | wm8994->drc_texts = kmalloc(sizeof(char *) | ||
3587 | * pdata->num_drc_cfgs, GFP_KERNEL); | ||
3588 | if (!wm8994->drc_texts) { | ||
3589 | dev_err(wm8994->codec.dev, | ||
3590 | "Failed to allocate %d DRC config texts\n", | ||
3591 | pdata->num_drc_cfgs); | ||
3592 | return; | ||
3593 | } | ||
3594 | |||
3595 | for (i = 0; i < pdata->num_drc_cfgs; i++) | ||
3596 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; | ||
3597 | |||
3598 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | ||
3599 | wm8994->drc_enum.texts = wm8994->drc_texts; | ||
3600 | |||
3601 | ret = snd_soc_add_controls(&wm8994->codec, controls, | ||
3602 | ARRAY_SIZE(controls)); | ||
3603 | if (ret != 0) | ||
3604 | dev_err(wm8994->codec.dev, | ||
3605 | "Failed to add DRC mode controls: %d\n", ret); | ||
3606 | |||
3607 | for (i = 0; i < WM8994_NUM_DRC; i++) | ||
3608 | wm8994_set_drc(codec, i); | ||
3609 | } | ||
3610 | |||
3611 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | ||
3612 | pdata->num_retune_mobile_cfgs); | ||
3613 | |||
3614 | if (pdata->num_retune_mobile_cfgs) | ||
3615 | wm8994_handle_retune_mobile_pdata(wm8994); | ||
3616 | else | ||
3617 | snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, | ||
3618 | ARRAY_SIZE(wm8994_eq_controls)); | ||
3619 | } | ||
3620 | |||
3621 | static int wm8994_probe(struct platform_device *pdev) | ||
3622 | { | ||
3623 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3624 | struct snd_soc_codec *codec; | ||
3625 | int ret = 0; | ||
3626 | |||
3627 | if (wm8994_codec == NULL) { | ||
3628 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
3629 | return -ENODEV; | ||
3630 | } | ||
3631 | |||
3632 | socdev->card->codec = wm8994_codec; | ||
3633 | codec = wm8994_codec; | ||
3634 | |||
3635 | /* register pcms */ | ||
3636 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
3637 | if (ret < 0) { | ||
3638 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
3639 | return ret; | ||
3640 | } | ||
3641 | |||
3642 | wm8994_handle_pdata(codec->private_data); | ||
3643 | |||
3644 | wm_hubs_add_analogue_controls(codec); | ||
3645 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3646 | ARRAY_SIZE(wm8994_snd_controls)); | ||
3647 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
3648 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
3649 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
3650 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
3651 | |||
3652 | return 0; | ||
3653 | } | ||
3654 | |||
3655 | static int wm8994_remove(struct platform_device *pdev) | ||
3656 | { | ||
3657 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3658 | |||
3659 | snd_soc_free_pcms(socdev); | ||
3660 | snd_soc_dapm_free(socdev); | ||
3661 | |||
3662 | return 0; | ||
3663 | } | ||
3664 | |||
3665 | struct snd_soc_codec_device soc_codec_dev_wm8994 = { | ||
3666 | .probe = wm8994_probe, | ||
3667 | .remove = wm8994_remove, | ||
3668 | .suspend = wm8994_suspend, | ||
3669 | .resume = wm8994_resume, | ||
3670 | }; | ||
3671 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); | ||
3672 | |||
3673 | static int wm8994_codec_probe(struct platform_device *pdev) | ||
3674 | { | ||
3675 | int ret; | ||
3676 | struct wm8994_priv *wm8994; | ||
3677 | struct snd_soc_codec *codec; | ||
3678 | int i; | ||
3679 | u16 rev; | ||
3680 | |||
3681 | if (wm8994_codec) { | ||
3682 | dev_err(&pdev->dev, "Another WM8994 is registered\n"); | ||
3683 | return -EINVAL; | ||
3684 | } | ||
3685 | |||
3686 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); | ||
3687 | if (!wm8994) { | ||
3688 | dev_err(&pdev->dev, "Failed to allocate private data\n"); | ||
3689 | return -ENOMEM; | ||
3690 | } | ||
3691 | |||
3692 | codec = &wm8994->codec; | ||
3693 | |||
3694 | mutex_init(&codec->mutex); | ||
3695 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
3696 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
3697 | |||
3698 | codec->private_data = wm8994; | ||
3699 | codec->control_data = dev_get_drvdata(pdev->dev.parent); | ||
3700 | codec->name = "WM8994"; | ||
3701 | codec->owner = THIS_MODULE; | ||
3702 | codec->read = wm8994_read; | ||
3703 | codec->write = wm8994_write; | ||
3704 | codec->readable_register = wm8994_readable; | ||
3705 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3706 | codec->set_bias_level = wm8994_set_bias_level; | ||
3707 | codec->dai = &wm8994_dai[0]; | ||
3708 | codec->num_dai = 3; | ||
3709 | codec->reg_cache_size = WM8994_MAX_REGISTER; | ||
3710 | codec->reg_cache = &wm8994->reg_cache; | ||
3711 | codec->dev = &pdev->dev; | ||
3712 | |||
3713 | wm8994->pdata = pdev->dev.parent->platform_data; | ||
3714 | |||
3715 | /* Fill the cache with physical values we inherited; don't reset */ | ||
3716 | ret = wm8994_bulk_read(codec->control_data, 0, | ||
3717 | ARRAY_SIZE(wm8994->reg_cache) - 1, | ||
3718 | codec->reg_cache); | ||
3719 | if (ret < 0) { | ||
3720 | dev_err(codec->dev, "Failed to fill register cache: %d\n", | ||
3721 | ret); | ||
3722 | goto err; | ||
3723 | } | ||
3724 | |||
3725 | /* Clear the cached values for unreadable/volatile registers to | ||
3726 | * avoid potential confusion. | ||
3727 | */ | ||
3728 | for (i = 0; i < ARRAY_SIZE(wm8994->reg_cache); i++) | ||
3729 | if (wm8994_volatile(i) || !wm8994_readable(i)) | ||
3730 | wm8994->reg_cache[i] = 0; | ||
3731 | |||
3732 | /* Set revision-specific configuration */ | ||
3733 | rev = snd_soc_read(codec, WM8994_CHIP_REVISION); | ||
3734 | switch (rev) { | ||
3735 | case 2: | ||
3736 | case 3: | ||
3737 | wm8994->hubs.dcs_codes = -5; | ||
3738 | wm8994->hubs.hp_startup_mode = 1; | ||
3739 | wm8994->hubs.dcs_readback_mode = 1; | ||
3740 | break; | ||
3741 | default: | ||
3742 | wm8994->hubs.dcs_readback_mode = 1; | ||
3743 | break; | ||
3744 | } | ||
3745 | |||
3746 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | ||
3747 | * configured on init - if a system wants to do this dynamically | ||
3748 | * at runtime we can deal with that then. | ||
3749 | */ | ||
3750 | ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1); | ||
3751 | if (ret < 0) { | ||
3752 | dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret); | ||
3753 | goto err; | ||
3754 | } | ||
3755 | if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { | ||
3756 | wm8994->lrclk_shared[0] = 1; | ||
3757 | wm8994_dai[0].symmetric_rates = 1; | ||
3758 | } else { | ||
3759 | wm8994->lrclk_shared[0] = 0; | ||
3760 | } | ||
3761 | |||
3762 | ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6); | ||
3763 | if (ret < 0) { | ||
3764 | dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret); | ||
3765 | goto err; | ||
3766 | } | ||
3767 | if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { | ||
3768 | wm8994->lrclk_shared[1] = 1; | ||
3769 | wm8994_dai[1].symmetric_rates = 1; | ||
3770 | } else { | ||
3771 | wm8994->lrclk_shared[1] = 0; | ||
3772 | } | ||
3773 | |||
3774 | for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) | ||
3775 | wm8994_dai[i].dev = codec->dev; | ||
3776 | |||
3777 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
3778 | |||
3779 | wm8994_codec = codec; | ||
3780 | |||
3781 | /* Latch volume updates (right only; we always do left then right). */ | ||
3782 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, | ||
3783 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); | ||
3784 | snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, | ||
3785 | WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); | ||
3786 | snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, | ||
3787 | WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); | ||
3788 | snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, | ||
3789 | WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); | ||
3790 | snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, | ||
3791 | WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); | ||
3792 | snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, | ||
3793 | WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); | ||
3794 | snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, | ||
3795 | WM8994_DAC1_VU, WM8994_DAC1_VU); | ||
3796 | snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, | ||
3797 | WM8994_DAC2_VU, WM8994_DAC2_VU); | ||
3798 | |||
3799 | /* Set the low bit of the 3D stereo depth so TLV matches */ | ||
3800 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2, | ||
3801 | 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT, | ||
3802 | 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT); | ||
3803 | snd_soc_update_bits(codec, WM8994_AIF1_DAC2_FILTERS_2, | ||
3804 | 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT, | ||
3805 | 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT); | ||
3806 | snd_soc_update_bits(codec, WM8994_AIF2_DAC_FILTERS_2, | ||
3807 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, | ||
3808 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); | ||
3809 | |||
3810 | wm8994_update_class_w(codec); | ||
3811 | |||
3812 | ret = snd_soc_register_codec(codec); | ||
3813 | if (ret != 0) { | ||
3814 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
3815 | goto err; | ||
3816 | } | ||
3817 | |||
3818 | ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
3819 | if (ret != 0) { | ||
3820 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
3821 | goto err_codec; | ||
3822 | } | ||
3823 | |||
3824 | platform_set_drvdata(pdev, wm8994); | ||
3825 | |||
3826 | return 0; | ||
3827 | |||
3828 | err_codec: | ||
3829 | snd_soc_unregister_codec(codec); | ||
3830 | err: | ||
3831 | kfree(wm8994); | ||
3832 | return ret; | ||
3833 | } | ||
3834 | |||
3835 | static int __devexit wm8994_codec_remove(struct platform_device *pdev) | ||
3836 | { | ||
3837 | struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); | ||
3838 | struct snd_soc_codec *codec = &wm8994->codec; | ||
3839 | |||
3840 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
3841 | snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
3842 | snd_soc_unregister_codec(&wm8994->codec); | ||
3843 | kfree(wm8994); | ||
3844 | wm8994_codec = NULL; | ||
3845 | |||
3846 | return 0; | ||
3847 | } | ||
3848 | |||
3849 | static struct platform_driver wm8994_codec_driver = { | ||
3850 | .driver = { | ||
3851 | .name = "wm8994-codec", | ||
3852 | .owner = THIS_MODULE, | ||
3853 | }, | ||
3854 | .probe = wm8994_codec_probe, | ||
3855 | .remove = __devexit_p(wm8994_codec_remove), | ||
3856 | }; | ||
3857 | |||
3858 | static __init int wm8994_init(void) | ||
3859 | { | ||
3860 | return platform_driver_register(&wm8994_codec_driver); | ||
3861 | } | ||
3862 | module_init(wm8994_init); | ||
3863 | |||
3864 | static __exit void wm8994_exit(void) | ||
3865 | { | ||
3866 | platform_driver_unregister(&wm8994_codec_driver); | ||
3867 | } | ||
3868 | module_exit(wm8994_exit); | ||
3869 | |||
3870 | |||
3871 | MODULE_DESCRIPTION("ASoC WM8994 driver"); | ||
3872 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
3873 | MODULE_LICENSE("GPL"); | ||
3874 | MODULE_ALIAS("platform:wm8994-codec"); | ||
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h new file mode 100644 index 000000000000..0a5e1424dea0 --- /dev/null +++ b/sound/soc/codecs/wm8994.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * wm8994.h -- WM8994 Soc Audio driver | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _WM8994_H | ||
10 | #define _WM8994_H | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | |||
14 | extern struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
15 | extern struct snd_soc_dai wm8994_dai[]; | ||
16 | |||
17 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ | ||
18 | #define WM8994_SYSCLK_MCLK1 1 | ||
19 | #define WM8994_SYSCLK_MCLK2 2 | ||
20 | #define WM8994_SYSCLK_FLL1 3 | ||
21 | #define WM8994_SYSCLK_FLL2 4 | ||
22 | |||
23 | #define WM8994_FLL1 1 | ||
24 | #define WM8994_FLL2 2 | ||
25 | |||
26 | #endif | ||
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 686e5aa97206..3a184fcb702b 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -1262,19 +1263,9 @@ static int wm9081_probe(struct platform_device *pdev) | |||
1262 | snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets, | 1263 | snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets, |
1263 | ARRAY_SIZE(wm9081_dapm_widgets)); | 1264 | ARRAY_SIZE(wm9081_dapm_widgets)); |
1264 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 1265 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
1265 | snd_soc_dapm_new_widgets(codec); | ||
1266 | |||
1267 | ret = snd_soc_init_card(socdev); | ||
1268 | if (ret < 0) { | ||
1269 | dev_err(codec->dev, "failed to register card: %d\n", ret); | ||
1270 | goto card_err; | ||
1271 | } | ||
1272 | 1266 | ||
1273 | return ret; | 1267 | return ret; |
1274 | 1268 | ||
1275 | card_err: | ||
1276 | snd_soc_free_pcms(socdev); | ||
1277 | snd_soc_dapm_free(socdev); | ||
1278 | pcm_err: | 1269 | pcm_err: |
1279 | return ret; | 1270 | return ret; |
1280 | } | 1271 | } |
@@ -1452,21 +1443,6 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client) | |||
1452 | return 0; | 1443 | return 0; |
1453 | } | 1444 | } |
1454 | 1445 | ||
1455 | #ifdef CONFIG_PM | ||
1456 | static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
1457 | { | ||
1458 | return snd_soc_suspend_device(&client->dev); | ||
1459 | } | ||
1460 | |||
1461 | static int wm9081_i2c_resume(struct i2c_client *client) | ||
1462 | { | ||
1463 | return snd_soc_resume_device(&client->dev); | ||
1464 | } | ||
1465 | #else | ||
1466 | #define wm9081_i2c_suspend NULL | ||
1467 | #define wm9081_i2c_resume NULL | ||
1468 | #endif | ||
1469 | |||
1470 | static const struct i2c_device_id wm9081_i2c_id[] = { | 1446 | static const struct i2c_device_id wm9081_i2c_id[] = { |
1471 | { "wm9081", 0 }, | 1447 | { "wm9081", 0 }, |
1472 | { } | 1448 | { } |
@@ -1480,8 +1456,6 @@ static struct i2c_driver wm9081_i2c_driver = { | |||
1480 | }, | 1456 | }, |
1481 | .probe = wm9081_i2c_probe, | 1457 | .probe = wm9081_i2c_probe, |
1482 | .remove = __devexit_p(wm9081_i2c_remove), | 1458 | .remove = __devexit_p(wm9081_i2c_remove), |
1483 | .suspend = wm9081_i2c_suspend, | ||
1484 | .resume = wm9081_i2c_resume, | ||
1485 | .id_table = wm9081_i2c_id, | 1459 | .id_table = wm9081_i2c_id, |
1486 | }; | 1460 | }; |
1487 | 1461 | ||
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index e7d2840d9e59..8793341849d1 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
@@ -205,7 +206,6 @@ static int wm9705_add_widgets(struct snd_soc_codec *codec) | |||
205 | snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, | 206 | snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, |
206 | ARRAY_SIZE(wm9705_dapm_widgets)); | 207 | ARRAY_SIZE(wm9705_dapm_widgets)); |
207 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 208 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
208 | snd_soc_dapm_new_widgets(codec); | ||
209 | 209 | ||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
@@ -403,12 +403,6 @@ static int wm9705_soc_probe(struct platform_device *pdev) | |||
403 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | 403 | ARRAY_SIZE(wm9705_snd_ac97_controls)); |
404 | wm9705_add_widgets(codec); | 404 | wm9705_add_widgets(codec); |
405 | 405 | ||
406 | ret = snd_soc_init_card(socdev); | ||
407 | if (ret < 0) { | ||
408 | printk(KERN_ERR "wm9705: failed to register card\n"); | ||
409 | goto reset_err; | ||
410 | } | ||
411 | |||
412 | return 0; | 406 | return 0; |
413 | 407 | ||
414 | reset_err: | 408 | reset_err: |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1fd4e88f50cf..2f48a8aae22c 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
@@ -436,7 +437,6 @@ static int wm9712_add_widgets(struct snd_soc_codec *codec) | |||
436 | 437 | ||
437 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 438 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
438 | 439 | ||
439 | snd_soc_dapm_new_widgets(codec); | ||
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
442 | 442 | ||
@@ -464,7 +464,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
464 | { | 464 | { |
465 | u16 *cache = codec->reg_cache; | 465 | u16 *cache = codec->reg_cache; |
466 | 466 | ||
467 | soc_ac97_ops.write(codec->ac97, reg, val); | 467 | if (reg < 0x7c) |
468 | soc_ac97_ops.write(codec->ac97, reg, val); | ||
468 | reg = reg >> 1; | 469 | reg = reg >> 1; |
469 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 470 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
470 | cache[reg] = val; | 471 | cache[reg] = val; |
@@ -695,17 +696,11 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
695 | snd_soc_add_controls(codec, wm9712_snd_ac97_controls, | 696 | snd_soc_add_controls(codec, wm9712_snd_ac97_controls, |
696 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | 697 | ARRAY_SIZE(wm9712_snd_ac97_controls)); |
697 | wm9712_add_widgets(codec); | 698 | wm9712_add_widgets(codec); |
698 | ret = snd_soc_init_card(socdev); | ||
699 | if (ret < 0) { | ||
700 | printk(KERN_ERR "wm9712: failed to register card\n"); | ||
701 | goto reset_err; | ||
702 | } | ||
703 | 699 | ||
704 | return 0; | 700 | return 0; |
705 | 701 | ||
706 | reset_err: | 702 | reset_err: |
707 | snd_soc_free_pcms(socdev); | 703 | snd_soc_free_pcms(socdev); |
708 | |||
709 | pcm_err: | 704 | pcm_err: |
710 | snd_soc_free_ac97_codec(codec); | 705 | snd_soc_free_ac97_codec(codec); |
711 | 706 | ||
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index abed37acf787..2fca514fde58 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
@@ -23,13 +24,12 @@ | |||
23 | #include <sound/ac97_codec.h> | 24 | #include <sound/ac97_codec.h> |
24 | #include <sound/initval.h> | 25 | #include <sound/initval.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
27 | #include <sound/tlv.h> | ||
26 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
27 | #include <sound/soc-dapm.h> | 29 | #include <sound/soc-dapm.h> |
28 | 30 | ||
29 | #include "wm9713.h" | 31 | #include "wm9713.h" |
30 | 32 | ||
31 | #define WM9713_VERSION "0.15" | ||
32 | |||
33 | struct wm9713_priv { | 33 | struct wm9713_priv { |
34 | u32 pll_in; /* PLL input frequency */ | 34 | u32 pll_in; /* PLL input frequency */ |
35 | }; | 35 | }; |
@@ -115,15 +115,27 @@ SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 | |||
115 | SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ | 115 | SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); | ||
119 | static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0); | ||
120 | static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0); | ||
121 | static unsigned int mic_tlv[] = { | ||
122 | TLV_DB_RANGE_HEAD(2), | ||
123 | 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), | ||
124 | 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0), | ||
125 | }; | ||
126 | |||
118 | static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = { | 127 | static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = { |
119 | SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1), | 128 | SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv), |
120 | SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1), | 129 | SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1), |
121 | SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), | 130 | SOC_DOUBLE_TLV("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1, |
131 | out_tlv), | ||
122 | SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1), | 132 | SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1), |
123 | SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1), | 133 | SOC_DOUBLE_TLV("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1, main_tlv), |
124 | SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1), | 134 | SOC_DOUBLE_TLV("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1, main_tlv), |
125 | SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), | 135 | SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), |
126 | SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), | 136 | SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), |
137 | SOC_SINGLE_TLV("Mic 1 Preamp Volume", AC97_3D_CONTROL, 10, 3, 0, mic_tlv), | ||
138 | SOC_SINGLE_TLV("Mic 2 Preamp Volume", AC97_3D_CONTROL, 12, 3, 0, mic_tlv), | ||
127 | 139 | ||
128 | SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), | 140 | SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), |
129 | SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), | 141 | SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), |
@@ -133,7 +145,7 @@ SOC_ENUM("Capture Volume Steps", wm9713_enum[5]), | |||
133 | SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0), | 145 | SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0), |
134 | SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0), | 146 | SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0), |
135 | 147 | ||
136 | SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1), | 148 | SOC_SINGLE_TLV("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1, misc_tlv), |
137 | SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0), | 149 | SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0), |
138 | SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0), | 150 | SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0), |
139 | 151 | ||
@@ -154,28 +166,43 @@ SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0), | |||
154 | 166 | ||
155 | SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1), | 167 | SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1), |
156 | SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0), | 168 | SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0), |
157 | SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1), | 169 | SOC_SINGLE_TLV("Out4 Playback Volume", AC97_MASTER_MONO, 8, 31, 1, out_tlv), |
158 | 170 | ||
159 | SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1), | 171 | SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1), |
160 | SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0), | 172 | SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0), |
161 | SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1), | 173 | SOC_SINGLE_TLV("Out3 Playback Volume", AC97_MASTER_MONO, 0, 31, 1, out_tlv), |
162 | 174 | ||
163 | SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1), | 175 | SOC_SINGLE_TLV("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1, main_tlv), |
164 | SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1), | 176 | SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1), |
165 | SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0), | 177 | SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0), |
166 | SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1), | 178 | SOC_SINGLE_TLV("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1, out_tlv), |
167 | 179 | ||
168 | SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1), | 180 | SOC_SINGLE_TLV("Headphone Mixer Beep Playback Volume", AC97_AUX, 12, 7, 1, |
169 | SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1), | 181 | misc_tlv), |
170 | SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1), | 182 | SOC_SINGLE_TLV("Speaker Mixer Beep Playback Volume", AC97_AUX, 8, 7, 1, |
183 | misc_tlv), | ||
184 | SOC_SINGLE_TLV("Mono Mixer Beep Playback Volume", AC97_AUX, 4, 7, 1, misc_tlv), | ||
171 | 185 | ||
172 | SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1), | 186 | SOC_SINGLE_TLV("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1, |
187 | misc_tlv), | ||
173 | SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1), | 188 | SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1), |
174 | SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1), | 189 | SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1), |
175 | 190 | ||
191 | SOC_SINGLE_TLV("Headphone Mixer Aux Playback Volume", AC97_REC_SEL, 12, 7, 1, | ||
192 | misc_tlv), | ||
193 | |||
194 | SOC_SINGLE_TLV("Speaker Mixer Voice Playback Volume", AC97_PCM, 8, 7, 1, | ||
195 | misc_tlv), | ||
196 | SOC_SINGLE_TLV("Speaker Mixer Aux Playback Volume", AC97_REC_SEL, 8, 7, 1, | ||
197 | misc_tlv), | ||
198 | |||
199 | SOC_SINGLE_TLV("Mono Mixer Voice Playback Volume", AC97_PCM, 4, 7, 1, | ||
200 | misc_tlv), | ||
201 | SOC_SINGLE_TLV("Mono Mixer Aux Playback Volume", AC97_REC_SEL, 4, 7, 1, | ||
202 | misc_tlv), | ||
203 | |||
176 | SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1), | 204 | SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1), |
177 | SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1), | 205 | SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1), |
178 | SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1), | ||
179 | 206 | ||
180 | SOC_ENUM("Bass Control", wm9713_enum[16]), | 207 | SOC_ENUM("Bass Control", wm9713_enum[16]), |
181 | SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1), | 208 | SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1), |
@@ -266,7 +293,7 @@ static int mixer_event(struct snd_soc_dapm_widget *w, | |||
266 | 293 | ||
267 | /* Left Headphone Mixers */ | 294 | /* Left Headphone Mixers */ |
268 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { | 295 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { |
269 | SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0), | 296 | SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), |
270 | SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), | 297 | SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), |
271 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), | 298 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), |
272 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), | 299 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), |
@@ -276,7 +303,7 @@ SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), | |||
276 | 303 | ||
277 | /* Right Headphone Mixers */ | 304 | /* Right Headphone Mixers */ |
278 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { | 305 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { |
279 | SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0), | 306 | SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), |
280 | SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), | 307 | SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), |
281 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), | 308 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), |
282 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), | 309 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), |
@@ -294,7 +321,7 @@ SOC_DAPM_ENUM("Route", wm9713_enum[0]); | |||
294 | 321 | ||
295 | /* Speaker Mixer */ | 322 | /* Speaker Mixer */ |
296 | static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = { | 323 | static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = { |
297 | SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1), | 324 | SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 11, 1, 1), |
298 | SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1), | 325 | SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1), |
299 | SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1), | 326 | SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1), |
300 | SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1), | 327 | SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1), |
@@ -304,7 +331,7 @@ SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1), | |||
304 | 331 | ||
305 | /* Mono Mixer */ | 332 | /* Mono Mixer */ |
306 | static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = { | 333 | static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = { |
307 | SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1), | 334 | SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 7, 1, 1), |
308 | SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1), | 335 | SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1), |
309 | SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1), | 336 | SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1), |
310 | SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1), | 337 | SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1), |
@@ -463,7 +490,7 @@ SND_SOC_DAPM_VMID("VMID"), | |||
463 | 490 | ||
464 | static const struct snd_soc_dapm_route audio_map[] = { | 491 | static const struct snd_soc_dapm_route audio_map[] = { |
465 | /* left HP mixer */ | 492 | /* left HP mixer */ |
466 | {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, | 493 | {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"}, |
467 | {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, | 494 | {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, |
468 | {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"}, | 495 | {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"}, |
469 | {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"}, | 496 | {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"}, |
@@ -472,7 +499,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
472 | {"Left HP Mixer", NULL, "Capture Headphone Mux"}, | 499 | {"Left HP Mixer", NULL, "Capture Headphone Mux"}, |
473 | 500 | ||
474 | /* right HP mixer */ | 501 | /* right HP mixer */ |
475 | {"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, | 502 | {"Right HP Mixer", "Beep Playback Switch", "PCBEEP"}, |
476 | {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"}, | 503 | {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"}, |
477 | {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"}, | 504 | {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"}, |
478 | {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"}, | 505 | {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"}, |
@@ -491,7 +518,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
491 | {"Capture Mixer", NULL, "Right Capture Source"}, | 518 | {"Capture Mixer", NULL, "Right Capture Source"}, |
492 | 519 | ||
493 | /* speaker mixer */ | 520 | /* speaker mixer */ |
494 | {"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"}, | 521 | {"Speaker Mixer", "Beep Playback Switch", "PCBEEP"}, |
495 | {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"}, | 522 | {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"}, |
496 | {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"}, | 523 | {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"}, |
497 | {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"}, | 524 | {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"}, |
@@ -499,7 +526,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
499 | {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"}, | 526 | {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"}, |
500 | 527 | ||
501 | /* mono mixer */ | 528 | /* mono mixer */ |
502 | {"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"}, | 529 | {"Mono Mixer", "Beep Playback Switch", "PCBEEP"}, |
503 | {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, | 530 | {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, |
504 | {"Mono Mixer", "Aux Playback Switch", "Aux DAC"}, | 531 | {"Mono Mixer", "Aux Playback Switch", "Aux DAC"}, |
505 | {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"}, | 532 | {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"}, |
@@ -625,7 +652,6 @@ static int wm9713_add_widgets(struct snd_soc_codec *codec) | |||
625 | 652 | ||
626 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 653 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
627 | 654 | ||
628 | snd_soc_dapm_new_widgets(codec); | ||
629 | return 0; | 655 | return 0; |
630 | } | 656 | } |
631 | 657 | ||
@@ -800,8 +826,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
800 | return 0; | 826 | return 0; |
801 | } | 827 | } |
802 | 828 | ||
803 | static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, | 829 | static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, |
804 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 830 | int source, unsigned int freq_in, unsigned int freq_out) |
805 | { | 831 | { |
806 | struct snd_soc_codec *codec = codec_dai->codec; | 832 | struct snd_soc_codec *codec = codec_dai->codec; |
807 | return wm9713_set_pll(codec, pll_id, freq_in, freq_out); | 833 | return wm9713_set_pll(codec, pll_id, freq_in, freq_out); |
@@ -1187,8 +1213,6 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1187 | struct snd_soc_codec *codec; | 1213 | struct snd_soc_codec *codec; |
1188 | int ret = 0, reg; | 1214 | int ret = 0, reg; |
1189 | 1215 | ||
1190 | printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION); | ||
1191 | |||
1192 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | 1216 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), |
1193 | GFP_KERNEL); | 1217 | GFP_KERNEL); |
1194 | if (socdev->card->codec == NULL) | 1218 | if (socdev->card->codec == NULL) |
@@ -1247,14 +1271,11 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1247 | snd_soc_add_controls(codec, wm9713_snd_ac97_controls, | 1271 | snd_soc_add_controls(codec, wm9713_snd_ac97_controls, |
1248 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | 1272 | ARRAY_SIZE(wm9713_snd_ac97_controls)); |
1249 | wm9713_add_widgets(codec); | 1273 | wm9713_add_widgets(codec); |
1250 | ret = snd_soc_init_card(socdev); | 1274 | |
1251 | if (ret < 0) | ||
1252 | goto reset_err; | ||
1253 | return 0; | 1275 | return 0; |
1254 | 1276 | ||
1255 | reset_err: | 1277 | reset_err: |
1256 | snd_soc_free_pcms(socdev); | 1278 | snd_soc_free_pcms(socdev); |
1257 | |||
1258 | pcm_err: | 1279 | pcm_err: |
1259 | snd_soc_free_ac97_codec(codec); | 1280 | snd_soc_free_ac97_codec(codec); |
1260 | 1281 | ||
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e542027eea89..e1f225a3ac46 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -62,36 +62,108 @@ static const char *speaker_mode_text[] = { | |||
62 | static const struct soc_enum speaker_mode = | 62 | static const struct soc_enum speaker_mode = |
63 | SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); | 63 | SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); |
64 | 64 | ||
65 | static void wait_for_dc_servo(struct snd_soc_codec *codec) | 65 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) |
66 | { | 66 | { |
67 | unsigned int reg; | 67 | unsigned int reg; |
68 | int count = 0; | 68 | int count = 0; |
69 | unsigned int val; | ||
70 | |||
71 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; | ||
72 | |||
73 | /* Trigger the command */ | ||
74 | snd_soc_write(codec, WM8993_DC_SERVO_0, val); | ||
69 | 75 | ||
70 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); | 76 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); |
77 | |||
71 | do { | 78 | do { |
72 | count++; | 79 | count++; |
73 | msleep(1); | 80 | msleep(1); |
74 | reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); | 81 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); |
75 | dev_dbg(codec->dev, "DC servo status: %x\n", reg); | 82 | dev_dbg(codec->dev, "DC servo: %x\n", reg); |
76 | } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK) | 83 | } while (reg & op && count < 400); |
77 | != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000); | ||
78 | 84 | ||
79 | if ((reg & WM8993_DCS_CAL_COMPLETE_MASK) | 85 | if (reg & op) |
80 | != WM8993_DCS_CAL_COMPLETE_MASK) | ||
81 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); | 86 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); |
82 | } | 87 | } |
83 | 88 | ||
84 | /* | 89 | /* |
90 | * Startup calibration of the DC servo | ||
91 | */ | ||
92 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | ||
93 | { | ||
94 | struct wm_hubs_data *hubs = codec->private_data; | ||
95 | u16 reg, reg_l, reg_r, dcs_cfg; | ||
96 | |||
97 | /* Set for 32 series updates */ | ||
98 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | ||
99 | WM8993_DCS_SERIES_NO_01_MASK, | ||
100 | 32 << WM8993_DCS_SERIES_NO_01_SHIFT); | ||
101 | wait_for_dc_servo(codec, | ||
102 | WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1); | ||
103 | |||
104 | /* Apply correction to DC servo result */ | ||
105 | if (hubs->dcs_codes) { | ||
106 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | ||
107 | hubs->dcs_codes); | ||
108 | |||
109 | /* Different chips in the family support different | ||
110 | * readback methods. | ||
111 | */ | ||
112 | switch (hubs->dcs_readback_mode) { | ||
113 | case 0: | ||
114 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
115 | & WM8993_DCS_INTEG_CHAN_0_MASK;; | ||
116 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
117 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
118 | break; | ||
119 | case 1: | ||
120 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | ||
121 | reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
122 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
123 | reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
124 | break; | ||
125 | default: | ||
126 | WARN(1, "Unknown DCS readback method"); | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | /* HPOUT1L */ | ||
131 | if (reg_l + hubs->dcs_codes > 0 && | ||
132 | reg_l + hubs->dcs_codes < 0xff) | ||
133 | reg_l += hubs->dcs_codes; | ||
134 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
135 | |||
136 | /* HPOUT1R */ | ||
137 | if (reg_r + hubs->dcs_codes > 0 && | ||
138 | reg_r + hubs->dcs_codes < 0xff) | ||
139 | reg_r += hubs->dcs_codes; | ||
140 | dcs_cfg |= reg_r; | ||
141 | |||
142 | /* Do it */ | ||
143 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); | ||
144 | wait_for_dc_servo(codec, | ||
145 | WM8993_DCS_TRIG_DAC_WR_0 | | ||
146 | WM8993_DCS_TRIG_DAC_WR_1); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /* | ||
85 | * Update the DC servo calibration on gain changes | 151 | * Update the DC servo calibration on gain changes |
86 | */ | 152 | */ |
87 | static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | 153 | static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, |
88 | struct snd_ctl_elem_value *ucontrol) | 154 | struct snd_ctl_elem_value *ucontrol) |
89 | { | 155 | { |
90 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 156 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
157 | struct wm_hubs_data *hubs = codec->private_data; | ||
91 | int ret; | 158 | int ret; |
92 | 159 | ||
93 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); | 160 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); |
94 | 161 | ||
162 | /* If we're applying an offset correction then updating the | ||
163 | * callibration would be likely to introduce further offsets. */ | ||
164 | if (hubs->dcs_codes) | ||
165 | return ret; | ||
166 | |||
95 | /* Only need to do this if the outputs are active */ | 167 | /* Only need to do this if the outputs are active */ |
96 | if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) | 168 | if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) |
97 | & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) | 169 | & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) |
@@ -251,6 +323,47 @@ SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, | |||
251 | line_tlv), | 323 | line_tlv), |
252 | }; | 324 | }; |
253 | 325 | ||
326 | static int hp_supply_event(struct snd_soc_dapm_widget *w, | ||
327 | struct snd_kcontrol *kcontrol, int event) | ||
328 | { | ||
329 | struct snd_soc_codec *codec = w->codec; | ||
330 | struct wm_hubs_data *hubs = codec->private_data; | ||
331 | |||
332 | switch (event) { | ||
333 | case SND_SOC_DAPM_PRE_PMU: | ||
334 | switch (hubs->hp_startup_mode) { | ||
335 | case 0: | ||
336 | break; | ||
337 | case 1: | ||
338 | /* Enable the headphone amp */ | ||
339 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | ||
340 | WM8993_HPOUT1L_ENA | | ||
341 | WM8993_HPOUT1R_ENA, | ||
342 | WM8993_HPOUT1L_ENA | | ||
343 | WM8993_HPOUT1R_ENA); | ||
344 | |||
345 | /* Enable the second stage */ | ||
346 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | ||
347 | WM8993_HPOUT1L_DLY | | ||
348 | WM8993_HPOUT1R_DLY, | ||
349 | WM8993_HPOUT1L_DLY | | ||
350 | WM8993_HPOUT1R_DLY); | ||
351 | break; | ||
352 | default: | ||
353 | dev_err(codec->dev, "Unknown HP startup mode %d\n", | ||
354 | hubs->hp_startup_mode); | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | case SND_SOC_DAPM_PRE_PMD: | ||
359 | snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, | ||
360 | WM8993_CP_ENA, 0); | ||
361 | break; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
254 | static int hp_event(struct snd_soc_dapm_widget *w, | 367 | static int hp_event(struct snd_soc_dapm_widget *w, |
255 | struct snd_kcontrol *kcontrol, int event) | 368 | struct snd_kcontrol *kcontrol, int event) |
256 | { | 369 | { |
@@ -271,14 +384,11 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
271 | reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; | 384 | reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; |
272 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); | 385 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); |
273 | 386 | ||
274 | /* Start the DC servo */ | 387 | /* Smallest supported update interval */ |
275 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 388 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
276 | 0xFFFF, | 389 | WM8993_DCS_TIMER_PERIOD_01_MASK, 1); |
277 | WM8993_DCS_ENA_CHAN_0 | | 390 | |
278 | WM8993_DCS_ENA_CHAN_1 | | 391 | calibrate_dc_servo(codec); |
279 | WM8993_DCS_TRIG_STARTUP_1 | | ||
280 | WM8993_DCS_TRIG_STARTUP_0); | ||
281 | wait_for_dc_servo(codec); | ||
282 | 392 | ||
283 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 393 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
284 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 394 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
@@ -286,23 +396,19 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
286 | break; | 396 | break; |
287 | 397 | ||
288 | case SND_SOC_DAPM_PRE_PMD: | 398 | case SND_SOC_DAPM_PRE_PMD: |
289 | reg &= ~(WM8993_HPOUT1L_RMV_SHORT | | 399 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, |
290 | WM8993_HPOUT1L_DLY | | 400 | WM8993_HPOUT1L_DLY | |
291 | WM8993_HPOUT1L_OUTP | | 401 | WM8993_HPOUT1R_DLY | |
292 | WM8993_HPOUT1R_RMV_SHORT | | 402 | WM8993_HPOUT1L_RMV_SHORT | |
293 | WM8993_HPOUT1R_DLY | | 403 | WM8993_HPOUT1R_RMV_SHORT, 0); |
294 | WM8993_HPOUT1R_OUTP); | ||
295 | 404 | ||
296 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 405 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, |
297 | 0xffff, 0); | 406 | WM8993_HPOUT1L_OUTP | |
407 | WM8993_HPOUT1R_OUTP, 0); | ||
298 | 408 | ||
299 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); | ||
300 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | 409 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, |
301 | WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, | 410 | WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, |
302 | 0); | 411 | 0); |
303 | |||
304 | snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, | ||
305 | WM8993_CP_ENA, 0); | ||
306 | break; | 412 | break; |
307 | } | 413 | } |
308 | 414 | ||
@@ -438,11 +544,11 @@ static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = { | |||
438 | SND_SOC_DAPM_INPUT("IN1LN"), | 544 | SND_SOC_DAPM_INPUT("IN1LN"), |
439 | SND_SOC_DAPM_INPUT("IN1LP"), | 545 | SND_SOC_DAPM_INPUT("IN1LP"), |
440 | SND_SOC_DAPM_INPUT("IN2LN"), | 546 | SND_SOC_DAPM_INPUT("IN2LN"), |
441 | SND_SOC_DAPM_INPUT("IN2LP/VXRN"), | 547 | SND_SOC_DAPM_INPUT("IN2LP:VXRN"), |
442 | SND_SOC_DAPM_INPUT("IN1RN"), | 548 | SND_SOC_DAPM_INPUT("IN1RN"), |
443 | SND_SOC_DAPM_INPUT("IN1RP"), | 549 | SND_SOC_DAPM_INPUT("IN1RP"), |
444 | SND_SOC_DAPM_INPUT("IN2RN"), | 550 | SND_SOC_DAPM_INPUT("IN2RN"), |
445 | SND_SOC_DAPM_INPUT("IN2RP/VXRP"), | 551 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), |
446 | 552 | ||
447 | SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), | 553 | SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), |
448 | SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), | 554 | SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), |
@@ -473,6 +579,8 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, | |||
473 | SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), | 579 | SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), |
474 | SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), | 580 | SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), |
475 | 581 | ||
582 | SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event, | ||
583 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
476 | SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, | 584 | SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, |
477 | NULL, 0, | 585 | NULL, 0, |
478 | hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 586 | hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -537,14 +645,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
537 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, | 645 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, |
538 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, | 646 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, |
539 | 647 | ||
540 | { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, | 648 | { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" }, |
541 | { "IN2L PGA", "IN2LN Switch", "IN2LN" }, | 649 | { "IN2L PGA", "IN2LN Switch", "IN2LN" }, |
542 | 650 | ||
543 | { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, | 651 | { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" }, |
544 | { "IN2R PGA", "IN2RN Switch", "IN2RN" }, | 652 | { "IN2R PGA", "IN2RN Switch", "IN2RN" }, |
545 | 653 | ||
546 | { "Direct Voice", NULL, "IN2LP/VXRN" }, | 654 | { "Direct Voice", NULL, "IN2LP:VXRN" }, |
547 | { "Direct Voice", NULL, "IN2RP/VXRP" }, | 655 | { "Direct Voice", NULL, "IN2RP:VXRP" }, |
548 | 656 | ||
549 | { "MIXINL", "IN1L Switch", "IN1L PGA" }, | 657 | { "MIXINL", "IN1L Switch", "IN1L PGA" }, |
550 | { "MIXINL", "IN2L Switch", "IN2L PGA" }, | 658 | { "MIXINL", "IN2L Switch", "IN2L PGA" }, |
@@ -565,7 +673,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
565 | { "Left Output Mixer", "Right Input Switch", "MIXINR" }, | 673 | { "Left Output Mixer", "Right Input Switch", "MIXINR" }, |
566 | { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, | 674 | { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, |
567 | { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, | 675 | { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, |
568 | { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, | 676 | { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" }, |
569 | { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, | 677 | { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, |
570 | { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, | 678 | { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, |
571 | 679 | ||
@@ -573,7 +681,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
573 | { "Right Output Mixer", "Right Input Switch", "MIXINR" }, | 681 | { "Right Output Mixer", "Right Input Switch", "MIXINR" }, |
574 | { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, | 682 | { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, |
575 | { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, | 683 | { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, |
576 | { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, | 684 | { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" }, |
577 | { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, | 685 | { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, |
578 | { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, | 686 | { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, |
579 | 687 | ||
@@ -626,6 +734,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
626 | { "Headphone PGA", NULL, "Left Headphone Mux" }, | 734 | { "Headphone PGA", NULL, "Left Headphone Mux" }, |
627 | { "Headphone PGA", NULL, "Right Headphone Mux" }, | 735 | { "Headphone PGA", NULL, "Right Headphone Mux" }, |
628 | { "Headphone PGA", NULL, "CLK_SYS" }, | 736 | { "Headphone PGA", NULL, "CLK_SYS" }, |
737 | { "Headphone PGA", NULL, "Headphone Supply" }, | ||
629 | 738 | ||
630 | { "HPOUT1L", NULL, "Headphone PGA" }, | 739 | { "HPOUT1L", NULL, "Headphone PGA" }, |
631 | { "HPOUT1R", NULL, "Headphone PGA" }, | 740 | { "HPOUT1R", NULL, "Headphone PGA" }, |
@@ -738,6 +847,47 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
738 | } | 847 | } |
739 | EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); | 848 | EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); |
740 | 849 | ||
850 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, | ||
851 | int lineout1_diff, int lineout2_diff, | ||
852 | int lineout1fb, int lineout2fb, | ||
853 | int jd_scthr, int jd_thr, int micbias1_lvl, | ||
854 | int micbias2_lvl) | ||
855 | { | ||
856 | if (!lineout1_diff) | ||
857 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | ||
858 | WM8993_LINEOUT1_MODE, | ||
859 | WM8993_LINEOUT1_MODE); | ||
860 | if (!lineout2_diff) | ||
861 | snd_soc_update_bits(codec, WM8993_LINE_MIXER2, | ||
862 | WM8993_LINEOUT2_MODE, | ||
863 | WM8993_LINEOUT2_MODE); | ||
864 | |||
865 | /* If the line outputs are differential then we aren't presenting | ||
866 | * VMID as an output and can disable it. | ||
867 | */ | ||
868 | if (lineout1_diff && lineout2_diff) | ||
869 | codec->idle_bias_off = 1; | ||
870 | |||
871 | if (lineout1fb) | ||
872 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
873 | WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); | ||
874 | |||
875 | if (lineout2fb) | ||
876 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
877 | WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); | ||
878 | |||
879 | snd_soc_update_bits(codec, WM8993_MICBIAS, | ||
880 | WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | | ||
881 | WM8993_MICB1_LVL | WM8993_MICB2_LVL, | ||
882 | jd_scthr << WM8993_JD_SCTHR_SHIFT | | ||
883 | jd_thr << WM8993_JD_THR_SHIFT | | ||
884 | micbias1_lvl | | ||
885 | micbias2_lvl << WM8993_MICB2_LVL_SHIFT); | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); | ||
890 | |||
741 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); | 891 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); |
742 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 892 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
743 | MODULE_LICENSE("GPL"); | 893 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index ec09cb6a2939..e51c16683589 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -18,7 +18,19 @@ struct snd_soc_codec; | |||
18 | 18 | ||
19 | extern const unsigned int wm_hubs_spkmix_tlv[]; | 19 | extern const unsigned int wm_hubs_spkmix_tlv[]; |
20 | 20 | ||
21 | /* This *must* be the first element of the codec->private_data struct */ | ||
22 | struct wm_hubs_data { | ||
23 | int dcs_codes; | ||
24 | int dcs_readback_mode; | ||
25 | int hp_startup_mode; | ||
26 | }; | ||
27 | |||
21 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 28 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
22 | extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); | 29 | extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); |
30 | extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | ||
31 | int lineout1_diff, int lineout2_diff, | ||
32 | int lineout1fb, int lineout2fb, | ||
33 | int jd_scthr, int jd_thr, | ||
34 | int micbias1_lvl, int micbias2_lvl); | ||
23 | 35 | ||
24 | #endif | 36 | #endif |