aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-18 15:59:01 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-18 15:59:01 -0400
commitf72222c74bd642182cc892c99df65cb105c61193 (patch)
tree3e35484b289f6dec19a73d5e56dcbcba846af032 /sound/soc/codecs
parent318b0b8d90326aee6a66c994432eee95c0a9aaea (diff)
parentd3c9e9a1390f8a34da8b69e09fa1afa90f5067f4 (diff)
Merge branch 'topic/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 into upstream/wm8711
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/Kconfig64
-rw-r--r--sound/soc/codecs/Makefile36
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/ad1836.c446
-rw-r--r--sound/soc/codecs/ad1836.h64
-rw-r--r--sound/soc/codecs/ad1938.c682
-rw-r--r--sound/soc/codecs/ad1938.h100
-rw-r--r--sound/soc/codecs/ad1980.c4
-rw-r--r--sound/soc/codecs/ak4535.c16
-rw-r--r--sound/soc/codecs/cs4270.c126
-rw-r--r--sound/soc/codecs/cx20442.c501
-rw-r--r--sound/soc/codecs/cx20442.h20
-rw-r--r--sound/soc/codecs/max9877.c308
-rw-r--r--sound/soc/codecs/max9877.h37
-rw-r--r--sound/soc/codecs/spdif_transciever.c74
-rw-r--r--sound/soc/codecs/spdif_transciever.h17
-rw-r--r--sound/soc/codecs/ssm2602.c29
-rw-r--r--sound/soc/codecs/stac9766.c463
-rw-r--r--sound/soc/codecs/stac9766.h21
-rw-r--r--sound/soc/codecs/tlv320aic23.c16
-rw-r--r--sound/soc/codecs/tlv320aic3x.c22
-rw-r--r--sound/soc/codecs/twl4030.c1316
-rw-r--r--sound/soc/codecs/twl4030.h45
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/uda1380.c313
-rw-r--r--sound/soc/codecs/uda1380.h8
-rw-r--r--sound/soc/codecs/wm8350.c42
-rw-r--r--sound/soc/codecs/wm8350.h1
-rw-r--r--sound/soc/codecs/wm8400.c34
-rw-r--r--sound/soc/codecs/wm8510.c177
-rw-r--r--sound/soc/codecs/wm8523.c699
-rw-r--r--sound/soc/codecs/wm8523.h160
-rw-r--r--sound/soc/codecs/wm8580.c213
-rw-r--r--sound/soc/codecs/wm8728.c111
-rw-r--r--sound/soc/codecs/wm8731.c222
-rw-r--r--sound/soc/codecs/wm8750.c154
-rw-r--r--sound/soc/codecs/wm8753.c47
-rw-r--r--sound/soc/codecs/wm8776.c744
-rw-r--r--sound/soc/codecs/wm8776.h51
-rw-r--r--sound/soc/codecs/wm8900.c351
-rw-r--r--sound/soc/codecs/wm8903.c376
-rw-r--r--sound/soc/codecs/wm8940.c933
-rw-r--r--sound/soc/codecs/wm8940.h104
-rw-r--r--sound/soc/codecs/wm8960.c942
-rw-r--r--sound/soc/codecs/wm8960.h127
-rw-r--r--sound/soc/codecs/wm8961.c1265
-rw-r--r--sound/soc/codecs/wm8961.h866
-rw-r--r--sound/soc/codecs/wm8971.c127
-rw-r--r--sound/soc/codecs/wm8974.c808
-rw-r--r--sound/soc/codecs/wm8974.h99
-rw-r--r--sound/soc/codecs/wm8988.c1069
-rw-r--r--sound/soc/codecs/wm8988.h60
-rw-r--r--sound/soc/codecs/wm8990.c196
-rw-r--r--sound/soc/codecs/wm8993.c1595
-rw-r--r--sound/soc/codecs/wm8993.h2132
-rw-r--r--sound/soc/codecs/wm9081.c1511
-rw-r--r--sound/soc/codecs/wm9081.h787
-rw-r--r--sound/soc/codecs/wm9705.c4
-rw-r--r--sound/soc/codecs/wm9712.c8
-rw-r--r--sound/soc/codecs/wm9713.c48
-rw-r--r--sound/soc/codecs/wm_hubs.c758
-rw-r--r--sound/soc/codecs/wm_hubs.h24
62 files changed, 19847 insertions, 1736 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 663840e67766..a5cfa78eb166 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -12,13 +12,18 @@ config SND_SOC_ALL_CODECS
12 tristate "Build all ASoC CODEC drivers" 12 tristate "Build all ASoC CODEC drivers"
13 select SND_SOC_L3 13 select SND_SOC_L3
14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER
15 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
16 select SND_SOC_AD73311 if I2C 18 select SND_SOC_AD73311 if I2C
17 select SND_SOC_AK4104 if SPI_MASTER 19 select SND_SOC_AK4104 if SPI_MASTER
18 select SND_SOC_AK4535 if I2C 20 select SND_SOC_AK4535 if I2C
19 select SND_SOC_CS4270 if I2C 21 select SND_SOC_CS4270 if I2C
22 select SND_SOC_MAX9877 if I2C
20 select SND_SOC_PCM3008 23 select SND_SOC_PCM3008
24 select SND_SOC_SPDIF
21 select SND_SOC_SSM2602 if I2C 25 select SND_SOC_SSM2602 if I2C
26 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
22 select SND_SOC_TLV320AIC23 if I2C 27 select SND_SOC_TLV320AIC23 if I2C
23 select SND_SOC_TLV320AIC26 if SPI_MASTER 28 select SND_SOC_TLV320AIC26 if SPI_MASTER
24 select SND_SOC_TLV320AIC3X if I2C 29 select SND_SOC_TLV320AIC3X if I2C
@@ -28,16 +33,25 @@ config SND_SOC_ALL_CODECS
28 select SND_SOC_WM8350 if MFD_WM8350 33 select SND_SOC_WM8350 if MFD_WM8350
29 select SND_SOC_WM8400 if MFD_WM8400 34 select SND_SOC_WM8400 if MFD_WM8400
30 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 35 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8523 if I2C
31 select SND_SOC_WM8580 if I2C 37 select SND_SOC_WM8580 if I2C
32 select SND_SOC_WM8711 if I2C 38 select SND_SOC_WM8711 if I2C
33 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 39 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
34 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 40 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
35 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 41 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 42 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
43 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
37 select SND_SOC_WM8900 if I2C 44 select SND_SOC_WM8900 if I2C
38 select SND_SOC_WM8903 if I2C 45 select SND_SOC_WM8903 if I2C
46 select SND_SOC_WM8940 if I2C
47 select SND_SOC_WM8960 if I2C
48 select SND_SOC_WM8961 if I2C
39 select SND_SOC_WM8971 if I2C 49 select SND_SOC_WM8971 if I2C
50 select SND_SOC_WM8974 if I2C
51 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
40 select SND_SOC_WM8990 if I2C 52 select SND_SOC_WM8990 if I2C
53 select SND_SOC_WM8993 if I2C
54 select SND_SOC_WM9081 if I2C
41 select SND_SOC_WM9705 if SND_SOC_AC97_BUS 55 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
42 select SND_SOC_WM9712 if SND_SOC_AC97_BUS 56 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
43 select SND_SOC_WM9713 if SND_SOC_AC97_BUS 57 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
@@ -52,11 +66,21 @@ config SND_SOC_ALL_CODECS
52 66
53 If unsure select "N". 67 If unsure select "N".
54 68
69config SND_SOC_WM_HUBS
70 tristate
71 default y if SND_SOC_WM8993=y
72 default m if SND_SOC_WM8993=m
55 73
56config SND_SOC_AC97_CODEC 74config SND_SOC_AC97_CODEC
57 tristate 75 tristate
58 select SND_AC97_CODEC 76 select SND_AC97_CODEC
59 77
78config SND_SOC_AD1836
79 tristate
80
81config SND_SOC_AD1938
82 tristate
83
60config SND_SOC_AD1980 84config SND_SOC_AD1980
61 tristate 85 tristate
62 86
@@ -81,15 +105,24 @@ config SND_SOC_CS4270_VD33_ERRATA
81 bool 105 bool
82 depends on SND_SOC_CS4270 106 depends on SND_SOC_CS4270
83 107
108config SND_SOC_CX20442
109 tristate
110
84config SND_SOC_L3 111config SND_SOC_L3
85 tristate 112 tristate
86 113
87config SND_SOC_PCM3008 114config SND_SOC_PCM3008
88 tristate 115 tristate
89 116
117config SND_SOC_SPDIF
118 tristate
119
90config SND_SOC_SSM2602 120config SND_SOC_SSM2602
91 tristate 121 tristate
92 122
123config SND_SOC_STAC9766
124 tristate
125
93config SND_SOC_TLV320AIC23 126config SND_SOC_TLV320AIC23
94 tristate 127 tristate
95 128
@@ -118,6 +151,9 @@ config SND_SOC_WM8400
118config SND_SOC_WM8510 151config SND_SOC_WM8510
119 tristate 152 tristate
120 153
154config SND_SOC_WM8523
155 tristate
156
121config SND_SOC_WM8580 157config SND_SOC_WM8580
122 tristate 158 tristate
123 159
@@ -136,18 +172,42 @@ config SND_SOC_WM8750
136config SND_SOC_WM8753 172config SND_SOC_WM8753
137 tristate 173 tristate
138 174
175config SND_SOC_WM8776
176 tristate
177
139config SND_SOC_WM8900 178config SND_SOC_WM8900
140 tristate 179 tristate
141 180
142config SND_SOC_WM8903 181config SND_SOC_WM8903
143 tristate 182 tristate
144 183
184config SND_SOC_WM8940
185 tristate
186
187config SND_SOC_WM8960
188 tristate
189
190config SND_SOC_WM8961
191 tristate
192
145config SND_SOC_WM8971 193config SND_SOC_WM8971
146 tristate 194 tristate
147 195
196config SND_SOC_WM8974
197 tristate
198
199config SND_SOC_WM8988
200 tristate
201
148config SND_SOC_WM8990 202config SND_SOC_WM8990
149 tristate 203 tristate
150 204
205config SND_SOC_WM8993
206 tristate
207
208config SND_SOC_WM9081
209 tristate
210
151config SND_SOC_WM9705 211config SND_SOC_WM9705
152 tristate 212 tristate
153 213
@@ -156,3 +216,7 @@ config SND_SOC_WM9712
156 216
157config SND_SOC_WM9713 217config SND_SOC_WM9713
158 tristate 218 tristate
219
220# Amp
221config SND_SOC_MAX9877
222 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 19950e998b6b..711d8f5887de 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,12 +1,17 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o
2snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
4snd-soc-ak4104-objs := ak4104.o 6snd-soc-ak4104-objs := ak4104.o
5snd-soc-ak4535-objs := ak4535.o 7snd-soc-ak4535-objs := ak4535.o
6snd-soc-cs4270-objs := cs4270.o 8snd-soc-cs4270-objs := cs4270.o
9snd-soc-cx20442-objs := cx20442.o
7snd-soc-l3-objs := l3.o 10snd-soc-l3-objs := l3.o
8snd-soc-pcm3008-objs := pcm3008.o 11snd-soc-pcm3008-objs := pcm3008.o
12snd-soc-spdif-objs := spdif_transciever.o
9snd-soc-ssm2602-objs := ssm2602.o 13snd-soc-ssm2602-objs := ssm2602.o
14snd-soc-stac9766-objs := stac9766.o
10snd-soc-tlv320aic23-objs := tlv320aic23.o 15snd-soc-tlv320aic23-objs := tlv320aic23.o
11snd-soc-tlv320aic26-objs := tlv320aic26.o 16snd-soc-tlv320aic26-objs := tlv320aic26.o
12snd-soc-tlv320aic3x-objs := tlv320aic3x.o 17snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -16,29 +21,47 @@ snd-soc-uda1380-objs := uda1380.o
16snd-soc-wm8350-objs := wm8350.o 21snd-soc-wm8350-objs := wm8350.o
17snd-soc-wm8400-objs := wm8400.o 22snd-soc-wm8400-objs := wm8400.o
18snd-soc-wm8510-objs := wm8510.o 23snd-soc-wm8510-objs := wm8510.o
24snd-soc-wm8523-objs := wm8523.o
19snd-soc-wm8580-objs := wm8580.o 25snd-soc-wm8580-objs := wm8580.o
20snd-soc-wm8711-objs := wm8711.o 26snd-soc-wm8711-objs := wm8711.o
21snd-soc-wm8728-objs := wm8728.o 27snd-soc-wm8728-objs := wm8728.o
22snd-soc-wm8731-objs := wm8731.o 28snd-soc-wm8731-objs := wm8731.o
23snd-soc-wm8750-objs := wm8750.o 29snd-soc-wm8750-objs := wm8750.o
24snd-soc-wm8753-objs := wm8753.o 30snd-soc-wm8753-objs := wm8753.o
31snd-soc-wm8776-objs := wm8776.o
25snd-soc-wm8900-objs := wm8900.o 32snd-soc-wm8900-objs := wm8900.o
26snd-soc-wm8903-objs := wm8903.o 33snd-soc-wm8903-objs := wm8903.o
34snd-soc-wm8940-objs := wm8940.o
35snd-soc-wm8960-objs := wm8960.o
36snd-soc-wm8961-objs := wm8961.o
27snd-soc-wm8971-objs := wm8971.o 37snd-soc-wm8971-objs := wm8971.o
38snd-soc-wm8974-objs := wm8974.o
39snd-soc-wm8988-objs := wm8988.o
28snd-soc-wm8990-objs := wm8990.o 40snd-soc-wm8990-objs := wm8990.o
41snd-soc-wm8993-objs := wm8993.o
42snd-soc-wm9081-objs := wm9081.o
29snd-soc-wm9705-objs := wm9705.o 43snd-soc-wm9705-objs := wm9705.o
30snd-soc-wm9712-objs := wm9712.o 44snd-soc-wm9712-objs := wm9712.o
31snd-soc-wm9713-objs := wm9713.o 45snd-soc-wm9713-objs := wm9713.o
46snd-soc-wm-hubs-objs := wm_hubs.o
47
48# Amp
49snd-soc-max9877-objs := max9877.o
32 50
33obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 51obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
52obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
53obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o
34obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 54obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
35obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 55obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
36obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 56obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
37obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 57obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
38obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 58obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
59obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
39obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 60obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
40obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 61obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
62obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
41obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 63obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
64obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
42obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 65obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
43obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 66obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
44obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 67obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
@@ -48,16 +71,29 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
48obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 71obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
49obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 72obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
50obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 73obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
74obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
51obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 75obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
52obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o 76obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
53obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 77obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
54obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 78obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
55obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 79obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
56obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 80obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
81obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
57obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o 82obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
58obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 83obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
59obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 84obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
85obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o
86obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
87obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
88obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
89obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
60obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 90obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
91obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
92obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
61obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o 93obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
62obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 94obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
63obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 95obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
96obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
97
98# Amp
99obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index b0d4af145b87..932299bb5d1e 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -53,13 +53,13 @@ struct snd_soc_dai ac97_dai = {
53 .channels_min = 1, 53 .channels_min = 1,
54 .channels_max = 2, 54 .channels_max = 2,
55 .rates = STD_AC97_RATES, 55 .rates = STD_AC97_RATES,
56 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 56 .formats = SND_SOC_STD_AC97_FMTS,},
57 .capture = { 57 .capture = {
58 .stream_name = "AC97 Capture", 58 .stream_name = "AC97 Capture",
59 .channels_min = 1, 59 .channels_min = 1,
60 .channels_max = 2, 60 .channels_max = 2,
61 .rates = STD_AC97_RATES, 61 .rates = STD_AC97_RATES,
62 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 62 .formats = SND_SOC_STD_AC97_FMTS,},
63 .ops = &ac97_dai_ops, 63 .ops = &ac97_dai_ops,
64}; 64};
65EXPORT_SYMBOL_GPL(ac97_dai); 65EXPORT_SYMBOL_GPL(ac97_dai);
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
new file mode 100644
index 000000000000..3612bb92df90
--- /dev/null
+++ b/sound/soc/codecs/ad1836.c
@@ -0,0 +1,446 @@
1/*
2 * File: sound/soc/codecs/ad1836.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Aug 04 2009
6 * Description: Driver for AD1836 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/version.h>
22#include <linux/kernel.h>
23#include <linux/device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/initval.h>
28#include <sound/soc.h>
29#include <sound/tlv.h>
30#include <sound/soc-dapm.h>
31#include <linux/spi/spi.h>
32#include "ad1836.h"
33
34/* codec private data */
35struct ad1836_priv {
36 struct snd_soc_codec codec;
37 u16 reg_cache[AD1836_NUM_REGS];
38};
39
40static struct snd_soc_codec *ad1836_codec;
41struct snd_soc_codec_device soc_codec_dev_ad1836;
42static int ad1836_register(struct ad1836_priv *ad1836);
43static void ad1836_unregister(struct ad1836_priv *ad1836);
44
45/*
46 * AD1836 volume/mute/de-emphasis etc. controls
47 */
48static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
49
50static const struct soc_enum ad1836_deemp_enum =
51 SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
52
53static const struct snd_kcontrol_new ad1836_snd_controls[] = {
54 /* DAC volume control */
55 SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL,
56 AD1836_DAC_R1_VOL, 0, 0x3FF, 0),
57 SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL,
58 AD1836_DAC_R2_VOL, 0, 0x3FF, 0),
59 SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL,
60 AD1836_DAC_R3_VOL, 0, 0x3FF, 0),
61
62 /* ADC switch control */
63 SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE,
64 AD1836_ADCR1_MUTE, 1, 1),
65 SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE,
66 AD1836_ADCR2_MUTE, 1, 1),
67
68 /* DAC switch control */
69 SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE,
70 AD1836_DACR1_MUTE, 1, 1),
71 SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE,
72 AD1836_DACR2_MUTE, 1, 1),
73 SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE,
74 AD1836_DACR3_MUTE, 1, 1),
75
76 /* ADC high-pass filter */
77 SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
78 AD1836_ADC_HIGHPASS_FILTER, 1, 0),
79
80 /* DAC de-emphasis */
81 SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
82};
83
84static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = {
85 SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
86 AD1836_DAC_POWERDOWN, 1),
87 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
88 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
89 AD1836_ADC_POWERDOWN, 1, NULL, 0),
90 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
91 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
92 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
93 SND_SOC_DAPM_INPUT("ADC1IN"),
94 SND_SOC_DAPM_INPUT("ADC2IN"),
95};
96
97static const struct snd_soc_dapm_route audio_paths[] = {
98 { "DAC", NULL, "ADC_PWR" },
99 { "ADC", NULL, "ADC_PWR" },
100 { "DAC1OUT", "DAC1 Switch", "DAC" },
101 { "DAC2OUT", "DAC2 Switch", "DAC" },
102 { "DAC3OUT", "DAC3 Switch", "DAC" },
103 { "ADC", "ADC1 Switch", "ADC1IN" },
104 { "ADC", "ADC2 Switch", "ADC2IN" },
105};
106
107/*
108 * DAI ops entries
109 */
110
111static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,
112 unsigned int fmt)
113{
114 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
115 /* at present, we support adc aux mode to interface with
116 * blackfin sport tdm mode
117 */
118 case SND_SOC_DAIFMT_DSP_A:
119 break;
120 default:
121 return -EINVAL;
122 }
123
124 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
125 case SND_SOC_DAIFMT_IB_IF:
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
132 /* ALCLK,ABCLK are both output, AD1836 can only be master */
133 case SND_SOC_DAIFMT_CBM_CFM:
134 break;
135 default:
136 return -EINVAL;
137 }
138
139 return 0;
140}
141
142static int ad1836_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params,
144 struct snd_soc_dai *dai)
145{
146 int word_len = 0;
147
148 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_device *socdev = rtd->socdev;
150 struct snd_soc_codec *codec = socdev->card->codec;
151
152 /* bit size */
153 switch (params_format(params)) {
154 case SNDRV_PCM_FORMAT_S16_LE:
155 word_len = 3;
156 break;
157 case SNDRV_PCM_FORMAT_S20_3LE:
158 word_len = 1;
159 break;
160 case SNDRV_PCM_FORMAT_S24_LE:
161 case SNDRV_PCM_FORMAT_S32_LE:
162 word_len = 0;
163 break;
164 }
165
166 snd_soc_update_bits(codec, AD1836_DAC_CTRL1,
167 AD1836_DAC_WORD_LEN_MASK, word_len);
168
169 snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
170 AD1836_ADC_WORD_LEN_MASK, word_len);
171
172 return 0;
173}
174
175
176/*
177 * interface to read/write ad1836 register
178 */
179#define AD1836_SPI_REG_SHFT 12
180#define AD1836_SPI_READ (1 << 11)
181#define AD1836_SPI_VAL_MSK 0x3FF
182
183/*
184 * write to the ad1836 register space
185 */
186
187static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg,
188 unsigned int value)
189{
190 u16 *reg_cache = codec->reg_cache;
191 int ret = 0;
192
193 if (value != reg_cache[reg]) {
194 unsigned short buf;
195 struct spi_transfer t = {
196 .tx_buf = &buf,
197 .len = 2,
198 };
199 struct spi_message m;
200
201 buf = (reg << AD1836_SPI_REG_SHFT) |
202 (value & AD1836_SPI_VAL_MSK);
203 spi_message_init(&m);
204 spi_message_add_tail(&t, &m);
205 ret = spi_sync(codec->control_data, &m);
206 if (ret == 0)
207 reg_cache[reg] = value;
208 }
209
210 return ret;
211}
212
213/*
214 * read from the ad1836 register space cache
215 */
216static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec,
217 unsigned int reg)
218{
219 u16 *reg_cache = codec->reg_cache;
220
221 if (reg >= codec->reg_cache_size)
222 return -EINVAL;
223
224 return reg_cache[reg];
225}
226
227static int __devinit ad1836_spi_probe(struct spi_device *spi)
228{
229 struct snd_soc_codec *codec;
230 struct ad1836_priv *ad1836;
231
232 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
233 if (ad1836 == NULL)
234 return -ENOMEM;
235
236 codec = &ad1836->codec;
237 codec->control_data = spi;
238 codec->dev = &spi->dev;
239
240 dev_set_drvdata(&spi->dev, ad1836);
241
242 return ad1836_register(ad1836);
243}
244
245static int __devexit ad1836_spi_remove(struct spi_device *spi)
246{
247 struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
248
249 ad1836_unregister(ad1836);
250 return 0;
251}
252
253static struct spi_driver ad1836_spi_driver = {
254 .driver = {
255 .name = "ad1836-spi",
256 .bus = &spi_bus_type,
257 .owner = THIS_MODULE,
258 },
259 .probe = ad1836_spi_probe,
260 .remove = __devexit_p(ad1836_spi_remove),
261};
262
263static struct snd_soc_dai_ops ad1836_dai_ops = {
264 .hw_params = ad1836_hw_params,
265 .set_fmt = ad1836_set_dai_fmt,
266};
267
268/* codec DAI instance */
269struct snd_soc_dai ad1836_dai = {
270 .name = "AD1836",
271 .playback = {
272 .stream_name = "Playback",
273 .channels_min = 2,
274 .channels_max = 6,
275 .rates = SNDRV_PCM_RATE_48000,
276 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
277 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
278 },
279 .capture = {
280 .stream_name = "Capture",
281 .channels_min = 2,
282 .channels_max = 4,
283 .rates = SNDRV_PCM_RATE_48000,
284 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
285 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
286 },
287 .ops = &ad1836_dai_ops,
288};
289EXPORT_SYMBOL_GPL(ad1836_dai);
290
291static int ad1836_register(struct ad1836_priv *ad1836)
292{
293 int ret;
294 struct snd_soc_codec *codec = &ad1836->codec;
295
296 if (ad1836_codec) {
297 dev_err(codec->dev, "Another ad1836 is registered\n");
298 return -EINVAL;
299 }
300
301 mutex_init(&codec->mutex);
302 INIT_LIST_HEAD(&codec->dapm_widgets);
303 INIT_LIST_HEAD(&codec->dapm_paths);
304 codec->private_data = ad1836;
305 codec->reg_cache = ad1836->reg_cache;
306 codec->reg_cache_size = AD1836_NUM_REGS;
307 codec->name = "AD1836";
308 codec->owner = THIS_MODULE;
309 codec->dai = &ad1836_dai;
310 codec->num_dai = 1;
311 codec->write = ad1836_write_reg;
312 codec->read = ad1836_read_reg_cache;
313 INIT_LIST_HEAD(&codec->dapm_widgets);
314 INIT_LIST_HEAD(&codec->dapm_paths);
315
316 ad1836_dai.dev = codec->dev;
317 ad1836_codec = codec;
318
319 /* default setting for ad1836 */
320 /* de-emphasis: 48kHz, power-on dac */
321 codec->write(codec, AD1836_DAC_CTRL1, 0x300);
322 /* unmute dac channels */
323 codec->write(codec, AD1836_DAC_CTRL2, 0x0);
324 /* high-pass filter enable, power-on adc */
325 codec->write(codec, AD1836_ADC_CTRL1, 0x100);
326 /* unmute adc channles, adc aux mode */
327 codec->write(codec, AD1836_ADC_CTRL2, 0x180);
328 /* left/right diff:PGA/MUX */
329 codec->write(codec, AD1836_ADC_CTRL3, 0x3A);
330 /* volume */
331 codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF);
332 codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF);
333 codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF);
334 codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF);
335 codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF);
336 codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF);
337
338 ret = snd_soc_register_codec(codec);
339 if (ret != 0) {
340 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
341 kfree(ad1836);
342 return ret;
343 }
344
345 ret = snd_soc_register_dai(&ad1836_dai);
346 if (ret != 0) {
347 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
348 snd_soc_unregister_codec(codec);
349 kfree(ad1836);
350 return ret;
351 }
352
353 return 0;
354}
355
356static void ad1836_unregister(struct ad1836_priv *ad1836)
357{
358 snd_soc_unregister_dai(&ad1836_dai);
359 snd_soc_unregister_codec(&ad1836->codec);
360 kfree(ad1836);
361 ad1836_codec = NULL;
362}
363
364static int ad1836_probe(struct platform_device *pdev)
365{
366 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
367 struct snd_soc_codec *codec;
368 int ret = 0;
369
370 if (ad1836_codec == NULL) {
371 dev_err(&pdev->dev, "Codec device not registered\n");
372 return -ENODEV;
373 }
374
375 socdev->card->codec = ad1836_codec;
376 codec = ad1836_codec;
377
378 /* register pcms */
379 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
380 if (ret < 0) {
381 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
382 goto pcm_err;
383 }
384
385 snd_soc_add_controls(codec, ad1836_snd_controls,
386 ARRAY_SIZE(ad1836_snd_controls));
387 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
388 ARRAY_SIZE(ad1836_dapm_widgets));
389 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
390 snd_soc_dapm_new_widgets(codec);
391
392 ret = snd_soc_init_card(socdev);
393 if (ret < 0) {
394 dev_err(codec->dev, "failed to register card: %d\n", ret);
395 goto card_err;
396 }
397
398 return ret;
399
400card_err:
401 snd_soc_free_pcms(socdev);
402 snd_soc_dapm_free(socdev);
403pcm_err:
404 return ret;
405}
406
407/* power down chip */
408static int ad1836_remove(struct platform_device *pdev)
409{
410 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
411
412 snd_soc_free_pcms(socdev);
413 snd_soc_dapm_free(socdev);
414
415 return 0;
416}
417
418struct snd_soc_codec_device soc_codec_dev_ad1836 = {
419 .probe = ad1836_probe,
420 .remove = ad1836_remove,
421};
422EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
423
424static int __init ad1836_init(void)
425{
426 int ret;
427
428 ret = spi_register_driver(&ad1836_spi_driver);
429 if (ret != 0) {
430 printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n",
431 ret);
432 }
433
434 return ret;
435}
436module_init(ad1836_init);
437
438static void __exit ad1836_exit(void)
439{
440 spi_unregister_driver(&ad1836_spi_driver);
441}
442module_exit(ad1836_exit);
443
444MODULE_DESCRIPTION("ASoC ad1836 driver");
445MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
446MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
new file mode 100644
index 000000000000..7660ee6973c0
--- /dev/null
+++ b/sound/soc/codecs/ad1836.h
@@ -0,0 +1,64 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: Aug 04, 2009
7 * Description: definitions for AD1836 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __AD1836_H__
20#define __AD1836_H__
21
22#define AD1836_DAC_CTRL1 0
23#define AD1836_DAC_POWERDOWN 2
24#define AD1836_DAC_SERFMT_MASK 0xE0
25#define AD1836_DAC_SERFMT_PCK256 (0x4 << 5)
26#define AD1836_DAC_SERFMT_PCK128 (0x5 << 5)
27#define AD1836_DAC_WORD_LEN_MASK 0x18
28
29#define AD1836_DAC_CTRL2 1
30#define AD1836_DACL1_MUTE 0
31#define AD1836_DACR1_MUTE 1
32#define AD1836_DACL2_MUTE 2
33#define AD1836_DACR2_MUTE 3
34#define AD1836_DACL3_MUTE 4
35#define AD1836_DACR3_MUTE 5
36
37#define AD1836_DAC_L1_VOL 2
38#define AD1836_DAC_R1_VOL 3
39#define AD1836_DAC_L2_VOL 4
40#define AD1836_DAC_R2_VOL 5
41#define AD1836_DAC_L3_VOL 6
42#define AD1836_DAC_R3_VOL 7
43
44#define AD1836_ADC_CTRL1 12
45#define AD1836_ADC_POWERDOWN 7
46#define AD1836_ADC_HIGHPASS_FILTER 8
47
48#define AD1836_ADC_CTRL2 13
49#define AD1836_ADCL1_MUTE 0
50#define AD1836_ADCR1_MUTE 1
51#define AD1836_ADCL2_MUTE 2
52#define AD1836_ADCR2_MUTE 3
53#define AD1836_ADC_WORD_LEN_MASK 0x30
54#define AD1836_ADC_SERFMT_MASK (7 << 6)
55#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6)
56#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6)
57
58#define AD1836_ADC_CTRL3 14
59
60#define AD1836_NUM_REGS 16
61
62extern struct snd_soc_dai ad1836_dai;
63extern struct snd_soc_codec_device soc_codec_dev_ad1836;
64#endif
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
new file mode 100644
index 000000000000..e62b27701a49
--- /dev/null
+++ b/sound/soc/codecs/ad1938.c
@@ -0,0 +1,682 @@
1/*
2 * File: sound/soc/codecs/ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: June 04 2009
6 * Description: Driver for AD1938 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/version.h>
32#include <linux/kernel.h>
33#include <linux/device.h>
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/initval.h>
38#include <sound/soc.h>
39#include <sound/tlv.h>
40#include <sound/soc-dapm.h>
41#include <linux/spi/spi.h>
42#include "ad1938.h"
43
44/* codec private data */
45struct ad1938_priv {
46 struct snd_soc_codec codec;
47 u8 reg_cache[AD1938_NUM_REGS];
48};
49
50static struct snd_soc_codec *ad1938_codec;
51struct snd_soc_codec_device soc_codec_dev_ad1938;
52static int ad1938_register(struct ad1938_priv *ad1938);
53static void ad1938_unregister(struct ad1938_priv *ad1938);
54
55/*
56 * AD1938 volume/mute/de-emphasis etc. controls
57 */
58static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
59
60static const struct soc_enum ad1938_deemp_enum =
61 SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp);
62
63static const struct snd_kcontrol_new ad1938_snd_controls[] = {
64 /* DAC volume control */
65 SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL,
66 AD1938_DAC_R1_VOL, 0, 0xFF, 1),
67 SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL,
68 AD1938_DAC_R2_VOL, 0, 0xFF, 1),
69 SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL,
70 AD1938_DAC_R3_VOL, 0, 0xFF, 1),
71 SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL,
72 AD1938_DAC_R4_VOL, 0, 0xFF, 1),
73
74 /* ADC switch control */
75 SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE,
76 AD1938_ADCR1_MUTE, 1, 1),
77 SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE,
78 AD1938_ADCR2_MUTE, 1, 1),
79
80 /* DAC switch control */
81 SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE,
82 AD1938_DACR1_MUTE, 1, 1),
83 SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE,
84 AD1938_DACR2_MUTE, 1, 1),
85 SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE,
86 AD1938_DACR3_MUTE, 1, 1),
87 SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE,
88 AD1938_DACR4_MUTE, 1, 1),
89
90 /* ADC high-pass filter */
91 SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0,
92 AD1938_ADC_HIGHPASS_FILTER, 1, 0),
93
94 /* DAC de-emphasis */
95 SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum),
96};
97
98static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = {
99 SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1),
100 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
101 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0),
102 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
103 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
104 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
105 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
106 SND_SOC_DAPM_INPUT("ADC1IN"),
107 SND_SOC_DAPM_INPUT("ADC2IN"),
108};
109
110static const struct snd_soc_dapm_route audio_paths[] = {
111 { "DAC", NULL, "ADC_PWR" },
112 { "ADC", NULL, "ADC_PWR" },
113 { "DAC1OUT", "DAC1 Switch", "DAC" },
114 { "DAC2OUT", "DAC2 Switch", "DAC" },
115 { "DAC3OUT", "DAC3 Switch", "DAC" },
116 { "DAC4OUT", "DAC4 Switch", "DAC" },
117 { "ADC", "ADC1 Switch", "ADC1IN" },
118 { "ADC", "ADC2 Switch", "ADC2IN" },
119};
120
121/*
122 * DAI ops entries
123 */
124
125static int ad1938_mute(struct snd_soc_dai *dai, int mute)
126{
127 struct snd_soc_codec *codec = dai->codec;
128 int reg;
129
130 reg = codec->read(codec, AD1938_DAC_CTRL2);
131 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
132 (~AD1938_DAC_MASTER_MUTE);
133 codec->write(codec, AD1938_DAC_CTRL2, reg);
134
135 return 0;
136}
137
138static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd)
139{
140 int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
141 reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg |
142 AD1938_PLL_POWERDOWN;
143 codec->write(codec, AD1938_PLL_CLK_CTRL0, reg);
144
145 return 0;
146}
147
148static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
149 unsigned int mask, int slots, int width)
150{
151 struct snd_soc_codec *codec = dai->codec;
152 int dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
153 int adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
154
155 dac_reg &= ~AD1938_DAC_CHAN_MASK;
156 adc_reg &= ~AD1938_ADC_CHAN_MASK;
157
158 switch (slots) {
159 case 2:
160 dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
161 adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
162 break;
163 case 4:
164 dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
165 adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
166 break;
167 case 8:
168 dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
169 adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
170 break;
171 case 16:
172 dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
173 adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
174 break;
175 default:
176 return -EINVAL;
177 }
178
179 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
180 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
181
182 return 0;
183}
184
185static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
186 unsigned int fmt)
187{
188 struct snd_soc_codec *codec = codec_dai->codec;
189 int adc_reg, dac_reg;
190
191 adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
192 dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
193
194 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
195 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
196 */
197 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
198 case SND_SOC_DAIFMT_I2S:
199 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
200 adc_reg |= AD1938_ADC_SERFMT_TDM;
201 break;
202 case SND_SOC_DAIFMT_DSP_A:
203 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
204 adc_reg |= AD1938_ADC_SERFMT_AUX;
205 break;
206 default:
207 return -EINVAL;
208 }
209
210 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
211 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
212 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
213 adc_reg &= ~AD1938_ADC_BCLK_INV;
214 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
215 dac_reg &= ~AD1938_DAC_BCLK_INV;
216 break;
217 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
218 adc_reg |= AD1938_ADC_LEFT_HIGH;
219 adc_reg &= ~AD1938_ADC_BCLK_INV;
220 dac_reg |= AD1938_DAC_LEFT_HIGH;
221 dac_reg &= ~AD1938_DAC_BCLK_INV;
222 break;
223 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
224 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
225 adc_reg |= AD1938_ADC_BCLK_INV;
226 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
227 dac_reg |= AD1938_DAC_BCLK_INV;
228 break;
229
230 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
231 adc_reg |= AD1938_ADC_LEFT_HIGH;
232 adc_reg |= AD1938_ADC_BCLK_INV;
233 dac_reg |= AD1938_DAC_LEFT_HIGH;
234 dac_reg |= AD1938_DAC_BCLK_INV;
235 break;
236 default:
237 return -EINVAL;
238 }
239
240 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
241 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
242 adc_reg |= AD1938_ADC_LCR_MASTER;
243 adc_reg |= AD1938_ADC_BCLK_MASTER;
244 dac_reg |= AD1938_DAC_LCR_MASTER;
245 dac_reg |= AD1938_DAC_BCLK_MASTER;
246 break;
247 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
248 adc_reg |= AD1938_ADC_LCR_MASTER;
249 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
250 dac_reg |= AD1938_DAC_LCR_MASTER;
251 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
252 break;
253 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
254 adc_reg &= ~AD1938_ADC_LCR_MASTER;
255 adc_reg |= AD1938_ADC_BCLK_MASTER;
256 dac_reg &= ~AD1938_DAC_LCR_MASTER;
257 dac_reg |= AD1938_DAC_BCLK_MASTER;
258 break;
259 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
260 adc_reg &= ~AD1938_ADC_LCR_MASTER;
261 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
262 dac_reg &= ~AD1938_DAC_LCR_MASTER;
263 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
264 break;
265 default:
266 return -EINVAL;
267 }
268
269 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
270 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
271
272 return 0;
273}
274
275static int ad1938_hw_params(struct snd_pcm_substream *substream,
276 struct snd_pcm_hw_params *params,
277 struct snd_soc_dai *dai)
278{
279 int word_len = 0, reg = 0;
280
281 struct snd_soc_pcm_runtime *rtd = substream->private_data;
282 struct snd_soc_device *socdev = rtd->socdev;
283 struct snd_soc_codec *codec = socdev->card->codec;
284
285 /* bit size */
286 switch (params_format(params)) {
287 case SNDRV_PCM_FORMAT_S16_LE:
288 word_len = 3;
289 break;
290 case SNDRV_PCM_FORMAT_S20_3LE:
291 word_len = 1;
292 break;
293 case SNDRV_PCM_FORMAT_S24_LE:
294 case SNDRV_PCM_FORMAT_S32_LE:
295 word_len = 0;
296 break;
297 }
298
299 reg = codec->read(codec, AD1938_DAC_CTRL2);
300 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
301 codec->write(codec, AD1938_DAC_CTRL2, reg);
302
303 reg = codec->read(codec, AD1938_ADC_CTRL1);
304 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
305 codec->write(codec, AD1938_ADC_CTRL1, reg);
306
307 return 0;
308}
309
310static int ad1938_set_bias_level(struct snd_soc_codec *codec,
311 enum snd_soc_bias_level level)
312{
313 switch (level) {
314 case SND_SOC_BIAS_ON:
315 ad1938_pll_powerctrl(codec, 1);
316 break;
317 case SND_SOC_BIAS_PREPARE:
318 break;
319 case SND_SOC_BIAS_STANDBY:
320 case SND_SOC_BIAS_OFF:
321 ad1938_pll_powerctrl(codec, 0);
322 break;
323 }
324 codec->bias_level = level;
325 return 0;
326}
327
328/*
329 * interface to read/write ad1938 register
330 */
331
332#define AD1938_SPI_ADDR 0x4
333#define AD1938_SPI_READ 0x1
334#define AD1938_SPI_BUFLEN 3
335
336/*
337 * write to the ad1938 register space
338 */
339
340static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
341 unsigned int value)
342{
343 u8 *reg_cache = codec->reg_cache;
344 int ret = 0;
345
346 if (value != reg_cache[reg]) {
347 uint8_t buf[AD1938_SPI_BUFLEN];
348 struct spi_transfer t = {
349 .tx_buf = buf,
350 .len = AD1938_SPI_BUFLEN,
351 };
352 struct spi_message m;
353
354 buf[0] = AD1938_SPI_ADDR << 1;
355 buf[1] = reg;
356 buf[2] = value;
357 spi_message_init(&m);
358 spi_message_add_tail(&t, &m);
359 ret = spi_sync(codec->control_data, &m);
360 if (ret == 0)
361 reg_cache[reg] = value;
362 }
363
364 return ret;
365}
366
367/*
368 * read from the ad1938 register space cache
369 */
370
371static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
372 unsigned int reg)
373{
374 u8 *reg_cache = codec->reg_cache;
375
376 if (reg >= codec->reg_cache_size)
377 return -EINVAL;
378
379 return reg_cache[reg];
380}
381
382/*
383 * read from the ad1938 register space
384 */
385
386static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
387 unsigned int reg)
388{
389 char w_buf[AD1938_SPI_BUFLEN];
390 char r_buf[AD1938_SPI_BUFLEN];
391 int ret;
392
393 struct spi_transfer t = {
394 .tx_buf = w_buf,
395 .rx_buf = r_buf,
396 .len = AD1938_SPI_BUFLEN,
397 };
398 struct spi_message m;
399
400 w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
401 w_buf[1] = reg;
402 w_buf[2] = 0;
403
404 spi_message_init(&m);
405 spi_message_add_tail(&t, &m);
406 ret = spi_sync(codec->control_data, &m);
407 if (ret == 0)
408 return r_buf[2];
409 else
410 return -EIO;
411}
412
413static int ad1938_fill_cache(struct snd_soc_codec *codec)
414{
415 int i;
416 u8 *reg_cache = codec->reg_cache;
417 struct spi_device *spi = codec->control_data;
418
419 for (i = 0; i < codec->reg_cache_size; i++) {
420 int ret = ad1938_read_reg(codec, i);
421 if (ret == -EIO) {
422 dev_err(&spi->dev, "AD1938 SPI read failure\n");
423 return ret;
424 }
425 reg_cache[i] = ret;
426 }
427
428 return 0;
429}
430
431static int __devinit ad1938_spi_probe(struct spi_device *spi)
432{
433 struct snd_soc_codec *codec;
434 struct ad1938_priv *ad1938;
435
436 ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
437 if (ad1938 == NULL)
438 return -ENOMEM;
439
440 codec = &ad1938->codec;
441 codec->control_data = spi;
442 codec->dev = &spi->dev;
443
444 dev_set_drvdata(&spi->dev, ad1938);
445
446 return ad1938_register(ad1938);
447}
448
449static int __devexit ad1938_spi_remove(struct spi_device *spi)
450{
451 struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
452
453 ad1938_unregister(ad1938);
454 return 0;
455}
456
457static struct spi_driver ad1938_spi_driver = {
458 .driver = {
459 .name = "ad1938",
460 .bus = &spi_bus_type,
461 .owner = THIS_MODULE,
462 },
463 .probe = ad1938_spi_probe,
464 .remove = __devexit_p(ad1938_spi_remove),
465};
466
467static struct snd_soc_dai_ops ad1938_dai_ops = {
468 .hw_params = ad1938_hw_params,
469 .digital_mute = ad1938_mute,
470 .set_tdm_slot = ad1938_set_tdm_slot,
471 .set_fmt = ad1938_set_dai_fmt,
472};
473
474/* codec DAI instance */
475struct snd_soc_dai ad1938_dai = {
476 .name = "AD1938",
477 .playback = {
478 .stream_name = "Playback",
479 .channels_min = 2,
480 .channels_max = 8,
481 .rates = SNDRV_PCM_RATE_48000,
482 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
483 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
484 },
485 .capture = {
486 .stream_name = "Capture",
487 .channels_min = 2,
488 .channels_max = 4,
489 .rates = SNDRV_PCM_RATE_48000,
490 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
491 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
492 },
493 .ops = &ad1938_dai_ops,
494};
495EXPORT_SYMBOL_GPL(ad1938_dai);
496
497static int ad1938_register(struct ad1938_priv *ad1938)
498{
499 int ret;
500 struct snd_soc_codec *codec = &ad1938->codec;
501
502 if (ad1938_codec) {
503 dev_err(codec->dev, "Another ad1938 is registered\n");
504 return -EINVAL;
505 }
506
507 mutex_init(&codec->mutex);
508 INIT_LIST_HEAD(&codec->dapm_widgets);
509 INIT_LIST_HEAD(&codec->dapm_paths);
510 codec->private_data = ad1938;
511 codec->reg_cache = ad1938->reg_cache;
512 codec->reg_cache_size = AD1938_NUM_REGS;
513 codec->name = "AD1938";
514 codec->owner = THIS_MODULE;
515 codec->dai = &ad1938_dai;
516 codec->num_dai = 1;
517 codec->write = ad1938_write_reg;
518 codec->read = ad1938_read_reg_cache;
519 INIT_LIST_HEAD(&codec->dapm_widgets);
520 INIT_LIST_HEAD(&codec->dapm_paths);
521
522 ad1938_dai.dev = codec->dev;
523 ad1938_codec = codec;
524
525 /* default setting for ad1938 */
526
527 /* unmute dac channels */
528 codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
529 /* de-emphasis: 48kHz, powedown dac */
530 codec->write(codec, AD1938_DAC_CTRL2, 0x1A);
531 /* powerdown dac, dac in tdm mode */
532 codec->write(codec, AD1938_DAC_CTRL0, 0x41);
533 /* high-pass filter enable */
534 codec->write(codec, AD1938_ADC_CTRL0, 0x3);
535 /* sata delay=1, adc aux mode */
536 codec->write(codec, AD1938_ADC_CTRL1, 0x43);
537 /* pll input: mclki/xi */
538 codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
539 codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
540
541 ad1938_fill_cache(codec);
542
543 ret = snd_soc_register_codec(codec);
544 if (ret != 0) {
545 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
546 kfree(ad1938);
547 return ret;
548 }
549
550 ret = snd_soc_register_dai(&ad1938_dai);
551 if (ret != 0) {
552 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
553 snd_soc_unregister_codec(codec);
554 kfree(ad1938);
555 return ret;
556 }
557
558 return 0;
559}
560
561static void ad1938_unregister(struct ad1938_priv *ad1938)
562{
563 ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF);
564 snd_soc_unregister_dai(&ad1938_dai);
565 snd_soc_unregister_codec(&ad1938->codec);
566 kfree(ad1938);
567 ad1938_codec = NULL;
568}
569
570static int ad1938_probe(struct platform_device *pdev)
571{
572 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
573 struct snd_soc_codec *codec;
574 int ret = 0;
575
576 if (ad1938_codec == NULL) {
577 dev_err(&pdev->dev, "Codec device not registered\n");
578 return -ENODEV;
579 }
580
581 socdev->card->codec = ad1938_codec;
582 codec = ad1938_codec;
583
584 /* register pcms */
585 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
586 if (ret < 0) {
587 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
588 goto pcm_err;
589 }
590
591 snd_soc_add_controls(codec, ad1938_snd_controls,
592 ARRAY_SIZE(ad1938_snd_controls));
593 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
594 ARRAY_SIZE(ad1938_dapm_widgets));
595 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
596 snd_soc_dapm_new_widgets(codec);
597
598 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
599
600 ret = snd_soc_init_card(socdev);
601 if (ret < 0) {
602 dev_err(codec->dev, "failed to register card: %d\n", ret);
603 goto card_err;
604 }
605
606 return ret;
607
608card_err:
609 snd_soc_free_pcms(socdev);
610 snd_soc_dapm_free(socdev);
611pcm_err:
612 return ret;
613}
614
615/* power down chip */
616static int ad1938_remove(struct platform_device *pdev)
617{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619
620 snd_soc_free_pcms(socdev);
621 snd_soc_dapm_free(socdev);
622
623 return 0;
624}
625
626#ifdef CONFIG_PM
627static int ad1938_suspend(struct platform_device *pdev,
628 pm_message_t state)
629{
630 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
631 struct snd_soc_codec *codec = socdev->card->codec;
632
633 ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF);
634 return 0;
635}
636
637static int ad1938_resume(struct platform_device *pdev)
638{
639 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
640 struct snd_soc_codec *codec = socdev->card->codec;
641
642 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
643 ad1938_set_bias_level(codec, SND_SOC_BIAS_ON);
644
645 return 0;
646}
647#else
648#define ad1938_suspend NULL
649#define ad1938_resume NULL
650#endif
651
652struct snd_soc_codec_device soc_codec_dev_ad1938 = {
653 .probe = ad1938_probe,
654 .remove = ad1938_remove,
655 .suspend = ad1938_suspend,
656 .resume = ad1938_resume,
657};
658EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
659
660static int __init ad1938_init(void)
661{
662 int ret;
663
664 ret = spi_register_driver(&ad1938_spi_driver);
665 if (ret != 0) {
666 printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
667 ret);
668 }
669
670 return ret;
671}
672module_init(ad1938_init);
673
674static void __exit ad1938_exit(void)
675{
676 spi_unregister_driver(&ad1938_spi_driver);
677}
678module_exit(ad1938_exit);
679
680MODULE_DESCRIPTION("ASoC ad1938 driver");
681MODULE_AUTHOR("Barry Song ");
682MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1938.h b/sound/soc/codecs/ad1938.h
new file mode 100644
index 000000000000..fe3c48cd2d5b
--- /dev/null
+++ b/sound/soc/codecs/ad1938.h
@@ -0,0 +1,100 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: May 25, 2009
7 * Description: definitions for AD1938 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#ifndef __AD1938_H__
30#define __AD1938_H__
31
32#define AD1938_PLL_CLK_CTRL0 0
33#define AD1938_PLL_POWERDOWN 0x01
34#define AD1938_PLL_CLK_CTRL1 1
35#define AD1938_DAC_CTRL0 2
36#define AD1938_DAC_POWERDOWN 0x01
37#define AD1938_DAC_SERFMT_MASK 0xC0
38#define AD1938_DAC_SERFMT_STEREO (0 << 6)
39#define AD1938_DAC_SERFMT_TDM (1 << 6)
40#define AD1938_DAC_CTRL1 3
41#define AD1938_DAC_2_CHANNELS 0
42#define AD1938_DAC_4_CHANNELS 1
43#define AD1938_DAC_8_CHANNELS 2
44#define AD1938_DAC_16_CHANNELS 3
45#define AD1938_DAC_CHAN_SHFT 1
46#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT)
47#define AD1938_DAC_LCR_MASTER (1 << 4)
48#define AD1938_DAC_BCLK_MASTER (1 << 5)
49#define AD1938_DAC_LEFT_HIGH (1 << 3)
50#define AD1938_DAC_BCLK_INV (1 << 7)
51#define AD1938_DAC_CTRL2 4
52#define AD1938_DAC_WORD_LEN_MASK 0xC
53#define AD1938_DAC_MASTER_MUTE 1
54#define AD1938_DAC_CHNL_MUTE 5
55#define AD1938_DACL1_MUTE 0
56#define AD1938_DACR1_MUTE 1
57#define AD1938_DACL2_MUTE 2
58#define AD1938_DACR2_MUTE 3
59#define AD1938_DACL3_MUTE 4
60#define AD1938_DACR3_MUTE 5
61#define AD1938_DACL4_MUTE 6
62#define AD1938_DACR4_MUTE 7
63#define AD1938_DAC_L1_VOL 6
64#define AD1938_DAC_R1_VOL 7
65#define AD1938_DAC_L2_VOL 8
66#define AD1938_DAC_R2_VOL 9
67#define AD1938_DAC_L3_VOL 10
68#define AD1938_DAC_R3_VOL 11
69#define AD1938_DAC_L4_VOL 12
70#define AD1938_DAC_R4_VOL 13
71#define AD1938_ADC_CTRL0 14
72#define AD1938_ADC_POWERDOWN 0x01
73#define AD1938_ADC_HIGHPASS_FILTER 1
74#define AD1938_ADCL1_MUTE 2
75#define AD1938_ADCR1_MUTE 3
76#define AD1938_ADCL2_MUTE 4
77#define AD1938_ADCR2_MUTE 5
78#define AD1938_ADC_CTRL1 15
79#define AD1938_ADC_SERFMT_MASK 0x60
80#define AD1938_ADC_SERFMT_STEREO (0 << 5)
81#define AD1938_ADC_SERFMT_TDM (1 << 2)
82#define AD1938_ADC_SERFMT_AUX (2 << 5)
83#define AD1938_ADC_WORD_LEN_MASK 0x3
84#define AD1938_ADC_CTRL2 16
85#define AD1938_ADC_2_CHANNELS 0
86#define AD1938_ADC_4_CHANNELS 1
87#define AD1938_ADC_8_CHANNELS 2
88#define AD1938_ADC_16_CHANNELS 3
89#define AD1938_ADC_CHAN_SHFT 4
90#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT)
91#define AD1938_ADC_LCR_MASTER (1 << 3)
92#define AD1938_ADC_BCLK_MASTER (1 << 6)
93#define AD1938_ADC_LEFT_HIGH (1 << 2)
94#define AD1938_ADC_BCLK_INV (1 << 1)
95
96#define AD1938_NUM_REGS 17
97
98extern struct snd_soc_dai ad1938_dai;
99extern struct snd_soc_codec_device soc_codec_dev_ad1938;
100#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index ddb3b08ac23c..d7440a982d22 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -137,13 +137,13 @@ struct snd_soc_dai ad1980_dai = {
137 .channels_min = 2, 137 .channels_min = 2,
138 .channels_max = 6, 138 .channels_max = 6,
139 .rates = SNDRV_PCM_RATE_48000, 139 .rates = SNDRV_PCM_RATE_48000,
140 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 140 .formats = SND_SOC_STD_AC97_FMTS, },
141 .capture = { 141 .capture = {
142 .stream_name = "Capture", 142 .stream_name = "Capture",
143 .channels_min = 2, 143 .channels_min = 2,
144 .channels_max = 2, 144 .channels_max = 2,
145 .rates = SNDRV_PCM_RATE_48000, 145 .rates = SNDRV_PCM_RATE_48000,
146 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 146 .formats = SND_SOC_STD_AC97_FMTS, },
147}; 147};
148EXPORT_SYMBOL_GPL(ad1980_dai); 148EXPORT_SYMBOL_GPL(ad1980_dai);
149 149
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index dd3380202766..0abec0d29a96 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -59,21 +59,6 @@ static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
59 return cache[reg]; 59 return cache[reg];
60} 60}
61 61
62static inline unsigned int ak4535_read(struct snd_soc_codec *codec,
63 unsigned int reg)
64{
65 u8 data;
66 data = reg;
67
68 if (codec->hw_write(codec->control_data, &data, 1) != 1)
69 return -EIO;
70
71 if (codec->hw_read(codec->control_data, &data, 1) != 1)
72 return -EIO;
73
74 return data;
75};
76
77/* 62/*
78 * write ak4535 register cache 63 * write ak4535 register cache
79 */ 64 */
@@ -635,7 +620,6 @@ static int ak4535_probe(struct platform_device *pdev)
635#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 620#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
636 if (setup->i2c_address) { 621 if (setup->i2c_address) {
637 codec->hw_write = (hw_write_t)i2c_master_send; 622 codec->hw_write = (hw_write_t)i2c_master_send;
638 codec->hw_read = (hw_read_t)i2c_master_recv;
639 ret = ak4535_add_i2c_device(pdev, setup); 623 ret = ak4535_add_i2c_device(pdev, setup);
640 } 624 }
641#endif 625#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 7fa09a387622..ca1e24a8f12a 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -18,7 +18,7 @@
18 * - The machine driver's 'startup' function must call 18 * - The machine driver's 'startup' function must call
19 * cs4270_set_dai_sysclk() with the value of MCLK. 19 * cs4270_set_dai_sysclk() with the value of MCLK.
20 * - Only I2S and left-justified modes are supported 20 * - Only I2S and left-justified modes are supported
21 * - Power management is not supported 21 * - Power management is supported
22 */ 22 */
23 23
24#include <linux/module.h> 24#include <linux/module.h>
@@ -27,6 +27,7 @@
27#include <sound/soc.h> 27#include <sound/soc.h>
28#include <sound/initval.h> 28#include <sound/initval.h>
29#include <linux/i2c.h> 29#include <linux/i2c.h>
30#include <linux/delay.h>
30 31
31#include "cs4270.h" 32#include "cs4270.h"
32 33
@@ -56,6 +57,7 @@
56#define CS4270_FIRSTREG 0x01 57#define CS4270_FIRSTREG 0x01
57#define CS4270_LASTREG 0x08 58#define CS4270_LASTREG 0x08
58#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) 59#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1)
60#define CS4270_I2C_INCR 0x80
59 61
60/* Bit masks for the CS4270 registers */ 62/* Bit masks for the CS4270 registers */
61#define CS4270_CHIPID_ID 0xF0 63#define CS4270_CHIPID_ID 0xF0
@@ -64,6 +66,8 @@
64#define CS4270_PWRCTL_PDN_ADC 0x20 66#define CS4270_PWRCTL_PDN_ADC 0x20
65#define CS4270_PWRCTL_PDN_DAC 0x02 67#define CS4270_PWRCTL_PDN_DAC 0x02
66#define CS4270_PWRCTL_PDN 0x01 68#define CS4270_PWRCTL_PDN 0x01
69#define CS4270_PWRCTL_PDN_ALL \
70 (CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | CS4270_PWRCTL_PDN)
67#define CS4270_MODE_SPEED_MASK 0x30 71#define CS4270_MODE_SPEED_MASK 0x30
68#define CS4270_MODE_1X 0x00 72#define CS4270_MODE_1X 0x00
69#define CS4270_MODE_2X 0x10 73#define CS4270_MODE_2X 0x10
@@ -109,6 +113,7 @@ struct cs4270_private {
109 unsigned int mclk; /* Input frequency of the MCLK pin */ 113 unsigned int mclk; /* Input frequency of the MCLK pin */
110 unsigned int mode; /* The mode (I2S or left-justified) */ 114 unsigned int mode; /* The mode (I2S or left-justified) */
111 unsigned int slave_mode; 115 unsigned int slave_mode;
116 unsigned int manual_mute;
112}; 117};
113 118
114/** 119/**
@@ -295,7 +300,7 @@ static int cs4270_fill_cache(struct snd_soc_codec *codec)
295 s32 length; 300 s32 length;
296 301
297 length = i2c_smbus_read_i2c_block_data(i2c_client, 302 length = i2c_smbus_read_i2c_block_data(i2c_client,
298 CS4270_FIRSTREG | 0x80, CS4270_NUMREGS, cache); 303 CS4270_FIRSTREG | CS4270_I2C_INCR, CS4270_NUMREGS, cache);
299 304
300 if (length != CS4270_NUMREGS) { 305 if (length != CS4270_NUMREGS) {
301 dev_err(codec->dev, "i2c read failure, addr=0x%x\n", 306 dev_err(codec->dev, "i2c read failure, addr=0x%x\n",
@@ -453,7 +458,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
453} 458}
454 459
455/** 460/**
456 * cs4270_mute - enable/disable the CS4270 external mute 461 * cs4270_dai_mute - enable/disable the CS4270 external mute
457 * @dai: the SOC DAI 462 * @dai: the SOC DAI
458 * @mute: 0 = disable mute, 1 = enable mute 463 * @mute: 0 = disable mute, 1 = enable mute
459 * 464 *
@@ -462,21 +467,52 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
462 * board does not have the MUTEA or MUTEB pins connected to such circuitry, 467 * board does not have the MUTEA or MUTEB pins connected to such circuitry,
463 * then this function will do nothing. 468 * then this function will do nothing.
464 */ 469 */
465static int cs4270_mute(struct snd_soc_dai *dai, int mute) 470static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute)
466{ 471{
467 struct snd_soc_codec *codec = dai->codec; 472 struct snd_soc_codec *codec = dai->codec;
473 struct cs4270_private *cs4270 = codec->private_data;
468 int reg6; 474 int reg6;
469 475
470 reg6 = snd_soc_read(codec, CS4270_MUTE); 476 reg6 = snd_soc_read(codec, CS4270_MUTE);
471 477
472 if (mute) 478 if (mute)
473 reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; 479 reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B;
474 else 480 else {
475 reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); 481 reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B);
482 reg6 |= cs4270->manual_mute;
483 }
476 484
477 return snd_soc_write(codec, CS4270_MUTE, reg6); 485 return snd_soc_write(codec, CS4270_MUTE, reg6);
478} 486}
479 487
488/**
489 * cs4270_soc_put_mute - put callback for the 'Master Playback switch'
490 * alsa control.
491 * @kcontrol: mixer control
492 * @ucontrol: control element information
493 *
494 * This function basically passes the arguments on to the generic
495 * snd_soc_put_volsw() function and saves the mute information in
496 * our private data structure. This is because we want to prevent
497 * cs4270_dai_mute() neglecting the user's decision to manually
498 * mute the codec's output.
499 *
500 * Returns 0 for success.
501 */
502static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol,
503 struct snd_ctl_elem_value *ucontrol)
504{
505 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
506 struct cs4270_private *cs4270 = codec->private_data;
507 int left = !ucontrol->value.integer.value[0];
508 int right = !ucontrol->value.integer.value[1];
509
510 cs4270->manual_mute = (left ? CS4270_MUTE_DAC_A : 0) |
511 (right ? CS4270_MUTE_DAC_B : 0);
512
513 return snd_soc_put_volsw(kcontrol, ucontrol);
514}
515
480/* A list of non-DAPM controls that the CS4270 supports */ 516/* A list of non-DAPM controls that the CS4270 supports */
481static const struct snd_kcontrol_new cs4270_snd_controls[] = { 517static const struct snd_kcontrol_new cs4270_snd_controls[] = {
482 SOC_DOUBLE_R("Master Playback Volume", 518 SOC_DOUBLE_R("Master Playback Volume",
@@ -486,7 +522,9 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
486 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), 522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
487 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), 523 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
488 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), 524 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
489 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0) 525 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
526 SOC_DOUBLE_EXT("Master Playback Switch", CS4270_MUTE, 0, 1, 1, 1,
527 snd_soc_get_volsw, cs4270_soc_put_mute),
490}; 528};
491 529
492/* 530/*
@@ -506,7 +544,7 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
506 .hw_params = cs4270_hw_params, 544 .hw_params = cs4270_hw_params,
507 .set_sysclk = cs4270_set_dai_sysclk, 545 .set_sysclk = cs4270_set_dai_sysclk,
508 .set_fmt = cs4270_set_dai_fmt, 546 .set_fmt = cs4270_set_dai_fmt,
509 .digital_mute = cs4270_mute, 547 .digital_mute = cs4270_dai_mute,
510}; 548};
511 549
512struct snd_soc_dai cs4270_dai = { 550struct snd_soc_dai cs4270_dai = {
@@ -753,6 +791,74 @@ static struct i2c_device_id cs4270_id[] = {
753}; 791};
754MODULE_DEVICE_TABLE(i2c, cs4270_id); 792MODULE_DEVICE_TABLE(i2c, cs4270_id);
755 793
794#ifdef CONFIG_PM
795
796/* This suspend/resume implementation can handle both - a simple standby
797 * where the codec remains powered, and a full suspend, where the voltage
798 * domain the codec is connected to is teared down and/or any other hardware
799 * reset condition is asserted.
800 *
801 * The codec's own power saving features are enabled in the suspend callback,
802 * and all registers are written back to the hardware when resuming.
803 */
804
805static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
806{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
808 struct snd_soc_codec *codec = &cs4270->codec;
809
810 return snd_soc_suspend_device(codec->dev);
811}
812
813static int cs4270_i2c_resume(struct i2c_client *client)
814{
815 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
816 struct snd_soc_codec *codec = &cs4270->codec;
817
818 return snd_soc_resume_device(codec->dev);
819}
820
821static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
822{
823 struct snd_soc_codec *codec = cs4270_codec;
824 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
825
826 return snd_soc_write(codec, CS4270_PWRCTL, reg);
827}
828
829static int cs4270_soc_resume(struct platform_device *pdev)
830{
831 struct snd_soc_codec *codec = cs4270_codec;
832 struct i2c_client *i2c_client = codec->control_data;
833 int reg;
834
835 /* In case the device was put to hard reset during sleep, we need to
836 * wait 500ns here before any I2C communication. */
837 ndelay(500);
838
839 /* first restore the entire register cache ... */
840 for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
841 u8 val = snd_soc_read(codec, reg);
842
843 if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
844 dev_err(codec->dev, "i2c write failed\n");
845 return -EIO;
846 }
847 }
848
849 /* ... then disable the power-down bits */
850 reg = snd_soc_read(codec, CS4270_PWRCTL);
851 reg &= ~CS4270_PWRCTL_PDN_ALL;
852
853 return snd_soc_write(codec, CS4270_PWRCTL, reg);
854}
855#else
856#define cs4270_i2c_suspend NULL
857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL
860#endif /* CONFIG_PM */
861
756/* 862/*
757 * cs4270_i2c_driver - I2C device identification 863 * cs4270_i2c_driver - I2C device identification
758 * 864 *
@@ -767,6 +873,8 @@ static struct i2c_driver cs4270_i2c_driver = {
767 .id_table = cs4270_id, 873 .id_table = cs4270_id,
768 .probe = cs4270_i2c_probe, 874 .probe = cs4270_i2c_probe,
769 .remove = cs4270_i2c_remove, 875 .remove = cs4270_i2c_remove,
876 .suspend = cs4270_i2c_suspend,
877 .resume = cs4270_i2c_resume,
770}; 878};
771 879
772/* 880/*
@@ -777,7 +885,9 @@ static struct i2c_driver cs4270_i2c_driver = {
777 */ 885 */
778struct snd_soc_codec_device soc_codec_device_cs4270 = { 886struct snd_soc_codec_device soc_codec_device_cs4270 = {
779 .probe = cs4270_probe, 887 .probe = cs4270_probe,
780 .remove = cs4270_remove 888 .remove = cs4270_remove,
889 .suspend = cs4270_soc_suspend,
890 .resume = cs4270_soc_resume,
781}; 891};
782EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); 892EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
783 893
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
new file mode 100644
index 000000000000..38eac9c866e1
--- /dev/null
+++ b/sound/soc/codecs/cx20442.c
@@ -0,0 +1,501 @@
1/*
2 * cx20442.c -- CX20442 ALSA Soc Audio driver
3 *
4 * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * Initially based on sound/soc/codecs/wm8400.c
7 * Copyright 2008, 2009 Wolfson Microelectronics PLC.
8 * Author: Mark Brown <broonie@opensource.wolfsonmicro.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#include <linux/tty.h>
17
18#include <sound/core.h>
19#include <sound/initval.h>
20#include <sound/soc-dapm.h>
21
22#include "cx20442.h"
23
24
25struct cx20442_priv {
26 struct snd_soc_codec codec;
27 u8 reg_cache[1];
28};
29
30#define CX20442_PM 0x0
31
32#define CX20442_TELIN 0
33#define CX20442_TELOUT 1
34#define CX20442_MIC 2
35#define CX20442_SPKOUT 3
36#define CX20442_AGC 4
37
38static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = {
39 SND_SOC_DAPM_OUTPUT("TELOUT"),
40 SND_SOC_DAPM_OUTPUT("SPKOUT"),
41 SND_SOC_DAPM_OUTPUT("AGCOUT"),
42
43 SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
44
45 SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0),
46 SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0),
47 SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
48
49 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
50 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
51
52 SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
53
54 SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0),
55 SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0),
56
57 SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
58
59 SND_SOC_DAPM_INPUT("TELIN"),
60 SND_SOC_DAPM_INPUT("MIC"),
61 SND_SOC_DAPM_INPUT("AGCIN"),
62};
63
64static const struct snd_soc_dapm_route cx20442_audio_map[] = {
65 {"TELOUT", NULL, "TELOUT Amp"},
66
67 {"SPKOUT", NULL, "SPKOUT Mixer"},
68 {"SPKOUT Mixer", NULL, "SPKOUT Amp"},
69
70 {"TELOUT Amp", NULL, "DAC"},
71 {"SPKOUT Amp", NULL, "DAC"},
72
73 {"SPKOUT Mixer", NULL, "SPKOUT AGC"},
74 {"SPKOUT AGC", NULL, "AGCIN"},
75
76 {"AGCOUT", NULL, "MIC AGC"},
77 {"MIC AGC", NULL, "MIC"},
78
79 {"MIC Bias", NULL, "MIC"},
80 {"Input Mixer", NULL, "MIC Bias"},
81
82 {"TELIN Bias", NULL, "TELIN"},
83 {"Input Mixer", NULL, "TELIN Bias"},
84
85 {"ADC", NULL, "Input Mixer"},
86};
87
88static int cx20442_add_widgets(struct snd_soc_codec *codec)
89{
90 snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets,
91 ARRAY_SIZE(cx20442_dapm_widgets));
92
93 snd_soc_dapm_add_routes(codec, cx20442_audio_map,
94 ARRAY_SIZE(cx20442_audio_map));
95
96 snd_soc_dapm_new_widgets(codec);
97 return 0;
98}
99
100static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
101 unsigned int reg)
102{
103 u8 *reg_cache = codec->reg_cache;
104
105 if (reg >= codec->reg_cache_size)
106 return -EINVAL;
107
108 return reg_cache[reg];
109}
110
111enum v253_vls {
112 V253_VLS_NONE = 0,
113 V253_VLS_T,
114 V253_VLS_L,
115 V253_VLS_LT,
116 V253_VLS_S,
117 V253_VLS_ST,
118 V253_VLS_M,
119 V253_VLS_MST,
120 V253_VLS_S1,
121 V253_VLS_S1T,
122 V253_VLS_MS1T,
123 V253_VLS_M1,
124 V253_VLS_M1ST,
125 V253_VLS_M1S1T,
126 V253_VLS_H,
127 V253_VLS_HT,
128 V253_VLS_MS,
129 V253_VLS_MS1,
130 V253_VLS_M1S,
131 V253_VLS_M1S1,
132 V253_VLS_TEST,
133};
134
135static int cx20442_pm_to_v253_vls(u8 value)
136{
137 switch (value & ~(1 << CX20442_AGC)) {
138 case 0:
139 return V253_VLS_T;
140 case (1 << CX20442_SPKOUT):
141 case (1 << CX20442_MIC):
142 case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
143 return V253_VLS_M1S1;
144 case (1 << CX20442_TELOUT):
145 case (1 << CX20442_TELIN):
146 case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN):
147 return V253_VLS_L;
148 case (1 << CX20442_TELOUT) | (1 << CX20442_MIC):
149 return V253_VLS_NONE;
150 }
151 return -EINVAL;
152}
153static int cx20442_pm_to_v253_vsp(u8 value)
154{
155 switch (value & ~(1 << CX20442_AGC)) {
156 case (1 << CX20442_SPKOUT):
157 case (1 << CX20442_MIC):
158 case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
159 return (bool)(value & (1 << CX20442_AGC));
160 }
161 return (value & (1 << CX20442_AGC)) ? -EINVAL : 0;
162}
163
164static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
165 unsigned int value)
166{
167 u8 *reg_cache = codec->reg_cache;
168 int vls, vsp, old, len;
169 char buf[18];
170
171 if (reg >= codec->reg_cache_size)
172 return -EINVAL;
173
174 /* hw_write and control_data pointers required for talking to the modem
175 * are expected to be set by the line discipline initialization code */
176 if (!codec->hw_write || !codec->control_data)
177 return -EIO;
178
179 old = reg_cache[reg];
180 reg_cache[reg] = value;
181
182 vls = cx20442_pm_to_v253_vls(value);
183 if (vls < 0)
184 return vls;
185
186 vsp = cx20442_pm_to_v253_vsp(value);
187 if (vsp < 0)
188 return vsp;
189
190 if ((vls == V253_VLS_T) ||
191 (vls == cx20442_pm_to_v253_vls(old))) {
192 if (vsp == cx20442_pm_to_v253_vsp(old))
193 return 0;
194 len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp);
195 } else if (vsp == cx20442_pm_to_v253_vsp(old))
196 len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls);
197 else
198 len = snprintf(buf, ARRAY_SIZE(buf),
199 "at+vls=%d;+vsp=%d\r", vls, vsp);
200
201 if (unlikely(len > (ARRAY_SIZE(buf) - 1)))
202 return -ENOMEM;
203
204 dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
205 if (codec->hw_write(codec->control_data, buf, len) != len)
206 return -EIO;
207
208 return 0;
209}
210
211
212/* Moved up here as line discipline referres it during initialization */
213static struct snd_soc_codec *cx20442_codec;
214
215
216/*
217 * Line discpline related code
218 *
219 * Any of the callback functions below can be used in two ways:
220 * 1) registerd by a machine driver as one of line discipline operations,
221 * 2) called from a machine's provided line discipline callback function
222 * in case when extra machine specific code must be run as well.
223 */
224
225/* Modem init: echo off, digital speaker off, quiet off, voice mode */
226static const char *v253_init = "ate0m0q0+fclass=8\r";
227
228/* Line discipline .open() */
229static int v253_open(struct tty_struct *tty)
230{
231 struct snd_soc_codec *codec = cx20442_codec;
232 int ret, len = strlen(v253_init);
233
234 /* Doesn't make sense without write callback */
235 if (!tty->ops->write)
236 return -EINVAL;
237
238 /* Pass the codec structure address for use by other ldisc callbacks */
239 tty->disc_data = codec;
240
241 if (tty->ops->write(tty, v253_init, len) != len) {
242 ret = -EIO;
243 goto err;
244 }
245 /* Actual setup will be performed after the modem responds. */
246 return 0;
247err:
248 tty->disc_data = NULL;
249 return ret;
250}
251
252/* Line discipline .close() */
253static void v253_close(struct tty_struct *tty)
254{
255 struct snd_soc_codec *codec = tty->disc_data;
256
257 tty->disc_data = NULL;
258
259 if (!codec)
260 return;
261
262 /* Prevent the codec driver from further accessing the modem */
263 codec->hw_write = NULL;
264 codec->control_data = NULL;
265 codec->pop_time = 0;
266}
267
268/* Line discipline .hangup() */
269static int v253_hangup(struct tty_struct *tty)
270{
271 v253_close(tty);
272 return 0;
273}
274
275/* Line discipline .receive_buf() */
276static void v253_receive(struct tty_struct *tty,
277 const unsigned char *cp, char *fp, int count)
278{
279 struct snd_soc_codec *codec = tty->disc_data;
280
281 if (!codec)
282 return;
283
284 if (!codec->control_data) {
285 /* First modem response, complete setup procedure */
286
287 /* Set up codec driver access to modem controls */
288 codec->control_data = tty;
289 codec->hw_write = (hw_write_t)tty->ops->write;
290 codec->pop_time = 1;
291 }
292}
293
294/* Line discipline .write_wakeup() */
295static void v253_wakeup(struct tty_struct *tty)
296{
297}
298
299struct tty_ldisc_ops v253_ops = {
300 .magic = TTY_LDISC_MAGIC,
301 .name = "cx20442",
302 .owner = THIS_MODULE,
303 .open = v253_open,
304 .close = v253_close,
305 .hangup = v253_hangup,
306 .receive_buf = v253_receive,
307 .write_wakeup = v253_wakeup,
308};
309EXPORT_SYMBOL_GPL(v253_ops);
310
311
312/*
313 * Codec DAI
314 */
315
316struct snd_soc_dai cx20442_dai = {
317 .name = "CX20442",
318 .playback = {
319 .stream_name = "Playback",
320 .channels_min = 1,
321 .channels_max = 1,
322 .rates = SNDRV_PCM_RATE_8000,
323 .formats = SNDRV_PCM_FMTBIT_S16_LE,
324 },
325 .capture = {
326 .stream_name = "Capture",
327 .channels_min = 1,
328 .channels_max = 1,
329 .rates = SNDRV_PCM_RATE_8000,
330 .formats = SNDRV_PCM_FMTBIT_S16_LE,
331 },
332};
333EXPORT_SYMBOL_GPL(cx20442_dai);
334
335static int cx20442_codec_probe(struct platform_device *pdev)
336{
337 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
338 struct snd_soc_codec *codec;
339 int ret;
340
341 if (!cx20442_codec) {
342 dev_err(&pdev->dev, "cx20442 not yet discovered\n");
343 return -ENODEV;
344 }
345 codec = cx20442_codec;
346
347 socdev->card->codec = codec;
348
349 /* register pcms */
350 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
351 if (ret < 0) {
352 dev_err(&pdev->dev, "failed to create pcms\n");
353 goto pcm_err;
354 }
355
356 cx20442_add_widgets(codec);
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
366card_err:
367 snd_soc_free_pcms(socdev);
368 snd_soc_dapm_free(socdev);
369pcm_err:
370 return ret;
371}
372
373/* power down chip */
374static int cx20442_codec_remove(struct platform_device *pdev)
375{
376 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
377
378 snd_soc_free_pcms(socdev);
379 snd_soc_dapm_free(socdev);
380
381 return 0;
382}
383
384struct snd_soc_codec_device cx20442_codec_dev = {
385 .probe = cx20442_codec_probe,
386 .remove = cx20442_codec_remove,
387};
388EXPORT_SYMBOL_GPL(cx20442_codec_dev);
389
390static int cx20442_register(struct cx20442_priv *cx20442)
391{
392 struct snd_soc_codec *codec = &cx20442->codec;
393 int ret;
394
395 mutex_init(&codec->mutex);
396 INIT_LIST_HEAD(&codec->dapm_widgets);
397 INIT_LIST_HEAD(&codec->dapm_paths);
398
399 codec->name = "CX20442";
400 codec->owner = THIS_MODULE;
401 codec->private_data = cx20442;
402
403 codec->dai = &cx20442_dai;
404 codec->num_dai = 1;
405
406 codec->reg_cache = &cx20442->reg_cache;
407 codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
408 codec->read = cx20442_read_reg_cache;
409 codec->write = cx20442_write;
410
411 codec->bias_level = SND_SOC_BIAS_OFF;
412
413 cx20442_dai.dev = codec->dev;
414
415 cx20442_codec = codec;
416
417 ret = snd_soc_register_codec(codec);
418 if (ret != 0) {
419 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
420 goto err;
421 }
422
423 ret = snd_soc_register_dai(&cx20442_dai);
424 if (ret != 0) {
425 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
426 goto err_codec;
427 }
428
429 return 0;
430
431err_codec:
432 snd_soc_unregister_codec(codec);
433err:
434 cx20442_codec = NULL;
435 kfree(cx20442);
436 return ret;
437}
438
439static void cx20442_unregister(struct cx20442_priv *cx20442)
440{
441 snd_soc_unregister_dai(&cx20442_dai);
442 snd_soc_unregister_codec(&cx20442->codec);
443
444 cx20442_codec = NULL;
445 kfree(cx20442);
446}
447
448static int cx20442_platform_probe(struct platform_device *pdev)
449{
450 struct cx20442_priv *cx20442;
451 struct snd_soc_codec *codec;
452
453 cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
454 if (cx20442 == NULL)
455 return -ENOMEM;
456
457 codec = &cx20442->codec;
458
459 codec->control_data = NULL;
460 codec->hw_write = NULL;
461 codec->pop_time = 0;
462
463 codec->dev = &pdev->dev;
464 platform_set_drvdata(pdev, cx20442);
465
466 return cx20442_register(cx20442);
467}
468
469static int __exit cx20442_platform_remove(struct platform_device *pdev)
470{
471 struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
472
473 cx20442_unregister(cx20442);
474 return 0;
475}
476
477static struct platform_driver cx20442_platform_driver = {
478 .driver = {
479 .name = "cx20442",
480 .owner = THIS_MODULE,
481 },
482 .probe = cx20442_platform_probe,
483 .remove = __exit_p(cx20442_platform_remove),
484};
485
486static int __init cx20442_init(void)
487{
488 return platform_driver_register(&cx20442_platform_driver);
489}
490module_init(cx20442_init);
491
492static void __exit cx20442_exit(void)
493{
494 platform_driver_unregister(&cx20442_platform_driver);
495}
496module_exit(cx20442_exit);
497
498MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
499MODULE_AUTHOR("Janusz Krzysztofik");
500MODULE_LICENSE("GPL");
501MODULE_ALIAS("platform:cx20442");
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
new file mode 100644
index 000000000000..688a5eb62e17
--- /dev/null
+++ b/sound/soc/codecs/cx20442.h
@@ -0,0 +1,20 @@
1/*
2 * cx20442.h -- audio driver for CX20442
3 *
4 * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 */
12
13#ifndef _CX20442_CODEC_H
14#define _CX20442_CODEC_H
15
16extern struct snd_soc_dai cx20442_dai;
17extern struct snd_soc_codec_device cx20442_codec_dev;
18extern struct tty_ldisc_ops v253_ops;
19
20#endif
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
new file mode 100644
index 000000000000..9e7e964a5fa3
--- /dev/null
+++ b/sound/soc/codecs/max9877.c
@@ -0,0 +1,308 @@
1/*
2 * max9877.c -- amp driver for max9877
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 <sound/soc.h>
18#include <sound/tlv.h>
19
20#include "max9877.h"
21
22static struct i2c_client *i2c;
23
24static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
25
26static void max9877_write_regs(void)
27{
28 unsigned int i;
29 u8 data[6];
30
31 data[0] = MAX9877_INPUT_MODE;
32 for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
33 data[i + 1] = max9877_regs[i];
34
35 if (i2c_master_send(i2c, data, 6) != 6)
36 dev_err(&i2c->dev, "i2c write failed\n");
37}
38
39static int max9877_get_reg(struct snd_kcontrol *kcontrol,
40 struct snd_ctl_elem_value *ucontrol)
41{
42 struct soc_mixer_control *mc =
43 (struct soc_mixer_control *)kcontrol->private_value;
44 unsigned int reg = mc->reg;
45 unsigned int shift = mc->shift;
46 unsigned int mask = mc->max;
47 unsigned int invert = mc->invert;
48
49 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
50
51 if (invert)
52 ucontrol->value.integer.value[0] =
53 mask - ucontrol->value.integer.value[0];
54
55 return 0;
56}
57
58static int max9877_set_reg(struct snd_kcontrol *kcontrol,
59 struct snd_ctl_elem_value *ucontrol)
60{
61 struct soc_mixer_control *mc =
62 (struct soc_mixer_control *)kcontrol->private_value;
63 unsigned int reg = mc->reg;
64 unsigned int shift = mc->shift;
65 unsigned int mask = mc->max;
66 unsigned int invert = mc->invert;
67 unsigned int val = (ucontrol->value.integer.value[0] & mask);
68
69 if (invert)
70 val = mask - val;
71
72 if (((max9877_regs[reg] >> shift) & mask) == val)
73 return 0;
74
75 max9877_regs[reg] &= ~(mask << shift);
76 max9877_regs[reg] |= val << shift;
77 max9877_write_regs();
78
79 return 1;
80}
81
82static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
83 struct snd_ctl_elem_value *ucontrol)
84{
85 struct soc_mixer_control *mc =
86 (struct soc_mixer_control *)kcontrol->private_value;
87 unsigned int reg = mc->reg;
88 unsigned int reg2 = mc->rreg;
89 unsigned int shift = mc->shift;
90 unsigned int mask = mc->max;
91
92 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
93 ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
94
95 return 0;
96}
97
98static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 struct soc_mixer_control *mc =
102 (struct soc_mixer_control *)kcontrol->private_value;
103 unsigned int reg = mc->reg;
104 unsigned int reg2 = mc->rreg;
105 unsigned int shift = mc->shift;
106 unsigned int mask = mc->max;
107 unsigned int val = (ucontrol->value.integer.value[0] & mask);
108 unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
109 unsigned int change = 1;
110
111 if (((max9877_regs[reg] >> shift) & mask) == val)
112 change = 0;
113
114 if (((max9877_regs[reg2] >> shift) & mask) == val2)
115 change = 0;
116
117 if (change) {
118 max9877_regs[reg] &= ~(mask << shift);
119 max9877_regs[reg] |= val << shift;
120 max9877_regs[reg2] &= ~(mask << shift);
121 max9877_regs[reg2] |= val2 << shift;
122 max9877_write_regs();
123 }
124
125 return change;
126}
127
128static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
129 struct snd_ctl_elem_value *ucontrol)
130{
131 u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
132
133 if (value)
134 value -= 1;
135
136 ucontrol->value.integer.value[0] = value;
137 return 0;
138}
139
140static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
141 struct snd_ctl_elem_value *ucontrol)
142{
143 u8 value = ucontrol->value.integer.value[0];
144
145 value += 1;
146
147 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
148 return 0;
149
150 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
151 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
152 max9877_write_regs();
153 return 1;
154}
155
156static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
157 struct snd_ctl_elem_value *ucontrol)
158{
159 u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
160
161 value = value >> MAX9877_OSC_OFFSET;
162
163 ucontrol->value.integer.value[0] = value;
164 return 0;
165}
166
167static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
168 struct snd_ctl_elem_value *ucontrol)
169{
170 u8 value = ucontrol->value.integer.value[0];
171
172 value = value << MAX9877_OSC_OFFSET;
173 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
174 return 0;
175
176 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
177 max9877_regs[MAX9877_OUTPUT_MODE] |= value;
178 max9877_write_regs();
179 return 1;
180}
181
182static const unsigned int max9877_pgain_tlv[] = {
183 TLV_DB_RANGE_HEAD(2),
184 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
185 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
186};
187
188static const unsigned int max9877_output_tlv[] = {
189 TLV_DB_RANGE_HEAD(4),
190 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
191 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
192 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
193 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
194};
195
196static const char *max9877_out_mode[] = {
197 "INA -> SPK",
198 "INA -> HP",
199 "INA -> SPK and HP",
200 "INB -> SPK",
201 "INB -> HP",
202 "INB -> SPK and HP",
203 "INA + INB -> SPK",
204 "INA + INB -> HP",
205 "INA + INB -> SPK and HP",
206};
207
208static const char *max9877_osc_mode[] = {
209 "1176KHz",
210 "1100KHz",
211 "700KHz",
212};
213
214static const struct soc_enum max9877_enum[] = {
215 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
216 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
217};
218
219static const struct snd_kcontrol_new max9877_controls[] = {
220 SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
221 MAX9877_INPUT_MODE, 0, 2, 0,
222 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
223 SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
224 MAX9877_INPUT_MODE, 2, 2, 0,
225 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
226 SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
227 MAX9877_SPK_VOLUME, 0, 31, 0,
228 max9877_get_reg, max9877_set_reg, max9877_output_tlv),
229 SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
230 MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
231 max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
232 SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
233 MAX9877_INPUT_MODE, 4, 1, 1,
234 max9877_get_reg, max9877_set_reg),
235 SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
236 MAX9877_INPUT_MODE, 5, 1, 1,
237 max9877_get_reg, max9877_set_reg),
238 SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
239 MAX9877_INPUT_MODE, 6, 1, 0,
240 max9877_get_reg, max9877_set_reg),
241 SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
242 MAX9877_OUTPUT_MODE, 6, 1, 0,
243 max9877_get_reg, max9877_set_reg),
244 SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
245 MAX9877_OUTPUT_MODE, 7, 1, 1,
246 max9877_get_reg, max9877_set_reg),
247 SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
248 max9877_get_out_mode, max9877_set_out_mode),
249 SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
250 max9877_get_osc_mode, max9877_set_osc_mode),
251};
252
253/* This function is called from ASoC machine driver */
254int max9877_add_controls(struct snd_soc_codec *codec)
255{
256 return snd_soc_add_controls(codec, max9877_controls,
257 ARRAY_SIZE(max9877_controls));
258}
259EXPORT_SYMBOL_GPL(max9877_add_controls);
260
261static int __devinit max9877_i2c_probe(struct i2c_client *client,
262 const struct i2c_device_id *id)
263{
264 i2c = client;
265
266 max9877_write_regs();
267
268 return 0;
269}
270
271static __devexit int max9877_i2c_remove(struct i2c_client *client)
272{
273 i2c = NULL;
274
275 return 0;
276}
277
278static const struct i2c_device_id max9877_i2c_id[] = {
279 { "max9877", 0 },
280 { }
281};
282MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
283
284static struct i2c_driver max9877_i2c_driver = {
285 .driver = {
286 .name = "max9877",
287 .owner = THIS_MODULE,
288 },
289 .probe = max9877_i2c_probe,
290 .remove = __devexit_p(max9877_i2c_remove),
291 .id_table = max9877_i2c_id,
292};
293
294static int __init max9877_init(void)
295{
296 return i2c_add_driver(&max9877_i2c_driver);
297}
298module_init(max9877_init);
299
300static void __exit max9877_exit(void)
301{
302 i2c_del_driver(&max9877_i2c_driver);
303}
304module_exit(max9877_exit);
305
306MODULE_DESCRIPTION("ASoC MAX9877 amp driver");
307MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
308MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max9877.h b/sound/soc/codecs/max9877.h
new file mode 100644
index 000000000000..6da72290ac58
--- /dev/null
+++ b/sound/soc/codecs/max9877.h
@@ -0,0 +1,37 @@
1/*
2 * max9877.h -- amp driver for max9877
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 _MAX9877_H
15#define _MAX9877_H
16
17#define MAX9877_INPUT_MODE 0x00
18#define MAX9877_SPK_VOLUME 0x01
19#define MAX9877_HPL_VOLUME 0x02
20#define MAX9877_HPR_VOLUME 0x03
21#define MAX9877_OUTPUT_MODE 0x04
22
23/* MAX9877_INPUT_MODE */
24#define MAX9877_INB (1 << 4)
25#define MAX9877_INA (1 << 5)
26#define MAX9877_ZCD (1 << 6)
27
28/* MAX9877_OUTPUT_MODE */
29#define MAX9877_OUTMODE_MASK (15 << 0)
30#define MAX9877_OSC_MASK (3 << 4)
31#define MAX9877_OSC_OFFSET 4
32#define MAX9877_BYPASS (1 << 6)
33#define MAX9877_SHDN (1 << 7)
34
35extern int max9877_add_controls(struct snd_soc_codec *codec);
36
37#endif
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
new file mode 100644
index 000000000000..a63191141052
--- /dev/null
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -0,0 +1,74 @@
1/*
2 * ALSA SoC SPDIF DIT driver
3 *
4 * This driver is used by controllers which can operate in DIT (SPDI/F) where
5 * no codec is needed. This file provides stub codec that can be used
6 * in these configurations. TI DaVinci Audio controller uses this driver.
7 *
8 * Author: Steve Chen, <schen@mvista.com>
9 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
10 * Copyright: (C) 2009 Texas Instruments, India
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <sound/soc.h>
20#include <sound/pcm.h>
21
22#include "spdif_transciever.h"
23
24MODULE_LICENSE("GPL");
25
26#define STUB_RATES SNDRV_PCM_RATE_8000_96000
27#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
28
29struct snd_soc_dai dit_stub_dai = {
30 .name = "DIT",
31 .playback = {
32 .stream_name = "Playback",
33 .channels_min = 1,
34 .channels_max = 384,
35 .rates = STUB_RATES,
36 .formats = STUB_FORMATS,
37 },
38};
39EXPORT_SYMBOL_GPL(dit_stub_dai);
40
41static int spdif_dit_probe(struct platform_device *pdev)
42{
43 dit_stub_dai.dev = &pdev->dev;
44 return snd_soc_register_dai(&dit_stub_dai);
45}
46
47static int spdif_dit_remove(struct platform_device *pdev)
48{
49 snd_soc_unregister_dai(&dit_stub_dai);
50 return 0;
51}
52
53static struct platform_driver spdif_dit_driver = {
54 .probe = spdif_dit_probe,
55 .remove = spdif_dit_remove,
56 .driver = {
57 .name = "spdif-dit",
58 .owner = THIS_MODULE,
59 },
60};
61
62static int __init dit_modinit(void)
63{
64 return platform_driver_register(&spdif_dit_driver);
65}
66
67static void __exit dit_exit(void)
68{
69 platform_driver_unregister(&spdif_dit_driver);
70}
71
72module_init(dit_modinit);
73module_exit(dit_exit);
74
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
new file mode 100644
index 000000000000..296f2eb6c4ef
--- /dev/null
+++ b/sound/soc/codecs/spdif_transciever.h
@@ -0,0 +1,17 @@
1/*
2 * ALSA SoC DIT/DIR driver header
3 *
4 * Author: Steve Chen, <schen@mvista.com>
5 * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef CODEC_STUBS_H
13#define CODEC_STUBS_H
14
15extern struct snd_soc_dai dit_stub_dai;
16
17#endif /* CODEC_STUBS_H */
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 87f606c76822..c550750c79c0 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -336,15 +336,17 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
336 master_runtime->sample_bits, 336 master_runtime->sample_bits,
337 master_runtime->rate); 337 master_runtime->rate);
338 338
339 snd_pcm_hw_constraint_minmax(substream->runtime, 339 if (master_runtime->rate != 0)
340 SNDRV_PCM_HW_PARAM_RATE, 340 snd_pcm_hw_constraint_minmax(substream->runtime,
341 master_runtime->rate, 341 SNDRV_PCM_HW_PARAM_RATE,
342 master_runtime->rate); 342 master_runtime->rate,
343 343 master_runtime->rate);
344 snd_pcm_hw_constraint_minmax(substream->runtime, 344
345 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 345 if (master_runtime->sample_bits != 0)
346 master_runtime->sample_bits, 346 snd_pcm_hw_constraint_minmax(substream->runtime,
347 master_runtime->sample_bits); 347 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
348 master_runtime->sample_bits,
349 master_runtime->sample_bits);
348 350
349 ssm2602->slave_substream = substream; 351 ssm2602->slave_substream = substream;
350 } else 352 } else
@@ -372,6 +374,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
372 struct snd_soc_device *socdev = rtd->socdev; 374 struct snd_soc_device *socdev = rtd->socdev;
373 struct snd_soc_codec *codec = socdev->card->codec; 375 struct snd_soc_codec *codec = socdev->card->codec;
374 struct ssm2602_priv *ssm2602 = codec->private_data; 376 struct ssm2602_priv *ssm2602 = codec->private_data;
377
375 /* deactivate */ 378 /* deactivate */
376 if (!codec->active) 379 if (!codec->active)
377 ssm2602_write(codec, SSM2602_ACTIVE, 0); 380 ssm2602_write(codec, SSM2602_ACTIVE, 0);
@@ -497,11 +500,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
497 return 0; 500 return 0;
498} 501}
499 502
500#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 503#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\
501 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ 504 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
502 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ 505 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
503 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
504 SNDRV_PCM_RATE_96000)
505 506
506#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 507#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
507 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 508 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
new file mode 100644
index 000000000000..befc6488c39a
--- /dev/null
+++ b/sound/soc/codecs/stac9766.c
@@ -0,0 +1,463 @@
1/*
2 * stac9766.c -- ALSA SoC STAC9766 codec support
3 *
4 * Copyright 2009 Jon Smirl, Digispeaker
5 * Author: Jon Smirl <jonsmirl@gmail.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 * Features:-
13 *
14 * o Support for AC97 Codec, S/PDIF
15 */
16
17#include <linux/init.h>
18#include <linux/module.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/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/tlv.h>
27#include <sound/soc-of-simple.h>
28
29#include "stac9766.h"
30
31#define STAC9766_VERSION "0.10"
32
33/*
34 * STAC9766 register cache
35 */
36static const u16 stac9766_reg[] = {
37 0x6A90, 0x8000, 0x8000, 0x8000, /* 6 */
38 0x0000, 0x0000, 0x8008, 0x8008, /* e */
39 0x8808, 0x8808, 0x8808, 0x8808, /* 16 */
40 0x8808, 0x0000, 0x8000, 0x0000, /* 1e */
41 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */
42 0x0a05, 0x0400, 0xbb80, 0x0000, /* 2e */
43 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */
44 0x0000, 0x2000, 0x0000, 0x0100, /* 3e */
45 0x0000, 0x0000, 0x0080, 0x0000, /* 46 */
46 0x0000, 0x0000, 0x0003, 0xffff, /* 4e */
47 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */
48 0x4000, 0x0000, 0x0000, 0x0000, /* 5e */
49 0x1201, 0xFFFF, 0xFFFF, 0x0000, /* 66 */
50 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */
51 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */
52 0x0000, 0x0000, 0x0000, 0x0000, /* 7e */
53};
54
55static const char *stac9766_record_mux[] = {"Mic", "CD", "Video", "AUX",
56 "Line", "Stereo Mix", "Mono Mix", "Phone"};
57static const char *stac9766_mono_mux[] = {"Mix", "Mic"};
58static const char *stac9766_mic_mux[] = {"Mic1", "Mic2"};
59static const char *stac9766_SPDIF_mux[] = {"PCM", "ADC Record"};
60static const char *stac9766_popbypass_mux[] = {"Normal", "Bypass Mixer"};
61static const char *stac9766_record_all_mux[] = {"All analog",
62 "Analog plus DAC"};
63static const char *stac9766_boost1[] = {"0dB", "10dB"};
64static const char *stac9766_boost2[] = {"0dB", "20dB"};
65static const char *stac9766_stereo_mic[] = {"Off", "On"};
66
67static const struct soc_enum stac9766_record_enum =
68 SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux);
69static const struct soc_enum stac9766_mono_enum =
70 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux);
71static const struct soc_enum stac9766_mic_enum =
72 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux);
73static const struct soc_enum stac9766_SPDIF_enum =
74 SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux);
75static const struct soc_enum stac9766_popbypass_enum =
76 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux);
77static const struct soc_enum stac9766_record_all_enum =
78 SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2,
79 stac9766_record_all_mux);
80static const struct soc_enum stac9766_boost1_enum =
81 SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */
82static const struct soc_enum stac9766_boost2_enum =
83 SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */
84static const struct soc_enum stac9766_stereo_mic_enum =
85 SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic);
86
87static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0);
88static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250);
89static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0);
90static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200);
91
92static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = {
93 SOC_DOUBLE_TLV("Speaker Volume", AC97_MASTER, 8, 0, 31, 1, master_tlv),
94 SOC_SINGLE("Speaker Switch", AC97_MASTER, 15, 1, 1),
95 SOC_DOUBLE_TLV("Headphone Volume", AC97_HEADPHONE, 8, 0, 31, 1,
96 master_tlv),
97 SOC_SINGLE("Headphone Switch", AC97_HEADPHONE, 15, 1, 1),
98 SOC_SINGLE_TLV("Mono Out Volume", AC97_MASTER_MONO, 0, 31, 1,
99 master_tlv),
100 SOC_SINGLE("Mono Out Switch", AC97_MASTER_MONO, 15, 1, 1),
101
102 SOC_DOUBLE_TLV("Record Volume", AC97_REC_GAIN, 8, 0, 15, 0, record_tlv),
103 SOC_SINGLE("Record Switch", AC97_REC_GAIN, 15, 1, 1),
104
105
106 SOC_SINGLE_TLV("Beep Volume", AC97_PC_BEEP, 1, 15, 1, beep_tlv),
107 SOC_SINGLE("Beep Switch", AC97_PC_BEEP, 15, 1, 1),
108 SOC_SINGLE("Beep Frequency", AC97_PC_BEEP, 5, 127, 1),
109 SOC_SINGLE_TLV("Phone Volume", AC97_PHONE, 0, 31, 1, mix_tlv),
110 SOC_SINGLE("Phone Switch", AC97_PHONE, 15, 1, 1),
111
112 SOC_ENUM("Mic Boost1", stac9766_boost1_enum),
113 SOC_ENUM("Mic Boost2", stac9766_boost2_enum),
114 SOC_SINGLE_TLV("Mic Volume", AC97_MIC, 0, 31, 1, mix_tlv),
115 SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1),
116 SOC_ENUM("Stereo Mic", stac9766_stereo_mic_enum),
117
118 SOC_DOUBLE_TLV("Line Volume", AC97_LINE, 8, 0, 31, 1, mix_tlv),
119 SOC_SINGLE("Line Switch", AC97_LINE, 15, 1, 1),
120 SOC_DOUBLE_TLV("CD Volume", AC97_CD, 8, 0, 31, 1, mix_tlv),
121 SOC_SINGLE("CD Switch", AC97_CD, 15, 1, 1),
122 SOC_DOUBLE_TLV("AUX Volume", AC97_AUX, 8, 0, 31, 1, mix_tlv),
123 SOC_SINGLE("AUX Switch", AC97_AUX, 15, 1, 1),
124 SOC_DOUBLE_TLV("Video Volume", AC97_VIDEO, 8, 0, 31, 1, mix_tlv),
125 SOC_SINGLE("Video Switch", AC97_VIDEO, 15, 1, 1),
126
127 SOC_DOUBLE_TLV("DAC Volume", AC97_PCM, 8, 0, 31, 1, mix_tlv),
128 SOC_SINGLE("DAC Switch", AC97_PCM, 15, 1, 1),
129 SOC_SINGLE("Loopback Test Switch", AC97_GENERAL_PURPOSE, 7, 1, 0),
130 SOC_SINGLE("3D Volume", AC97_3D_CONTROL, 3, 2, 1),
131 SOC_SINGLE("3D Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
132
133 SOC_ENUM("SPDIF Mux", stac9766_SPDIF_enum),
134 SOC_ENUM("Mic1/2 Mux", stac9766_mic_enum),
135 SOC_ENUM("Record All Mux", stac9766_record_all_enum),
136 SOC_ENUM("Record Mux", stac9766_record_enum),
137 SOC_ENUM("Mono Mux", stac9766_mono_enum),
138 SOC_ENUM("Pop Bypass Mux", stac9766_popbypass_enum),
139};
140
141static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
142 unsigned int val)
143{
144 u16 *cache = codec->reg_cache;
145
146 if (reg > AC97_STAC_PAGE0) {
147 stac9766_ac97_write(codec, AC97_INT_PAGING, 0);
148 soc_ac97_ops.write(codec->ac97, reg, val);
149 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
150 return 0;
151 }
152 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
153 return -EIO;
154
155 soc_ac97_ops.write(codec->ac97, reg, val);
156 cache[reg / 2] = val;
157 return 0;
158}
159
160static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
161 unsigned int reg)
162{
163 u16 val = 0, *cache = codec->reg_cache;
164
165 if (reg > AC97_STAC_PAGE0) {
166 stac9766_ac97_write(codec, AC97_INT_PAGING, 0);
167 val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0);
168 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
169 return val;
170 }
171 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
172 return -EIO;
173
174 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
175 reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 ||
176 reg == AC97_VENDOR_ID2) {
177
178 val = soc_ac97_ops.read(codec->ac97, reg);
179 return val;
180 }
181 return cache[reg / 2];
182}
183
184static int ac97_analog_prepare(struct snd_pcm_substream *substream,
185 struct snd_soc_dai *dai)
186{
187 struct snd_soc_codec *codec = dai->codec;
188 struct snd_pcm_runtime *runtime = substream->runtime;
189 unsigned short reg, vra;
190
191 vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
192
193 vra |= 0x1; /* enable variable rate audio */
194
195 stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
196
197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
198 reg = AC97_PCM_FRONT_DAC_RATE;
199 else
200 reg = AC97_PCM_LR_ADC_RATE;
201
202 return stac9766_ac97_write(codec, reg, runtime->rate);
203}
204
205static int ac97_digital_prepare(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai)
207{
208 struct snd_soc_codec *codec = dai->codec;
209 struct snd_pcm_runtime *runtime = substream->runtime;
210 unsigned short reg, vra;
211
212 stac9766_ac97_write(codec, AC97_SPDIF, 0x2002);
213
214 vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS);
215 vra |= 0x5; /* Enable VRA and SPDIF out */
216
217 stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra);
218
219 reg = AC97_PCM_FRONT_DAC_RATE;
220
221 return stac9766_ac97_write(codec, reg, runtime->rate);
222}
223
224static 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
240static int stac9766_set_bias_level(struct snd_soc_codec *codec,
241 enum snd_soc_bias_level level)
242{
243 switch (level) {
244 case SND_SOC_BIAS_ON: /* full On */
245 case SND_SOC_BIAS_PREPARE: /* partial On */
246 case SND_SOC_BIAS_STANDBY: /* Off, with power */
247 stac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000);
248 break;
249 case SND_SOC_BIAS_OFF: /* Off, without power */
250 /* disable everything including AC link */
251 stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff);
252 break;
253 }
254 codec->bias_level = level;
255 return 0;
256}
257
258static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
259{
260 if (try_warm && soc_ac97_ops.warm_reset) {
261 soc_ac97_ops.warm_reset(codec->ac97);
262 if (stac9766_ac97_read(codec, 0) == stac9766_reg[0])
263 return 1;
264 }
265
266 soc_ac97_ops.reset(codec->ac97);
267 if (soc_ac97_ops.warm_reset)
268 soc_ac97_ops.warm_reset(codec->ac97);
269 if (stac9766_ac97_read(codec, 0) != stac9766_reg[0])
270 return -EIO;
271 return 0;
272}
273
274static int stac9766_codec_suspend(struct platform_device *pdev,
275 pm_message_t state)
276{
277 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
278 struct snd_soc_codec *codec = socdev->card->codec;
279
280 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
281 return 0;
282}
283
284static int stac9766_codec_resume(struct platform_device *pdev)
285{
286 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
287 struct snd_soc_codec *codec = socdev->card->codec;
288 u16 id, reset;
289
290 reset = 0;
291 /* give the codec an AC97 warm reset to start the link */
292reset:
293 if (reset > 5) {
294 printk(KERN_ERR "stac9766 failed to resume");
295 return -EIO;
296 }
297 codec->ac97->bus->ops->warm_reset(codec->ac97);
298 id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2);
299 if (id != 0x4c13) {
300 stac9766_reset(codec, 0);
301 reset++;
302 goto reset;
303 }
304 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
305
306 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
307 stac9766_set_bias_level(codec, SND_SOC_BIAS_ON);
308
309 return 0;
310}
311
312static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
313 .prepare = ac97_analog_prepare,
314};
315
316static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
317 .prepare = ac97_digital_prepare,
318 .trigger = ac97_digital_trigger,
319};
320
321struct snd_soc_dai stac9766_dai[] = {
322{
323 .name = "stac9766 analog",
324 .id = 0,
325 .ac97_control = 1,
326
327 /* stream cababilities */
328 .playback = {
329 .stream_name = "stac9766 analog",
330 .channels_min = 1,
331 .channels_max = 2,
332 .rates = SNDRV_PCM_RATE_8000_48000,
333 .formats = SND_SOC_STD_AC97_FMTS,
334 },
335 .capture = {
336 .stream_name = "stac9766 analog",
337 .channels_min = 1,
338 .channels_max = 2,
339 .rates = SNDRV_PCM_RATE_8000_48000,
340 .formats = SND_SOC_STD_AC97_FMTS,
341 },
342 /* alsa ops */
343 .ops = &stac9766_dai_ops_analog,
344},
345{
346 .name = "stac9766 IEC958",
347 .id = 1,
348 .ac97_control = 1,
349
350 /* stream cababilities */
351 .playback = {
352 .stream_name = "stac9766 IEC958",
353 .channels_min = 1,
354 .channels_max = 2,
355 .rates = SNDRV_PCM_RATE_32000 | \
356 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
357 .formats = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE,
358 },
359 /* alsa ops */
360 .ops = &stac9766_dai_ops_digital,
361}
362};
363EXPORT_SYMBOL_GPL(stac9766_dai);
364
365static int stac9766_codec_probe(struct platform_device *pdev)
366{
367 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
368 struct snd_soc_codec *codec;
369 int ret = 0;
370
371 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
372
373 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
374 if (socdev->card->codec == NULL)
375 return -ENOMEM;
376 codec = socdev->card->codec;
377 mutex_init(&codec->mutex);
378
379 codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
380 GFP_KERNEL);
381 if (codec->reg_cache == NULL) {
382 ret = -ENOMEM;
383 goto cache_err;
384 }
385 codec->reg_cache_size = sizeof(stac9766_reg);
386 codec->reg_cache_step = 2;
387
388 codec->name = "STAC9766";
389 codec->owner = THIS_MODULE;
390 codec->dai = stac9766_dai;
391 codec->num_dai = ARRAY_SIZE(stac9766_dai);
392 codec->write = stac9766_ac97_write;
393 codec->read = stac9766_ac97_read;
394 codec->set_bias_level = stac9766_set_bias_level;
395 INIT_LIST_HEAD(&codec->dapm_widgets);
396 INIT_LIST_HEAD(&codec->dapm_paths);
397
398 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
399 if (ret < 0)
400 goto codec_err;
401
402 /* register pcms */
403 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
404 if (ret < 0)
405 goto pcm_err;
406
407 /* do a cold reset for the controller and then try
408 * a warm reset followed by an optional cold reset for codec */
409 stac9766_reset(codec, 0);
410 ret = stac9766_reset(codec, 1);
411 if (ret < 0) {
412 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
413 goto reset_err;
414 }
415
416 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
417
418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
419 ARRAY_SIZE(stac9766_snd_ac97_controls));
420
421 ret = snd_soc_init_card(socdev);
422 if (ret < 0)
423 goto reset_err;
424 return 0;
425
426reset_err:
427 snd_soc_free_pcms(socdev);
428pcm_err:
429 snd_soc_free_ac97_codec(codec);
430codec_err:
431 kfree(codec->private_data);
432cache_err:
433 kfree(socdev->card->codec);
434 socdev->card->codec = NULL;
435 return ret;
436}
437
438static int stac9766_codec_remove(struct platform_device *pdev)
439{
440 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
441 struct snd_soc_codec *codec = socdev->card->codec;
442
443 if (codec == NULL)
444 return 0;
445
446 snd_soc_free_pcms(socdev);
447 snd_soc_free_ac97_codec(codec);
448 kfree(codec->reg_cache);
449 kfree(codec);
450 return 0;
451}
452
453struct snd_soc_codec_device soc_codec_dev_stac9766 = {
454 .probe = stac9766_codec_probe,
455 .remove = stac9766_codec_remove,
456 .suspend = stac9766_codec_suspend,
457 .resume = stac9766_codec_resume,
458};
459EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766);
460
461MODULE_DESCRIPTION("ASoC stac9766 driver");
462MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
463MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h
new file mode 100644
index 000000000000..65642eb8393e
--- /dev/null
+++ b/sound/soc/codecs/stac9766.h
@@ -0,0 +1,21 @@
1/*
2 * stac9766.h -- STAC9766 Soc Audio driver
3 */
4
5#ifndef _STAC9766_H
6#define _STAC9766_H
7
8#define AC97_STAC_PAGE0 0x1000
9#define AC97_STAC_DA_CONTROL (AC97_STAC_PAGE0 | 0x6A)
10#define AC97_STAC_ANALOG_SPECIAL (AC97_STAC_PAGE0 | 0x6E)
11#define AC97_STAC_STEREO_MIC 0x78
12
13/* STAC9766 DAI ID's */
14#define STAC9766_DAI_AC97_ANALOG 0
15#define STAC9766_DAI_AC97_DIGITAL 1
16
17extern struct snd_soc_dai stac9766_dai[];
18extern struct snd_soc_codec_device soc_codec_dev_stac9766;
19
20
21#endif
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index c3f4afb5d017..0b8dcb5cd729 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -86,7 +86,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
86 */ 86 */
87 87
88 if ((reg < 0 || reg > 9) && (reg != 15)) { 88 if ((reg < 0 || reg > 9) && (reg != 15)) {
89 printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg); 89 printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
90 return -1; 90 return -1;
91 } 91 }
92 92
@@ -98,7 +98,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
98 if (codec->hw_write(codec->control_data, data, 2) == 2) 98 if (codec->hw_write(codec->control_data, data, 2) == 2)
99 return 0; 99 return 0;
100 100
101 printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__, 101 printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
102 value, reg); 102 value, reg);
103 103
104 return -EIO; 104 return -EIO;
@@ -273,14 +273,14 @@ static const unsigned short sr_valid_mask[] = {
273 * Every divisor is a factor of 11*12 273 * Every divisor is a factor of 11*12
274 */ 274 */
275#define SR_MULT (11*12) 275#define SR_MULT (11*12)
276#define A(x) (x) ? (SR_MULT/x) : 0 276#define A(x) (SR_MULT/x)
277static const unsigned char sr_adc_mult_table[] = { 277static const unsigned char sr_adc_mult_table[] = {
278 A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1), 278 A(2), A(2), A(12), A(12), 0, 0, A(3), A(1),
279 A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1) 279 A(2), A(2), A(11), A(11), 0, 0, 0, A(1)
280}; 280};
281static const unsigned char sr_dac_mult_table[] = { 281static const unsigned char sr_dac_mult_table[] = {
282 A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1), 282 A(2), A(12), A(2), A(12), 0, 0, A(3), A(1),
283 A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1) 283 A(2), A(11), A(2), A(11), 0, 0, 0, A(1)
284}; 284};
285 285
286static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc, 286static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
@@ -523,6 +523,8 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
523 case SND_SOC_DAIFMT_I2S: 523 case SND_SOC_DAIFMT_I2S:
524 iface_reg |= TLV320AIC23_FOR_I2S; 524 iface_reg |= TLV320AIC23_FOR_I2S;
525 break; 525 break;
526 case SND_SOC_DAIFMT_DSP_A:
527 iface_reg |= TLV320AIC23_LRP_ON;
526 case SND_SOC_DAIFMT_DSP_B: 528 case SND_SOC_DAIFMT_DSP_B:
527 iface_reg |= TLV320AIC23_FOR_DSP; 529 iface_reg |= TLV320AIC23_FOR_DSP;
528 break; 530 break;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index ab099f482487..126b15b18aeb 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -145,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
145 u8 *value) 145 u8 *value)
146{ 146{
147 *value = reg & 0xff; 147 *value = reg & 0xff;
148 if (codec->hw_read(codec->control_data, value, 1) != 1) 148
149 return -EIO; 149 value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
150 150
151 aic3x_write_reg_cache(codec, reg, *value); 151 aic3x_write_reg_cache(codec, reg, *value);
152 return 0; 152 return 0;
@@ -767,6 +767,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
767 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; 767 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
768 u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; 768 u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
769 u16 pll_d = 1; 769 u16 pll_d = 1;
770 u8 reg;
770 771
771 /* select data word length */ 772 /* select data word length */
772 data = 773 data =
@@ -801,8 +802,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
801 pll_q &= 0xf; 802 pll_q &= 0xf;
802 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); 803 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
803 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); 804 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
804 } else 805 /* disable PLL if it is bypassed */
806 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
807 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
808
809 } else {
805 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); 810 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
811 /* enable PLL when it is used */
812 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
813 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
814 }
806 815
807 /* Route Left DAC to left channel input and 816 /* Route Left DAC to left channel input and
808 * right DAC to right channel input */ 817 * right DAC to right channel input */
@@ -1316,12 +1325,6 @@ static struct i2c_driver aic3x_i2c_driver = {
1316 .id_table = aic3x_i2c_id, 1325 .id_table = aic3x_i2c_id,
1317}; 1326};
1318 1327
1319static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
1320{
1321 value[0] = i2c_smbus_read_byte_data(client, value[0]);
1322 return (len == 1);
1323}
1324
1325static int aic3x_add_i2c_device(struct platform_device *pdev, 1328static int aic3x_add_i2c_device(struct platform_device *pdev,
1326 const struct aic3x_setup_data *setup) 1329 const struct aic3x_setup_data *setup)
1327{ 1330{
@@ -1394,7 +1397,6 @@ static int aic3x_probe(struct platform_device *pdev)
1394#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1397#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1395 if (setup->i2c_address) { 1398 if (setup->i2c_address) {
1396 codec->hw_write = (hw_write_t) i2c_master_send; 1399 codec->hw_write = (hw_write_t) i2c_master_send;
1397 codec->hw_read = (hw_read_t) aic3x_i2c_read;
1398 ret = aic3x_add_i2c_device(pdev, setup); 1400 ret = aic3x_add_i2c_device(pdev, setup);
1399 } 1401 }
1400#else 1402#else
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index df7c8c281d2f..4df7c6c61c76 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -115,6 +115,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
115 0x00, /* REG_VIBRA_PWM_SET (0x47) */ 115 0x00, /* REG_VIBRA_PWM_SET (0x47) */
116 0x00, /* REG_ANAMIC_GAIN (0x48) */ 116 0x00, /* REG_ANAMIC_GAIN (0x48) */
117 0x00, /* REG_MISC_SET_2 (0x49) */ 117 0x00, /* REG_MISC_SET_2 (0x49) */
118 0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */
118}; 119};
119 120
120/* codec private data */ 121/* codec private data */
@@ -125,6 +126,17 @@ struct twl4030_priv {
125 126
126 struct snd_pcm_substream *master_substream; 127 struct snd_pcm_substream *master_substream;
127 struct snd_pcm_substream *slave_substream; 128 struct snd_pcm_substream *slave_substream;
129
130 unsigned int configured;
131 unsigned int rate;
132 unsigned int sample_bits;
133 unsigned int channels;
134
135 unsigned int sysclk;
136
137 /* Headset output state handling */
138 unsigned int hsl_enabled;
139 unsigned int hsr_enabled;
128}; 140};
129 141
130/* 142/*
@@ -161,7 +173,11 @@ static int twl4030_write(struct snd_soc_codec *codec,
161 unsigned int reg, unsigned int value) 173 unsigned int reg, unsigned int value)
162{ 174{
163 twl4030_write_reg_cache(codec, reg, value); 175 twl4030_write_reg_cache(codec, reg, value);
164 return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); 176 if (likely(reg < TWL4030_REG_SW_SHADOW))
177 return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value,
178 reg);
179 else
180 return 0;
165} 181}
166 182
167static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 183static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
@@ -188,6 +204,7 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
188 204
189static void twl4030_init_chip(struct snd_soc_codec *codec) 205static void twl4030_init_chip(struct snd_soc_codec *codec)
190{ 206{
207 u8 *cache = codec->reg_cache;
191 int i; 208 int i;
192 209
193 /* clear CODECPDZ prior to setting register defaults */ 210 /* clear CODECPDZ prior to setting register defaults */
@@ -195,7 +212,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
195 212
196 /* set all audio section registers to reasonable defaults */ 213 /* set all audio section registers to reasonable defaults */
197 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) 214 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
198 twl4030_write(codec, i, twl4030_reg[i]); 215 twl4030_write(codec, i, cache[i]);
199 216
200} 217}
201 218
@@ -208,55 +225,11 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
208 return; 225 return;
209 226
210 if (mute) { 227 if (mute) {
211 /* Bypass the reg_cache and mute the volumes
212 * Headset mute is done in it's own event handler
213 * Things to mute: Earpiece, PreDrivL/R, CarkitL/R
214 */
215 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
216 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
217 reg_val & (~TWL4030_EAR_GAIN),
218 TWL4030_REG_EAR_CTL);
219
220 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
221 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
222 reg_val & (~TWL4030_PREDL_GAIN),
223 TWL4030_REG_PREDL_CTL);
224 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
225 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
226 reg_val & (~TWL4030_PREDR_GAIN),
227 TWL4030_REG_PREDL_CTL);
228
229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
230 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
231 reg_val & (~TWL4030_PRECKL_GAIN),
232 TWL4030_REG_PRECKL_CTL);
233 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
234 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
235 reg_val & (~TWL4030_PRECKL_GAIN),
236 TWL4030_REG_PRECKR_CTL);
237
238 /* Disable PLL */ 228 /* Disable PLL */
239 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
240 reg_val &= ~TWL4030_APLL_EN; 230 reg_val &= ~TWL4030_APLL_EN;
241 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); 231 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
242 } else { 232 } else {
243 /* Restore the volumes
244 * Headset mute is done in it's own event handler
245 * Things to restore: Earpiece, PreDrivL/R, CarkitL/R
246 */
247 twl4030_write(codec, TWL4030_REG_EAR_CTL,
248 twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL));
249
250 twl4030_write(codec, TWL4030_REG_PREDL_CTL,
251 twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL));
252 twl4030_write(codec, TWL4030_REG_PREDR_CTL,
253 twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL));
254
255 twl4030_write(codec, TWL4030_REG_PRECKL_CTL,
256 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL));
257 twl4030_write(codec, TWL4030_REG_PRECKR_CTL,
258 twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL));
259
260 /* Enable PLL */ 233 /* Enable PLL */
261 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 234 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
262 reg_val |= TWL4030_APLL_EN; 235 reg_val |= TWL4030_APLL_EN;
@@ -316,104 +289,60 @@ static void twl4030_power_down(struct snd_soc_codec *codec)
316} 289}
317 290
318/* Earpiece */ 291/* Earpiece */
319static const char *twl4030_earpiece_texts[] = 292static const struct snd_kcontrol_new twl4030_dapm_earpiece_controls[] = {
320 {"Off", "DACL1", "DACL2", "DACR1"}; 293 SOC_DAPM_SINGLE("Voice", TWL4030_REG_EAR_CTL, 0, 1, 0),
321 294 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_EAR_CTL, 1, 1, 0),
322static const unsigned int twl4030_earpiece_values[] = 295 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_EAR_CTL, 2, 1, 0),
323 {0x0, 0x1, 0x2, 0x4}; 296 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_EAR_CTL, 3, 1, 0),
324 297};
325static const struct soc_enum twl4030_earpiece_enum =
326 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, 0x7,
327 ARRAY_SIZE(twl4030_earpiece_texts),
328 twl4030_earpiece_texts,
329 twl4030_earpiece_values);
330
331static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
332SOC_DAPM_VALUE_ENUM("Route", twl4030_earpiece_enum);
333 298
334/* PreDrive Left */ 299/* PreDrive Left */
335static const char *twl4030_predrivel_texts[] = 300static const struct snd_kcontrol_new twl4030_dapm_predrivel_controls[] = {
336 {"Off", "DACL1", "DACL2", "DACR2"}; 301 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDL_CTL, 0, 1, 0),
337 302 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PREDL_CTL, 1, 1, 0),
338static const unsigned int twl4030_predrivel_values[] = 303 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDL_CTL, 2, 1, 0),
339 {0x0, 0x1, 0x2, 0x4}; 304 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDL_CTL, 3, 1, 0),
340 305};
341static const struct soc_enum twl4030_predrivel_enum =
342 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, 0x7,
343 ARRAY_SIZE(twl4030_predrivel_texts),
344 twl4030_predrivel_texts,
345 twl4030_predrivel_values);
346
347static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
348SOC_DAPM_VALUE_ENUM("Route", twl4030_predrivel_enum);
349 306
350/* PreDrive Right */ 307/* PreDrive Right */
351static const char *twl4030_predriver_texts[] = 308static const struct snd_kcontrol_new twl4030_dapm_predriver_controls[] = {
352 {"Off", "DACR1", "DACR2", "DACL2"}; 309 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDR_CTL, 0, 1, 0),
353 310 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PREDR_CTL, 1, 1, 0),
354static const unsigned int twl4030_predriver_values[] = 311 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDR_CTL, 2, 1, 0),
355 {0x0, 0x1, 0x2, 0x4}; 312 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDR_CTL, 3, 1, 0),
356 313};
357static const struct soc_enum twl4030_predriver_enum =
358 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, 0x7,
359 ARRAY_SIZE(twl4030_predriver_texts),
360 twl4030_predriver_texts,
361 twl4030_predriver_values);
362
363static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
364SOC_DAPM_VALUE_ENUM("Route", twl4030_predriver_enum);
365 314
366/* Headset Left */ 315/* Headset Left */
367static const char *twl4030_hsol_texts[] = 316static const struct snd_kcontrol_new twl4030_dapm_hsol_controls[] = {
368 {"Off", "DACL1", "DACL2"}; 317 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 0, 1, 0),
369 318 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_HS_SEL, 1, 1, 0),
370static const struct soc_enum twl4030_hsol_enum = 319 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_HS_SEL, 2, 1, 0),
371 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1, 320};
372 ARRAY_SIZE(twl4030_hsol_texts),
373 twl4030_hsol_texts);
374
375static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
376SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
377 321
378/* Headset Right */ 322/* Headset Right */
379static const char *twl4030_hsor_texts[] = 323static const struct snd_kcontrol_new twl4030_dapm_hsor_controls[] = {
380 {"Off", "DACR1", "DACR2"}; 324 SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 3, 1, 0),
381 325 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_HS_SEL, 4, 1, 0),
382static const struct soc_enum twl4030_hsor_enum = 326 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_HS_SEL, 5, 1, 0),
383 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4, 327};
384 ARRAY_SIZE(twl4030_hsor_texts),
385 twl4030_hsor_texts);
386
387static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
388SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
389 328
390/* Carkit Left */ 329/* Carkit Left */
391static const char *twl4030_carkitl_texts[] = 330static const struct snd_kcontrol_new twl4030_dapm_carkitl_controls[] = {
392 {"Off", "DACL1", "DACL2"}; 331 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKL_CTL, 0, 1, 0),
393 332 SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PRECKL_CTL, 1, 1, 0),
394static const struct soc_enum twl4030_carkitl_enum = 333 SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PRECKL_CTL, 2, 1, 0),
395 SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1, 334};
396 ARRAY_SIZE(twl4030_carkitl_texts),
397 twl4030_carkitl_texts);
398
399static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
400SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
401 335
402/* Carkit Right */ 336/* Carkit Right */
403static const char *twl4030_carkitr_texts[] = 337static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = {
404 {"Off", "DACR1", "DACR2"}; 338 SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKR_CTL, 0, 1, 0),
405 339 SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PRECKR_CTL, 1, 1, 0),
406static const struct soc_enum twl4030_carkitr_enum = 340 SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PRECKR_CTL, 2, 1, 0),
407 SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1, 341};
408 ARRAY_SIZE(twl4030_carkitr_texts),
409 twl4030_carkitr_texts);
410
411static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
412SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
413 342
414/* Handsfree Left */ 343/* Handsfree Left */
415static const char *twl4030_handsfreel_texts[] = 344static const char *twl4030_handsfreel_texts[] =
416 {"Voice", "DACL1", "DACL2", "DACR2"}; 345 {"Voice", "AudioL1", "AudioL2", "AudioR2"};
417 346
418static const struct soc_enum twl4030_handsfreel_enum = 347static const struct soc_enum twl4030_handsfreel_enum =
419 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, 348 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
@@ -423,9 +352,13 @@ static const struct soc_enum twl4030_handsfreel_enum =
423static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = 352static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
424SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); 353SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
425 354
355/* Handsfree Left virtual mute */
356static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
357 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
358
426/* Handsfree Right */ 359/* Handsfree Right */
427static const char *twl4030_handsfreer_texts[] = 360static const char *twl4030_handsfreer_texts[] =
428 {"Voice", "DACR1", "DACR2", "DACL2"}; 361 {"Voice", "AudioR1", "AudioR2", "AudioL2"};
429 362
430static const struct soc_enum twl4030_handsfreer_enum = 363static const struct soc_enum twl4030_handsfreer_enum =
431 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, 364 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
@@ -435,37 +368,52 @@ static const struct soc_enum twl4030_handsfreer_enum =
435static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = 368static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
436SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); 369SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
437 370
438/* Left analog microphone selection */ 371/* Handsfree Right virtual mute */
439static const char *twl4030_analoglmic_texts[] = 372static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
440 {"Off", "Main mic", "Headset mic", "AUXL", "Carkit mic"}; 373 SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
441 374
442static const unsigned int twl4030_analoglmic_values[] = 375/* Vibra */
443 {0x0, 0x1, 0x2, 0x4, 0x8}; 376/* Vibra audio path selection */
377static const char *twl4030_vibra_texts[] =
378 {"AudioL1", "AudioR1", "AudioL2", "AudioR2"};
444 379
445static const struct soc_enum twl4030_analoglmic_enum = 380static const struct soc_enum twl4030_vibra_enum =
446 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0, 0xf, 381 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2,
447 ARRAY_SIZE(twl4030_analoglmic_texts), 382 ARRAY_SIZE(twl4030_vibra_texts),
448 twl4030_analoglmic_texts, 383 twl4030_vibra_texts);
449 twl4030_analoglmic_values);
450 384
451static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control = 385static const struct snd_kcontrol_new twl4030_dapm_vibra_control =
452SOC_DAPM_VALUE_ENUM("Route", twl4030_analoglmic_enum); 386SOC_DAPM_ENUM("Route", twl4030_vibra_enum);
453 387
454/* Right analog microphone selection */ 388/* Vibra path selection: local vibrator (PWM) or audio driven */
455static const char *twl4030_analogrmic_texts[] = 389static const char *twl4030_vibrapath_texts[] =
456 {"Off", "Sub mic", "AUXR"}; 390 {"Local vibrator", "Audio"};
457 391
458static const unsigned int twl4030_analogrmic_values[] = 392static const struct soc_enum twl4030_vibrapath_enum =
459 {0x0, 0x1, 0x4}; 393 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4,
394 ARRAY_SIZE(twl4030_vibrapath_texts),
395 twl4030_vibrapath_texts);
460 396
461static const struct soc_enum twl4030_analogrmic_enum = 397static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control =
462 SOC_VALUE_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0, 0x5, 398SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
463 ARRAY_SIZE(twl4030_analogrmic_texts),
464 twl4030_analogrmic_texts,
465 twl4030_analogrmic_values);
466 399
467static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control = 400/* Left analog microphone selection */
468SOC_DAPM_VALUE_ENUM("Route", twl4030_analogrmic_enum); 401static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = {
402 SOC_DAPM_SINGLE("Main Mic Capture Switch",
403 TWL4030_REG_ANAMICL, 0, 1, 0),
404 SOC_DAPM_SINGLE("Headset Mic Capture Switch",
405 TWL4030_REG_ANAMICL, 1, 1, 0),
406 SOC_DAPM_SINGLE("AUXL Capture Switch",
407 TWL4030_REG_ANAMICL, 2, 1, 0),
408 SOC_DAPM_SINGLE("Carkit Mic Capture Switch",
409 TWL4030_REG_ANAMICL, 3, 1, 0),
410};
411
412/* Right analog microphone selection */
413static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
414 SOC_DAPM_SINGLE("Sub Mic Capture Switch", TWL4030_REG_ANAMICR, 0, 1, 0),
415 SOC_DAPM_SINGLE("AUXR Capture Switch", TWL4030_REG_ANAMICR, 2, 1, 0),
416};
469 417
470/* TX1 L/R Analog/Digital microphone selection */ 418/* TX1 L/R Analog/Digital microphone selection */
471static const char *twl4030_micpathtx1_texts[] = 419static const char *twl4030_micpathtx1_texts[] =
@@ -507,6 +455,10 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
507static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = 455static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
508 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); 456 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
509 457
458/* Analog bypass for Voice */
459static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
460 SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
461
510/* Digital bypass gain, 0 mutes the bypass */ 462/* Digital bypass gain, 0 mutes the bypass */
511static const unsigned int twl4030_dapm_dbypass_tlv[] = { 463static const unsigned int twl4030_dapm_dbypass_tlv[] = {
512 TLV_DB_RANGE_HEAD(2), 464 TLV_DB_RANGE_HEAD(2),
@@ -526,6 +478,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
526 TWL4030_REG_ATX2ARXPGA, 0, 7, 0, 478 TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
527 twl4030_dapm_dbypass_tlv); 479 twl4030_dapm_dbypass_tlv);
528 480
481/*
482 * Voice Sidetone GAIN volume control:
483 * from -51 to -10 dB in 1 dB steps (mute instead of -51 dB)
484 */
485static DECLARE_TLV_DB_SCALE(twl4030_dapm_dbypassv_tlv, -5100, 100, 1);
486
487/* Digital bypass voice: sidetone (VUL -> VDL)*/
488static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
489 SOC_DAPM_SINGLE_TLV("Volume",
490 TWL4030_REG_VSTPGA, 0, 0x29, 0,
491 twl4030_dapm_dbypassv_tlv);
492
529static int micpath_event(struct snd_soc_dapm_widget *w, 493static int micpath_event(struct snd_soc_dapm_widget *w,
530 struct snd_kcontrol *kcontrol, int event) 494 struct snd_kcontrol *kcontrol, int event)
531{ 495{
@@ -556,63 +520,205 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
556 return 0; 520 return 0;
557} 521}
558 522
559static int handsfree_event(struct snd_soc_dapm_widget *w, 523/*
560 struct snd_kcontrol *kcontrol, int event) 524 * Output PGA builder:
525 * Handle the muting and unmuting of the given output (turning off the
526 * amplifier associated with the output pin)
527 * On mute bypass the reg_cache and mute the volume
528 * On unmute: restore the register content
529 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R
530 */
531#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \
532static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
533 struct snd_kcontrol *kcontrol, int event) \
534{ \
535 u8 reg_val; \
536 \
537 switch (event) { \
538 case SND_SOC_DAPM_POST_PMU: \
539 twl4030_write(w->codec, reg, \
540 twl4030_read_reg_cache(w->codec, reg)); \
541 break; \
542 case SND_SOC_DAPM_POST_PMD: \
543 reg_val = twl4030_read_reg_cache(w->codec, reg); \
544 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \
545 reg_val & (~mask), \
546 reg); \
547 break; \
548 } \
549 return 0; \
550}
551
552TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN);
553TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN);
554TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN);
555TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN);
556TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN);
557
558static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
561{ 559{
562 struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
563 unsigned char hs_ctl; 560 unsigned char hs_ctl;
564 561
565 hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); 562 hs_ctl = twl4030_read_reg_cache(codec, reg);
566 563
567 if (hs_ctl & TWL4030_HF_CTL_REF_EN) { 564 if (ramp) {
565 /* HF ramp-up */
566 hs_ctl |= TWL4030_HF_CTL_REF_EN;
567 twl4030_write(codec, reg, hs_ctl);
568 udelay(10);
568 hs_ctl |= TWL4030_HF_CTL_RAMP_EN; 569 hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
569 twl4030_write(w->codec, e->reg, hs_ctl); 570 twl4030_write(codec, reg, hs_ctl);
571 udelay(40);
570 hs_ctl |= TWL4030_HF_CTL_LOOP_EN; 572 hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
571 twl4030_write(w->codec, e->reg, hs_ctl);
572 hs_ctl |= TWL4030_HF_CTL_HB_EN; 573 hs_ctl |= TWL4030_HF_CTL_HB_EN;
573 twl4030_write(w->codec, e->reg, hs_ctl); 574 twl4030_write(codec, reg, hs_ctl);
574 } else { 575 } else {
575 hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN 576 /* HF ramp-down */
576 | TWL4030_HF_CTL_HB_EN); 577 hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN;
577 twl4030_write(w->codec, e->reg, hs_ctl); 578 hs_ctl &= ~TWL4030_HF_CTL_HB_EN;
579 twl4030_write(codec, reg, hs_ctl);
580 hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN;
581 twl4030_write(codec, reg, hs_ctl);
582 udelay(40);
583 hs_ctl &= ~TWL4030_HF_CTL_REF_EN;
584 twl4030_write(codec, reg, hs_ctl);
578 } 585 }
586}
579 587
588static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
589 struct snd_kcontrol *kcontrol, int event)
590{
591 switch (event) {
592 case SND_SOC_DAPM_POST_PMU:
593 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1);
594 break;
595 case SND_SOC_DAPM_POST_PMD:
596 handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0);
597 break;
598 }
580 return 0; 599 return 0;
581} 600}
582 601
583static int headsetl_event(struct snd_soc_dapm_widget *w, 602static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
584 struct snd_kcontrol *kcontrol, int event) 603 struct snd_kcontrol *kcontrol, int event)
585{ 604{
586 unsigned char hs_gain, hs_pop;
587
588 /* Save the current volume */
589 hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET);
590 hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET);
591
592 switch (event) { 605 switch (event) {
593 case SND_SOC_DAPM_POST_PMU: 606 case SND_SOC_DAPM_POST_PMU:
594 /* Do the anti-pop/bias ramp enable according to the TRM */ 607 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1);
595 hs_pop |= TWL4030_VMID_EN;
596 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
597 /* Is this needed? Can we just use whatever gain here? */
598 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET,
599 (hs_gain & (~0x0f)) | 0x0a);
600 hs_pop |= TWL4030_RAMP_EN;
601 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop);
602
603 /* Restore the original volume */
604 twl4030_write(w->codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
605 break; 608 break;
606 case SND_SOC_DAPM_POST_PMD: 609 case SND_SOC_DAPM_POST_PMD:
607 /* Do the anti-pop/bias ramp disable according to the TRM */ 610 handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0);
611 break;
612 }
613 return 0;
614}
615
616static void headset_ramp(struct snd_soc_codec *codec, int ramp)
617{
618 struct snd_soc_device *socdev = codec->socdev;
619 struct twl4030_setup_data *setup = socdev->codec_data;
620
621 unsigned char hs_gain, hs_pop;
622 struct twl4030_priv *twl4030 = codec->private_data;
623 /* Base values for ramp delay calculation: 2^19 - 2^26 */
624 unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
625 8388608, 16777216, 33554432, 67108864};
626
627 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
628 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
629
630 /* Enable external mute control, this dramatically reduces
631 * the pop-noise */
632 if (setup && setup->hs_extmute) {
633 if (setup->set_hs_extmute) {
634 setup->set_hs_extmute(1);
635 } else {
636 hs_pop |= TWL4030_EXTMUTE;
637 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
638 }
639 }
640
641 if (ramp) {
642 /* Headset ramp-up according to the TRM */
643 hs_pop |= TWL4030_VMID_EN;
644 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
645 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
646 hs_pop |= TWL4030_RAMP_EN;
647 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
648 /* Wait ramp delay time + 1, so the VMID can settle */
649 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
650 twl4030->sysclk) + 1);
651 } else {
652 /* Headset ramp-down _not_ according to
653 * the TRM, but in a way that it is working */
608 hs_pop &= ~TWL4030_RAMP_EN; 654 hs_pop &= ~TWL4030_RAMP_EN;
609 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 655 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
656 /* Wait ramp delay time + 1, so the VMID can settle */
657 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
658 twl4030->sysclk) + 1);
610 /* Bypass the reg_cache to mute the headset */ 659 /* Bypass the reg_cache to mute the headset */
611 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 660 twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
612 hs_gain & (~0x0f), 661 hs_gain & (~0x0f),
613 TWL4030_REG_HS_GAIN_SET); 662 TWL4030_REG_HS_GAIN_SET);
663
614 hs_pop &= ~TWL4030_VMID_EN; 664 hs_pop &= ~TWL4030_VMID_EN;
615 twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); 665 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
666 }
667
668 /* Disable external mute */
669 if (setup && setup->hs_extmute) {
670 if (setup->set_hs_extmute) {
671 setup->set_hs_extmute(0);
672 } else {
673 hs_pop &= ~TWL4030_EXTMUTE;
674 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
675 }
676 }
677}
678
679static int headsetlpga_event(struct snd_soc_dapm_widget *w,
680 struct snd_kcontrol *kcontrol, int event)
681{
682 struct twl4030_priv *twl4030 = w->codec->private_data;
683
684 switch (event) {
685 case SND_SOC_DAPM_POST_PMU:
686 /* Do the ramp-up only once */
687 if (!twl4030->hsr_enabled)
688 headset_ramp(w->codec, 1);
689
690 twl4030->hsl_enabled = 1;
691 break;
692 case SND_SOC_DAPM_POST_PMD:
693 /* Do the ramp-down only if both headsetL/R is disabled */
694 if (!twl4030->hsr_enabled)
695 headset_ramp(w->codec, 0);
696
697 twl4030->hsl_enabled = 0;
698 break;
699 }
700 return 0;
701}
702
703static int headsetrpga_event(struct snd_soc_dapm_widget *w,
704 struct snd_kcontrol *kcontrol, int event)
705{
706 struct twl4030_priv *twl4030 = w->codec->private_data;
707
708 switch (event) {
709 case SND_SOC_DAPM_POST_PMU:
710 /* Do the ramp-up only once */
711 if (!twl4030->hsl_enabled)
712 headset_ramp(w->codec, 1);
713
714 twl4030->hsr_enabled = 1;
715 break;
716 case SND_SOC_DAPM_POST_PMD:
717 /* Do the ramp-down only if both headsetL/R is disabled */
718 if (!twl4030->hsl_enabled)
719 headset_ramp(w->codec, 0);
720
721 twl4030->hsr_enabled = 0;
616 break; 722 break;
617 } 723 }
618 return 0; 724 return 0;
@@ -624,11 +730,23 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
624 struct soc_mixer_control *m = 730 struct soc_mixer_control *m =
625 (struct soc_mixer_control *)w->kcontrols->private_value; 731 (struct soc_mixer_control *)w->kcontrols->private_value;
626 struct twl4030_priv *twl4030 = w->codec->private_data; 732 struct twl4030_priv *twl4030 = w->codec->private_data;
627 unsigned char reg; 733 unsigned char reg, misc;
628 734
629 reg = twl4030_read_reg_cache(w->codec, m->reg); 735 reg = twl4030_read_reg_cache(w->codec, m->reg);
630 736
631 if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { 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) {
632 /* Analog bypass */ 750 /* Analog bypass */
633 if (reg & (1 << m->shift)) 751 if (reg & (1 << m->shift))
634 twl4030->bypass_state |= 752 twl4030->bypass_state |=
@@ -636,14 +754,28 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
636 else 754 else
637 twl4030->bypass_state &= 755 twl4030->bypass_state &=
638 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); 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);
639 } else { 763 } else {
640 /* Digital bypass */ 764 /* Digital bypass */
641 if (reg & (0x7 << m->shift)) 765 if (reg & (0x7 << m->shift))
642 twl4030->bypass_state |= (1 << (m->shift ? 5 : 4)); 766 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
643 else 767 else
644 twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4)); 768 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
645 } 769 }
646 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
647 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { 779 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
648 if (twl4030->bypass_state) 780 if (twl4030->bypass_state)
649 twl4030_codec_mute(w->codec, 0); 781 twl4030_codec_mute(w->codec, 0);
@@ -810,6 +942,48 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
810 return err; 942 return err;
811} 943}
812 944
945/* Codec operation modes */
946static const char *twl4030_op_modes_texts[] = {
947 "Option 2 (voice/audio)", "Option 1 (audio)"
948};
949
950static const struct soc_enum twl4030_op_modes_enum =
951 SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0,
952 ARRAY_SIZE(twl4030_op_modes_texts),
953 twl4030_op_modes_texts);
954
955static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
956 struct snd_ctl_elem_value *ucontrol)
957{
958 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
959 struct twl4030_priv *twl4030 = codec->private_data;
960 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
961 unsigned short val;
962 unsigned short mask, bitmask;
963
964 if (twl4030->configured) {
965 printk(KERN_ERR "twl4030 operation mode cannot be "
966 "changed on-the-fly\n");
967 return -EBUSY;
968 }
969
970 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
971 ;
972 if (ucontrol->value.enumerated.item[0] > e->max - 1)
973 return -EINVAL;
974
975 val = ucontrol->value.enumerated.item[0] << e->shift_l;
976 mask = (bitmask - 1) << e->shift_l;
977 if (e->shift_l != e->shift_r) {
978 if (ucontrol->value.enumerated.item[1] > e->max - 1)
979 return -EINVAL;
980 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
981 mask |= (bitmask - 1) << e->shift_r;
982 }
983
984 return snd_soc_update_bits(codec, e->reg, mask, val);
985}
986
813/* 987/*
814 * FGAIN volume control: 988 * FGAIN volume control:
815 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) 989 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
@@ -824,6 +998,12 @@ static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
824static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0); 998static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
825 999
826/* 1000/*
1001 * Voice Downlink GAIN volume control:
1002 * from -37 to 12 dB in 1 dB steps (mute instead of -37 dB)
1003 */
1004static DECLARE_TLV_DB_SCALE(digital_voice_downlink_tlv, -3700, 100, 1);
1005
1006/*
827 * Analog playback gain 1007 * Analog playback gain
828 * -24 dB to 12 dB in 2 dB steps 1008 * -24 dB to 12 dB in 2 dB steps
829 */ 1009 */
@@ -853,6 +1033,16 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
853 */ 1033 */
854static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); 1034static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
855 1035
1036/* AVADC clock priority */
1037static const char *twl4030_avadc_clk_priority_texts[] = {
1038 "Voice high priority", "HiFi high priority"
1039};
1040
1041static const struct soc_enum twl4030_avadc_clk_priority_enum =
1042 SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
1043 ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
1044 twl4030_avadc_clk_priority_texts);
1045
856static const char *twl4030_rampdelay_texts[] = { 1046static const char *twl4030_rampdelay_texts[] = {
857 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", 1047 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
858 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", 1048 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
@@ -864,7 +1054,32 @@ static const struct soc_enum twl4030_rampdelay_enum =
864 ARRAY_SIZE(twl4030_rampdelay_texts), 1054 ARRAY_SIZE(twl4030_rampdelay_texts),
865 twl4030_rampdelay_texts); 1055 twl4030_rampdelay_texts);
866 1056
1057/* Vibra H-bridge direction mode */
1058static const char *twl4030_vibradirmode_texts[] = {
1059 "Vibra H-bridge direction", "Audio data MSB",
1060};
1061
1062static const struct soc_enum twl4030_vibradirmode_enum =
1063 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5,
1064 ARRAY_SIZE(twl4030_vibradirmode_texts),
1065 twl4030_vibradirmode_texts);
1066
1067/* Vibra H-bridge direction */
1068static const char *twl4030_vibradir_texts[] = {
1069 "Positive polarity", "Negative polarity",
1070};
1071
1072static const struct soc_enum twl4030_vibradir_enum =
1073 SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1,
1074 ARRAY_SIZE(twl4030_vibradir_texts),
1075 twl4030_vibradir_texts);
1076
867static const struct snd_kcontrol_new twl4030_snd_controls[] = { 1077static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1078 /* Codec operation mode control */
1079 SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum,
1080 snd_soc_get_enum_double,
1081 snd_soc_put_twl4030_opmode_enum_double),
1082
868 /* Common playback gain controls */ 1083 /* Common playback gain controls */
869 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", 1084 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
870 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, 1085 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
@@ -893,6 +1108,16 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
893 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, 1108 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
894 1, 1, 0), 1109 1, 1, 0),
895 1110
1111 /* Common voice downlink gain controls */
1112 SOC_SINGLE_TLV("DAC Voice Digital Downlink Volume",
1113 TWL4030_REG_VRXPGA, 0, 0x31, 0, digital_voice_downlink_tlv),
1114
1115 SOC_SINGLE_TLV("DAC Voice Analog Downlink Volume",
1116 TWL4030_REG_VDL_APGA_CTL, 3, 0x12, 1, analog_tlv),
1117
1118 SOC_SINGLE("DAC Voice Analog Downlink Switch",
1119 TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
1120
896 /* Separate output gain controls */ 1121 /* Separate output gain controls */
897 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", 1122 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
898 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, 1123 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
@@ -919,7 +1144,12 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
919 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 1144 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
920 0, 3, 5, 0, input_gain_tlv), 1145 0, 3, 5, 0, input_gain_tlv),
921 1146
1147 SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum),
1148
922 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), 1149 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
1150
1151 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
1152 SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum),
923}; 1153};
924 1154
925static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { 1155static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
@@ -947,26 +1177,19 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
947 SND_SOC_DAPM_OUTPUT("CARKITR"), 1177 SND_SOC_DAPM_OUTPUT("CARKITR"),
948 SND_SOC_DAPM_OUTPUT("HFL"), 1178 SND_SOC_DAPM_OUTPUT("HFL"),
949 SND_SOC_DAPM_OUTPUT("HFR"), 1179 SND_SOC_DAPM_OUTPUT("HFR"),
1180 SND_SOC_DAPM_OUTPUT("VIBRA"),
950 1181
951 /* DACs */ 1182 /* DACs */
952 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", 1183 SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback",
953 SND_SOC_NOPM, 0, 0), 1184 SND_SOC_NOPM, 0, 0),
954 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", 1185 SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback",
955 SND_SOC_NOPM, 0, 0), 1186 SND_SOC_NOPM, 0, 0),
956 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", 1187 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback",
957 SND_SOC_NOPM, 0, 0), 1188 SND_SOC_NOPM, 0, 0),
958 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", 1189 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback",
1190 SND_SOC_NOPM, 0, 0),
1191 SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback",
959 SND_SOC_NOPM, 0, 0), 1192 SND_SOC_NOPM, 0, 0),
960
961 /* Analog PGAs */
962 SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
963 0, 0, NULL, 0),
964 SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
965 0, 0, NULL, 0),
966 SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
967 0, 0, NULL, 0),
968 SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
969 0, 0, NULL, 0),
970 1193
971 /* Analog bypasses */ 1194 /* Analog bypasses */
972 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1195 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
@@ -981,6 +1204,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
981 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1204 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
982 &twl4030_dapm_abypassl2_control, 1205 &twl4030_dapm_abypassl2_control,
983 bypass_event, SND_SOC_DAPM_POST_REG), 1206 bypass_event, SND_SOC_DAPM_POST_REG),
1207 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1208 &twl4030_dapm_abypassv_control,
1209 bypass_event, SND_SOC_DAPM_POST_REG),
984 1210
985 /* Digital bypasses */ 1211 /* Digital bypasses */
986 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1212 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
@@ -989,43 +1215,103 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
989 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1215 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
990 &twl4030_dapm_dbypassr_control, bypass_event, 1216 &twl4030_dapm_dbypassr_control, bypass_event,
991 SND_SOC_DAPM_POST_REG), 1217 SND_SOC_DAPM_POST_REG),
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),
992 1221
993 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1222 /* Digital mixers, power control for the physical DACs */
994 0, 0, NULL, 0), 1223 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
995 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1224 TWL4030_REG_AVDAC_CTL, 0, 0, NULL, 0),
996 1, 0, NULL, 0), 1225 SND_SOC_DAPM_MIXER("Digital L1 Playback Mixer",
997 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1226 TWL4030_REG_AVDAC_CTL, 1, 0, NULL, 0),
998 2, 0, NULL, 0), 1227 SND_SOC_DAPM_MIXER("Digital R2 Playback Mixer",
999 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", TWL4030_REG_AVDAC_CTL, 1228 TWL4030_REG_AVDAC_CTL, 2, 0, NULL, 0),
1000 3, 0, NULL, 0), 1229 SND_SOC_DAPM_MIXER("Digital L2 Playback Mixer",
1001 1230 TWL4030_REG_AVDAC_CTL, 3, 0, NULL, 0),
1002 /* Output MUX controls */ 1231 SND_SOC_DAPM_MIXER("Digital Voice Playback Mixer",
1232 TWL4030_REG_AVDAC_CTL, 4, 0, NULL, 0),
1233
1234 /* Analog mixers, power control for the physical PGAs */
1235 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer",
1236 TWL4030_REG_ARXR1_APGA_CTL, 0, 0, NULL, 0),
1237 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer",
1238 TWL4030_REG_ARXL1_APGA_CTL, 0, 0, NULL, 0),
1239 SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer",
1240 TWL4030_REG_ARXR2_APGA_CTL, 0, 0, NULL, 0),
1241 SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer",
1242 TWL4030_REG_ARXL2_APGA_CTL, 0, 0, NULL, 0),
1243 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1244 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1245
1246 /* Output MIXER controls */
1003 /* Earpiece */ 1247 /* Earpiece */
1004 SND_SOC_DAPM_VALUE_MUX("Earpiece Mux", SND_SOC_NOPM, 0, 0, 1248 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
1005 &twl4030_dapm_earpiece_control), 1249 &twl4030_dapm_earpiece_controls[0],
1250 ARRAY_SIZE(twl4030_dapm_earpiece_controls)),
1251 SND_SOC_DAPM_PGA_E("Earpiece PGA", SND_SOC_NOPM,
1252 0, 0, NULL, 0, earpiecepga_event,
1253 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1006 /* PreDrivL/R */ 1254 /* PreDrivL/R */
1007 SND_SOC_DAPM_VALUE_MUX("PredriveL Mux", SND_SOC_NOPM, 0, 0, 1255 SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0,
1008 &twl4030_dapm_predrivel_control), 1256 &twl4030_dapm_predrivel_controls[0],
1009 SND_SOC_DAPM_VALUE_MUX("PredriveR Mux", SND_SOC_NOPM, 0, 0, 1257 ARRAY_SIZE(twl4030_dapm_predrivel_controls)),
1010 &twl4030_dapm_predriver_control), 1258 SND_SOC_DAPM_PGA_E("PredriveL PGA", SND_SOC_NOPM,
1259 0, 0, NULL, 0, predrivelpga_event,
1260 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1261 SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0,
1262 &twl4030_dapm_predriver_controls[0],
1263 ARRAY_SIZE(twl4030_dapm_predriver_controls)),
1264 SND_SOC_DAPM_PGA_E("PredriveR PGA", SND_SOC_NOPM,
1265 0, 0, NULL, 0, predriverpga_event,
1266 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1011 /* HeadsetL/R */ 1267 /* HeadsetL/R */
1012 SND_SOC_DAPM_MUX_E("HeadsetL Mux", SND_SOC_NOPM, 0, 0, 1268 SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0,
1013 &twl4030_dapm_hsol_control, headsetl_event, 1269 &twl4030_dapm_hsol_controls[0],
1014 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1270 ARRAY_SIZE(twl4030_dapm_hsol_controls)),
1015 SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, 1271 SND_SOC_DAPM_PGA_E("HeadsetL PGA", SND_SOC_NOPM,
1016 &twl4030_dapm_hsor_control), 1272 0, 0, NULL, 0, headsetlpga_event,
1273 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1274 SND_SOC_DAPM_MIXER("HeadsetR Mixer", SND_SOC_NOPM, 0, 0,
1275 &twl4030_dapm_hsor_controls[0],
1276 ARRAY_SIZE(twl4030_dapm_hsor_controls)),
1277 SND_SOC_DAPM_PGA_E("HeadsetR PGA", SND_SOC_NOPM,
1278 0, 0, NULL, 0, headsetrpga_event,
1279 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1017 /* CarkitL/R */ 1280 /* CarkitL/R */
1018 SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0, 1281 SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0,
1019 &twl4030_dapm_carkitl_control), 1282 &twl4030_dapm_carkitl_controls[0],
1020 SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0, 1283 ARRAY_SIZE(twl4030_dapm_carkitl_controls)),
1021 &twl4030_dapm_carkitr_control), 1284 SND_SOC_DAPM_PGA_E("CarkitL PGA", SND_SOC_NOPM,
1285 0, 0, NULL, 0, carkitlpga_event,
1286 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1287 SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0,
1288 &twl4030_dapm_carkitr_controls[0],
1289 ARRAY_SIZE(twl4030_dapm_carkitr_controls)),
1290 SND_SOC_DAPM_PGA_E("CarkitR PGA", SND_SOC_NOPM,
1291 0, 0, NULL, 0, carkitrpga_event,
1292 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1293
1294 /* Output MUX controls */
1022 /* HandsfreeL/R */ 1295 /* HandsfreeL/R */
1023 SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, 1296 SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
1024 &twl4030_dapm_handsfreel_control, handsfree_event, 1297 &twl4030_dapm_handsfreel_control),
1025 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1298 SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0,
1026 SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, 1299 &twl4030_dapm_handsfreelmute_control),
1027 &twl4030_dapm_handsfreer_control, handsfree_event, 1300 SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
1028 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1301 0, 0, NULL, 0, handsfreelpga_event,
1302 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1303 SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
1304 &twl4030_dapm_handsfreer_control),
1305 SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0,
1306 &twl4030_dapm_handsfreermute_control),
1307 SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
1308 0, 0, NULL, 0, handsfreerpga_event,
1309 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1310 /* Vibra */
1311 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1312 &twl4030_dapm_vibra_control),
1313 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1314 &twl4030_dapm_vibrapath_control),
1029 1315
1030 /* Introducing four virtual ADC, since TWL4030 have four channel for 1316 /* Introducing four virtual ADC, since TWL4030 have four channel for
1031 capture */ 1317 capture */
@@ -1050,11 +1336,15 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1050 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| 1336 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
1051 SND_SOC_DAPM_POST_REG), 1337 SND_SOC_DAPM_POST_REG),
1052 1338
1053 /* Analog input muxes with switch for the capture amplifiers */ 1339 /* Analog input mixers for the capture amplifiers */
1054 SND_SOC_DAPM_VALUE_MUX("Analog Left Capture Route", 1340 SND_SOC_DAPM_MIXER("Analog Left",
1055 TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_control), 1341 TWL4030_REG_ANAMICL, 4, 0,
1056 SND_SOC_DAPM_VALUE_MUX("Analog Right Capture Route", 1342 &twl4030_dapm_analoglmic_controls[0],
1057 TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_control), 1343 ARRAY_SIZE(twl4030_dapm_analoglmic_controls)),
1344 SND_SOC_DAPM_MIXER("Analog Right",
1345 TWL4030_REG_ANAMICR, 4, 0,
1346 &twl4030_dapm_analogrmic_controls[0],
1347 ARRAY_SIZE(twl4030_dapm_analogrmic_controls)),
1058 1348
1059 SND_SOC_DAPM_PGA("ADC Physical Left", 1349 SND_SOC_DAPM_PGA("ADC Physical Left",
1060 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), 1350 TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0),
@@ -1073,74 +1363,103 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1073}; 1363};
1074 1364
1075static const struct snd_soc_dapm_route intercon[] = { 1365static const struct snd_soc_dapm_route intercon[] = {
1076 {"Analog L1 Playback Mixer", NULL, "DAC Left1"}, 1366 {"Digital L1 Playback Mixer", NULL, "DAC Left1"},
1077 {"Analog R1 Playback Mixer", NULL, "DAC Right1"}, 1367 {"Digital R1 Playback Mixer", NULL, "DAC Right1"},
1078 {"Analog L2 Playback Mixer", NULL, "DAC Left2"}, 1368 {"Digital L2 Playback Mixer", NULL, "DAC Left2"},
1079 {"Analog R2 Playback Mixer", NULL, "DAC Right2"}, 1369 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1080 1370 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1081 {"ARXL1_APGA", NULL, "Analog L1 Playback Mixer"}, 1371
1082 {"ARXR1_APGA", NULL, "Analog R1 Playback Mixer"}, 1372 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1083 {"ARXL2_APGA", NULL, "Analog L2 Playback Mixer"}, 1373 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1084 {"ARXR2_APGA", NULL, "Analog R2 Playback Mixer"}, 1374 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
1375 {"Analog R2 Playback Mixer", NULL, "Digital R2 Playback Mixer"},
1376 {"Analog Voice Playback Mixer", NULL, "Digital Voice Playback Mixer"},
1085 1377
1086 /* Internal playback routings */ 1378 /* Internal playback routings */
1087 /* Earpiece */ 1379 /* Earpiece */
1088 {"Earpiece Mux", "DACL1", "ARXL1_APGA"}, 1380 {"Earpiece Mixer", "Voice", "Analog Voice Playback Mixer"},
1089 {"Earpiece Mux", "DACL2", "ARXL2_APGA"}, 1381 {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1090 {"Earpiece Mux", "DACR1", "ARXR1_APGA"}, 1382 {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1383 {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1384 {"Earpiece PGA", NULL, "Earpiece Mixer"},
1091 /* PreDrivL */ 1385 /* PreDrivL */
1092 {"PredriveL Mux", "DACL1", "ARXL1_APGA"}, 1386 {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"},
1093 {"PredriveL Mux", "DACL2", "ARXL2_APGA"}, 1387 {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1094 {"PredriveL Mux", "DACR2", "ARXR2_APGA"}, 1388 {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1389 {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1390 {"PredriveL PGA", NULL, "PredriveL Mixer"},
1095 /* PreDrivR */ 1391 /* PreDrivR */
1096 {"PredriveR Mux", "DACR1", "ARXR1_APGA"}, 1392 {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"},
1097 {"PredriveR Mux", "DACR2", "ARXR2_APGA"}, 1393 {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1098 {"PredriveR Mux", "DACL2", "ARXL2_APGA"}, 1394 {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1395 {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1396 {"PredriveR PGA", NULL, "PredriveR Mixer"},
1099 /* HeadsetL */ 1397 /* HeadsetL */
1100 {"HeadsetL Mux", "DACL1", "ARXL1_APGA"}, 1398 {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"},
1101 {"HeadsetL Mux", "DACL2", "ARXL2_APGA"}, 1399 {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1400 {"HeadsetL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1401 {"HeadsetL PGA", NULL, "HeadsetL Mixer"},
1102 /* HeadsetR */ 1402 /* HeadsetR */
1103 {"HeadsetR Mux", "DACR1", "ARXR1_APGA"}, 1403 {"HeadsetR Mixer", "Voice", "Analog Voice Playback Mixer"},
1104 {"HeadsetR Mux", "DACR2", "ARXR2_APGA"}, 1404 {"HeadsetR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1405 {"HeadsetR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1406 {"HeadsetR PGA", NULL, "HeadsetR Mixer"},
1105 /* CarkitL */ 1407 /* CarkitL */
1106 {"CarkitL Mux", "DACL1", "ARXL1_APGA"}, 1408 {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"},
1107 {"CarkitL Mux", "DACL2", "ARXL2_APGA"}, 1409 {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
1410 {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
1411 {"CarkitL PGA", NULL, "CarkitL Mixer"},
1108 /* CarkitR */ 1412 /* CarkitR */
1109 {"CarkitR Mux", "DACR1", "ARXR1_APGA"}, 1413 {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"},
1110 {"CarkitR Mux", "DACR2", "ARXR2_APGA"}, 1414 {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
1415 {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
1416 {"CarkitR PGA", NULL, "CarkitR Mixer"},
1111 /* HandsfreeL */ 1417 /* HandsfreeL */
1112 {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"}, 1418 {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"},
1113 {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"}, 1419 {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
1114 {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"}, 1420 {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
1421 {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
1422 {"HandsfreeL", "Switch", "HandsfreeL Mux"},
1423 {"HandsfreeL PGA", NULL, "HandsfreeL"},
1115 /* HandsfreeR */ 1424 /* HandsfreeR */
1116 {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"}, 1425 {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
1117 {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"}, 1426 {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
1118 {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"}, 1427 {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
1428 {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
1429 {"HandsfreeR", "Switch", "HandsfreeR Mux"},
1430 {"HandsfreeR PGA", NULL, "HandsfreeR"},
1431 /* Vibra */
1432 {"Vibra Mux", "AudioL1", "DAC Left1"},
1433 {"Vibra Mux", "AudioR1", "DAC Right1"},
1434 {"Vibra Mux", "AudioL2", "DAC Left2"},
1435 {"Vibra Mux", "AudioR2", "DAC Right2"},
1119 1436
1120 /* outputs */ 1437 /* outputs */
1121 {"OUTL", NULL, "ARXL2_APGA"}, 1438 {"OUTL", NULL, "Analog L2 Playback Mixer"},
1122 {"OUTR", NULL, "ARXR2_APGA"}, 1439 {"OUTR", NULL, "Analog R2 Playback Mixer"},
1123 {"EARPIECE", NULL, "Earpiece Mux"}, 1440 {"EARPIECE", NULL, "Earpiece PGA"},
1124 {"PREDRIVEL", NULL, "PredriveL Mux"}, 1441 {"PREDRIVEL", NULL, "PredriveL PGA"},
1125 {"PREDRIVER", NULL, "PredriveR Mux"}, 1442 {"PREDRIVER", NULL, "PredriveR PGA"},
1126 {"HSOL", NULL, "HeadsetL Mux"}, 1443 {"HSOL", NULL, "HeadsetL PGA"},
1127 {"HSOR", NULL, "HeadsetR Mux"}, 1444 {"HSOR", NULL, "HeadsetR PGA"},
1128 {"CARKITL", NULL, "CarkitL Mux"}, 1445 {"CARKITL", NULL, "CarkitL PGA"},
1129 {"CARKITR", NULL, "CarkitR Mux"}, 1446 {"CARKITR", NULL, "CarkitR PGA"},
1130 {"HFL", NULL, "HandsfreeL Mux"}, 1447 {"HFL", NULL, "HandsfreeL PGA"},
1131 {"HFR", NULL, "HandsfreeR Mux"}, 1448 {"HFR", NULL, "HandsfreeR PGA"},
1449 {"Vibra Route", "Audio", "Vibra Mux"},
1450 {"VIBRA", NULL, "Vibra Route"},
1132 1451
1133 /* Capture path */ 1452 /* Capture path */
1134 {"Analog Left Capture Route", "Main mic", "MAINMIC"}, 1453 {"Analog Left", "Main Mic Capture Switch", "MAINMIC"},
1135 {"Analog Left Capture Route", "Headset mic", "HSMIC"}, 1454 {"Analog Left", "Headset Mic Capture Switch", "HSMIC"},
1136 {"Analog Left Capture Route", "AUXL", "AUXL"}, 1455 {"Analog Left", "AUXL Capture Switch", "AUXL"},
1137 {"Analog Left Capture Route", "Carkit mic", "CARKITMIC"}, 1456 {"Analog Left", "Carkit Mic Capture Switch", "CARKITMIC"},
1138 1457
1139 {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, 1458 {"Analog Right", "Sub Mic Capture Switch", "SUBMIC"},
1140 {"Analog Right Capture Route", "AUXR", "AUXR"}, 1459 {"Analog Right", "AUXR Capture Switch", "AUXR"},
1141 1460
1142 {"ADC Physical Left", NULL, "Analog Left Capture Route"}, 1461 {"ADC Physical Left", NULL, "Analog Left"},
1143 {"ADC Physical Right", NULL, "Analog Right Capture Route"}, 1462 {"ADC Physical Right", NULL, "Analog Right"},
1144 1463
1145 {"Digimic0 Enable", NULL, "DIGIMIC0"}, 1464 {"Digimic0 Enable", NULL, "DIGIMIC0"},
1146 {"Digimic1 Enable", NULL, "DIGIMIC1"}, 1465 {"Digimic1 Enable", NULL, "DIGIMIC1"},
@@ -1164,22 +1483,26 @@ static const struct snd_soc_dapm_route intercon[] = {
1164 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1483 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
1165 1484
1166 /* Analog bypass routes */ 1485 /* Analog bypass routes */
1167 {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"}, 1486 {"Right1 Analog Loopback", "Switch", "Analog Right"},
1168 {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1487 {"Left1 Analog Loopback", "Switch", "Analog Left"},
1169 {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, 1488 {"Right2 Analog Loopback", "Switch", "Analog Right"},
1170 {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, 1489 {"Left2 Analog Loopback", "Switch", "Analog Left"},
1490 {"Voice Analog Loopback", "Switch", "Analog Left"},
1171 1491
1172 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1492 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1173 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1493 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1174 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1494 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
1175 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, 1495 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
1496 {"Analog Voice Playback Mixer", NULL, "Voice Analog Loopback"},
1176 1497
1177 /* Digital bypass routes */ 1498 /* Digital bypass routes */
1178 {"Right Digital Loopback", "Volume", "TX1 Capture Route"}, 1499 {"Right Digital Loopback", "Volume", "TX1 Capture Route"},
1179 {"Left Digital Loopback", "Volume", "TX1 Capture Route"}, 1500 {"Left Digital Loopback", "Volume", "TX1 Capture Route"},
1501 {"Voice Digital Loopback", "Volume", "TX2 Capture Route"},
1180 1502
1181 {"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"}, 1503 {"Digital R2 Playback Mixer", NULL, "Right Digital Loopback"},
1182 {"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"}, 1504 {"Digital L2 Playback Mixer", NULL, "Left Digital Loopback"},
1505 {"Digital Voice Playback Mixer", NULL, "Voice Digital Loopback"},
1183 1506
1184}; 1507};
1185 1508
@@ -1226,6 +1549,58 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1226 return 0; 1549 return 0;
1227} 1550}
1228 1551
1552static void twl4030_constraints(struct twl4030_priv *twl4030,
1553 struct snd_pcm_substream *mst_substream)
1554{
1555 struct snd_pcm_substream *slv_substream;
1556
1557 /* Pick the stream, which need to be constrained */
1558 if (mst_substream == twl4030->master_substream)
1559 slv_substream = twl4030->slave_substream;
1560 else if (mst_substream == twl4030->slave_substream)
1561 slv_substream = twl4030->master_substream;
1562 else /* This should not happen.. */
1563 return;
1564
1565 /* Set the constraints according to the already configured stream */
1566 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1567 SNDRV_PCM_HW_PARAM_RATE,
1568 twl4030->rate,
1569 twl4030->rate);
1570
1571 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1572 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1573 twl4030->sample_bits,
1574 twl4030->sample_bits);
1575
1576 snd_pcm_hw_constraint_minmax(slv_substream->runtime,
1577 SNDRV_PCM_HW_PARAM_CHANNELS,
1578 twl4030->channels,
1579 twl4030->channels);
1580}
1581
1582/* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for
1583 * capture has to be enabled/disabled. */
1584static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
1585 int enable)
1586{
1587 u8 reg, mask;
1588
1589 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1590
1591 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1592 mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN;
1593 else
1594 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1595
1596 if (enable)
1597 reg |= mask;
1598 else
1599 reg &= ~mask;
1600
1601 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1602}
1603
1229static int twl4030_startup(struct snd_pcm_substream *substream, 1604static int twl4030_startup(struct snd_pcm_substream *substream,
1230 struct snd_soc_dai *dai) 1605 struct snd_soc_dai *dai)
1231{ 1606{
@@ -1234,26 +1609,25 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
1234 struct snd_soc_codec *codec = socdev->card->codec; 1609 struct snd_soc_codec *codec = socdev->card->codec;
1235 struct twl4030_priv *twl4030 = codec->private_data; 1610 struct twl4030_priv *twl4030 = codec->private_data;
1236 1611
1237 /* If we already have a playback or capture going then constrain
1238 * this substream to match it.
1239 */
1240 if (twl4030->master_substream) { 1612 if (twl4030->master_substream) {
1241 struct snd_pcm_runtime *master_runtime;
1242 master_runtime = twl4030->master_substream->runtime;
1243
1244 snd_pcm_hw_constraint_minmax(substream->runtime,
1245 SNDRV_PCM_HW_PARAM_RATE,
1246 master_runtime->rate,
1247 master_runtime->rate);
1248
1249 snd_pcm_hw_constraint_minmax(substream->runtime,
1250 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1251 master_runtime->sample_bits,
1252 master_runtime->sample_bits);
1253
1254 twl4030->slave_substream = substream; 1613 twl4030->slave_substream = substream;
1255 } else 1614 /* The DAI has one configuration for playback and capture, so
1615 * if the DAI has been already configured then constrain this
1616 * substream to match it. */
1617 if (twl4030->configured)
1618 twl4030_constraints(twl4030, twl4030->master_substream);
1619 } else {
1620 if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
1621 TWL4030_OPTION_1)) {
1622 /* In option2 4 channel is not supported, set the
1623 * constraint for the first stream for channels, the
1624 * second stream will 'inherit' this cosntraint */
1625 snd_pcm_hw_constraint_minmax(substream->runtime,
1626 SNDRV_PCM_HW_PARAM_CHANNELS,
1627 2, 2);
1628 }
1256 twl4030->master_substream = substream; 1629 twl4030->master_substream = substream;
1630 }
1257 1631
1258 return 0; 1632 return 0;
1259} 1633}
@@ -1270,6 +1644,17 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
1270 twl4030->master_substream = twl4030->slave_substream; 1644 twl4030->master_substream = twl4030->slave_substream;
1271 1645
1272 twl4030->slave_substream = NULL; 1646 twl4030->slave_substream = NULL;
1647
1648 /* If all streams are closed, or the remaining stream has not yet
1649 * been configured than set the DAI as not configured. */
1650 if (!twl4030->master_substream)
1651 twl4030->configured = 0;
1652 else if (!twl4030->master_substream->runtime->channels)
1653 twl4030->configured = 0;
1654
1655 /* If the closing substream had 4 channel, do the necessary cleanup */
1656 if (substream->runtime->channels == 4)
1657 twl4030_tdm_enable(codec, substream->stream, 0);
1273} 1658}
1274 1659
1275static int twl4030_hw_params(struct snd_pcm_substream *substream, 1660static int twl4030_hw_params(struct snd_pcm_substream *substream,
@@ -1282,8 +1667,22 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1282 struct twl4030_priv *twl4030 = codec->private_data; 1667 struct twl4030_priv *twl4030 = codec->private_data;
1283 u8 mode, old_mode, format, old_format; 1668 u8 mode, old_mode, format, old_format;
1284 1669
1285 if (substream == twl4030->slave_substream) 1670 /* If the substream has 4 channel, do the necessary setup */
1286 /* Ignoring hw_params for slave substream */ 1671 if (params_channels(params) == 4) {
1672 format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1673 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
1674
1675 /* Safety check: are we in the correct operating mode and
1676 * the interface is in TDM mode? */
1677 if ((mode & TWL4030_OPTION_1) &&
1678 ((format & TWL4030_AIF_FORMAT) == TWL4030_AIF_FORMAT_TDM))
1679 twl4030_tdm_enable(codec, substream->stream, 1);
1680 else
1681 return -EINVAL;
1682 }
1683
1684 if (twl4030->configured)
1685 /* Ignoring hw_params for already configured DAI */
1287 return 0; 1686 return 0;
1288 1687
1289 /* bit rate */ 1688 /* bit rate */
@@ -1363,6 +1762,21 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1363 /* set CODECPDZ afterwards */ 1762 /* set CODECPDZ afterwards */
1364 twl4030_codec_enable(codec, 1); 1763 twl4030_codec_enable(codec, 1);
1365 } 1764 }
1765
1766 /* Store the important parameters for the DAI configuration and set
1767 * the DAI as configured */
1768 twl4030->configured = 1;
1769 twl4030->rate = params_rate(params);
1770 twl4030->sample_bits = hw_param_interval(params,
1771 SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
1772 twl4030->channels = params_channels(params);
1773
1774 /* If both playback and capture streams are open, and one of them
1775 * is setting the hw parameters right now (since we are here), set
1776 * constraints to the other stream to match the current one. */
1777 if (twl4030->slave_substream)
1778 twl4030_constraints(twl4030, substream);
1779
1366 return 0; 1780 return 0;
1367} 1781}
1368 1782
@@ -1370,17 +1784,21 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1370 int clk_id, unsigned int freq, int dir) 1784 int clk_id, unsigned int freq, int dir)
1371{ 1785{
1372 struct snd_soc_codec *codec = codec_dai->codec; 1786 struct snd_soc_codec *codec = codec_dai->codec;
1787 struct twl4030_priv *twl4030 = codec->private_data;
1373 u8 infreq; 1788 u8 infreq;
1374 1789
1375 switch (freq) { 1790 switch (freq) {
1376 case 19200000: 1791 case 19200000:
1377 infreq = TWL4030_APLL_INFREQ_19200KHZ; 1792 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1793 twl4030->sysclk = 19200;
1378 break; 1794 break;
1379 case 26000000: 1795 case 26000000:
1380 infreq = TWL4030_APLL_INFREQ_26000KHZ; 1796 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1797 twl4030->sysclk = 26000;
1381 break; 1798 break;
1382 case 38400000: 1799 case 38400000:
1383 infreq = TWL4030_APLL_INFREQ_38400KHZ; 1800 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1801 twl4030->sysclk = 38400;
1384 break; 1802 break;
1385 default: 1803 default:
1386 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", 1804 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
@@ -1424,6 +1842,9 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1424 case SND_SOC_DAIFMT_I2S: 1842 case SND_SOC_DAIFMT_I2S:
1425 format |= TWL4030_AIF_FORMAT_CODEC; 1843 format |= TWL4030_AIF_FORMAT_CODEC;
1426 break; 1844 break;
1845 case SND_SOC_DAIFMT_DSP_A:
1846 format |= TWL4030_AIF_FORMAT_TDM;
1847 break;
1427 default: 1848 default:
1428 return -EINVAL; 1849 return -EINVAL;
1429 } 1850 }
@@ -1443,6 +1864,206 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1443 return 0; 1864 return 0;
1444} 1865}
1445 1866
1867static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
1868{
1869 struct snd_soc_codec *codec = dai->codec;
1870 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1871
1872 if (tristate)
1873 reg |= TWL4030_AIF_TRI_EN;
1874 else
1875 reg &= ~TWL4030_AIF_TRI_EN;
1876
1877 return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg);
1878}
1879
1880/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
1881 * (VTXL, VTXR) for uplink has to be enabled/disabled. */
1882static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
1883 int enable)
1884{
1885 u8 reg, mask;
1886
1887 reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
1888
1889 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1890 mask = TWL4030_ARXL1_VRX_EN;
1891 else
1892 mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN;
1893
1894 if (enable)
1895 reg |= mask;
1896 else
1897 reg &= ~mask;
1898
1899 twl4030_write(codec, TWL4030_REG_OPTION, reg);
1900}
1901
1902static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1903 struct snd_soc_dai *dai)
1904{
1905 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1906 struct snd_soc_device *socdev = rtd->socdev;
1907 struct snd_soc_codec *codec = socdev->card->codec;
1908 u8 infreq;
1909 u8 mode;
1910
1911 /* If the system master clock is not 26MHz, the voice PCM interface is
1912 * not avilable.
1913 */
1914 infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL)
1915 & TWL4030_APLL_INFREQ;
1916
1917 if (infreq != TWL4030_APLL_INFREQ_26000KHZ) {
1918 printk(KERN_ERR "TWL4030 voice startup: "
1919 "MCLK is not 26MHz, call set_sysclk() on init\n");
1920 return -EINVAL;
1921 }
1922
1923 /* If the codec mode is not option2, the voice PCM interface is not
1924 * avilable.
1925 */
1926 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1927 & TWL4030_OPT_MODE;
1928
1929 if (mode != TWL4030_OPTION_2) {
1930 printk(KERN_ERR "TWL4030 voice startup: "
1931 "the codec mode is not option2\n");
1932 return -EINVAL;
1933 }
1934
1935 return 0;
1936}
1937
1938static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
1939 struct snd_soc_dai *dai)
1940{
1941 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1942 struct snd_soc_device *socdev = rtd->socdev;
1943 struct snd_soc_codec *codec = socdev->card->codec;
1944
1945 /* Enable voice digital filters */
1946 twl4030_voice_enable(codec, substream->stream, 0);
1947}
1948
1949static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
1950 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1951{
1952 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1953 struct snd_soc_device *socdev = rtd->socdev;
1954 struct snd_soc_codec *codec = socdev->card->codec;
1955 u8 old_mode, mode;
1956
1957 /* Enable voice digital filters */
1958 twl4030_voice_enable(codec, substream->stream, 1);
1959
1960 /* bit rate */
1961 old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
1962 & ~(TWL4030_CODECPDZ);
1963 mode = old_mode;
1964
1965 switch (params_rate(params)) {
1966 case 8000:
1967 mode &= ~(TWL4030_SEL_16K);
1968 break;
1969 case 16000:
1970 mode |= TWL4030_SEL_16K;
1971 break;
1972 default:
1973 printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
1974 params_rate(params));
1975 return -EINVAL;
1976 }
1977
1978 if (mode != old_mode) {
1979 /* change rate and set CODECPDZ */
1980 twl4030_codec_enable(codec, 0);
1981 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1982 twl4030_codec_enable(codec, 1);
1983 }
1984
1985 return 0;
1986}
1987
1988static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1989 int clk_id, unsigned int freq, int dir)
1990{
1991 struct snd_soc_codec *codec = codec_dai->codec;
1992 u8 infreq;
1993
1994 switch (freq) {
1995 case 26000000:
1996 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1997 break;
1998 default:
1999 printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n",
2000 freq);
2001 return -EINVAL;
2002 }
2003
2004 infreq |= TWL4030_APLL_EN;
2005 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
2006
2007 return 0;
2008}
2009
2010static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
2011 unsigned int fmt)
2012{
2013 struct snd_soc_codec *codec = codec_dai->codec;
2014 u8 old_format, format;
2015
2016 /* get format */
2017 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
2018 format = old_format;
2019
2020 /* set master/slave audio interface */
2021 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2022 case SND_SOC_DAIFMT_CBM_CFM:
2023 format &= ~(TWL4030_VIF_SLAVE_EN);
2024 break;
2025 case SND_SOC_DAIFMT_CBS_CFS:
2026 format |= TWL4030_VIF_SLAVE_EN;
2027 break;
2028 default:
2029 return -EINVAL;
2030 }
2031
2032 /* clock inversion */
2033 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2034 case SND_SOC_DAIFMT_IB_NF:
2035 format &= ~(TWL4030_VIF_FORMAT);
2036 break;
2037 case SND_SOC_DAIFMT_NB_IF:
2038 format |= TWL4030_VIF_FORMAT;
2039 break;
2040 default:
2041 return -EINVAL;
2042 }
2043
2044 if (format != old_format) {
2045 /* change format and set CODECPDZ */
2046 twl4030_codec_enable(codec, 0);
2047 twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
2048 twl4030_codec_enable(codec, 1);
2049 }
2050
2051 return 0;
2052}
2053
2054static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
2055{
2056 struct snd_soc_codec *codec = dai->codec;
2057 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
2058
2059 if (tristate)
2060 reg |= TWL4030_VIF_TRI_EN;
2061 else
2062 reg &= ~TWL4030_VIF_TRI_EN;
2063
2064 return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg);
2065}
2066
1446#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 2067#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
1447#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 2068#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1448 2069
@@ -1452,23 +2073,51 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
1452 .hw_params = twl4030_hw_params, 2073 .hw_params = twl4030_hw_params,
1453 .set_sysclk = twl4030_set_dai_sysclk, 2074 .set_sysclk = twl4030_set_dai_sysclk,
1454 .set_fmt = twl4030_set_dai_fmt, 2075 .set_fmt = twl4030_set_dai_fmt,
2076 .set_tristate = twl4030_set_tristate,
2077};
2078
2079static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
2080 .startup = twl4030_voice_startup,
2081 .shutdown = twl4030_voice_shutdown,
2082 .hw_params = twl4030_voice_hw_params,
2083 .set_sysclk = twl4030_voice_set_dai_sysclk,
2084 .set_fmt = twl4030_voice_set_dai_fmt,
2085 .set_tristate = twl4030_voice_set_tristate,
1455}; 2086};
1456 2087
1457struct snd_soc_dai twl4030_dai = { 2088struct snd_soc_dai twl4030_dai[] = {
2089{
1458 .name = "twl4030", 2090 .name = "twl4030",
1459 .playback = { 2091 .playback = {
1460 .stream_name = "Playback", 2092 .stream_name = "HiFi Playback",
1461 .channels_min = 2, 2093 .channels_min = 2,
1462 .channels_max = 2, 2094 .channels_max = 4,
1463 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000, 2095 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
1464 .formats = TWL4030_FORMATS,}, 2096 .formats = TWL4030_FORMATS,},
1465 .capture = { 2097 .capture = {
1466 .stream_name = "Capture", 2098 .stream_name = "Capture",
1467 .channels_min = 2, 2099 .channels_min = 2,
1468 .channels_max = 2, 2100 .channels_max = 4,
1469 .rates = TWL4030_RATES, 2101 .rates = TWL4030_RATES,
1470 .formats = TWL4030_FORMATS,}, 2102 .formats = TWL4030_FORMATS,},
1471 .ops = &twl4030_dai_ops, 2103 .ops = &twl4030_dai_ops,
2104},
2105{
2106 .name = "twl4030 Voice",
2107 .playback = {
2108 .stream_name = "Voice Playback",
2109 .channels_min = 1,
2110 .channels_max = 1,
2111 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2112 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2113 .capture = {
2114 .stream_name = "Capture",
2115 .channels_min = 1,
2116 .channels_max = 2,
2117 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
2118 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
2119 .ops = &twl4030_dai_voice_ops,
2120},
1472}; 2121};
1473EXPORT_SYMBOL_GPL(twl4030_dai); 2122EXPORT_SYMBOL_GPL(twl4030_dai);
1474 2123
@@ -1500,6 +2149,8 @@ static int twl4030_resume(struct platform_device *pdev)
1500static int twl4030_init(struct snd_soc_device *socdev) 2149static int twl4030_init(struct snd_soc_device *socdev)
1501{ 2150{
1502 struct snd_soc_codec *codec = socdev->card->codec; 2151 struct snd_soc_codec *codec = socdev->card->codec;
2152 struct twl4030_setup_data *setup = socdev->codec_data;
2153 struct twl4030_priv *twl4030 = codec->private_data;
1503 int ret = 0; 2154 int ret = 0;
1504 2155
1505 printk(KERN_INFO "TWL4030 Audio Codec init \n"); 2156 printk(KERN_INFO "TWL4030 Audio Codec init \n");
@@ -1509,14 +2160,31 @@ static int twl4030_init(struct snd_soc_device *socdev)
1509 codec->read = twl4030_read_reg_cache; 2160 codec->read = twl4030_read_reg_cache;
1510 codec->write = twl4030_write; 2161 codec->write = twl4030_write;
1511 codec->set_bias_level = twl4030_set_bias_level; 2162 codec->set_bias_level = twl4030_set_bias_level;
1512 codec->dai = &twl4030_dai; 2163 codec->dai = twl4030_dai;
1513 codec->num_dai = 1; 2164 codec->num_dai = ARRAY_SIZE(twl4030_dai),
1514 codec->reg_cache_size = sizeof(twl4030_reg); 2165 codec->reg_cache_size = sizeof(twl4030_reg);
1515 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), 2166 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
1516 GFP_KERNEL); 2167 GFP_KERNEL);
1517 if (codec->reg_cache == NULL) 2168 if (codec->reg_cache == NULL)
1518 return -ENOMEM; 2169 return -ENOMEM;
1519 2170
2171 /* Configuration for headset ramp delay from setup data */
2172 if (setup) {
2173 unsigned char hs_pop;
2174
2175 if (setup->sysclk)
2176 twl4030->sysclk = setup->sysclk;
2177 else
2178 twl4030->sysclk = 26000;
2179
2180 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2181 hs_pop &= ~TWL4030_RAMP_DELAY;
2182 hs_pop |= (setup->ramp_delay_value << 2);
2183 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2184 } else {
2185 twl4030->sysclk = 26000;
2186 }
2187
1520 /* register pcms */ 2188 /* register pcms */
1521 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2189 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1522 if (ret < 0) { 2190 if (ret < 0) {
@@ -1604,13 +2272,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
1604 2272
1605static int __init twl4030_modinit(void) 2273static int __init twl4030_modinit(void)
1606{ 2274{
1607 return snd_soc_register_dai(&twl4030_dai); 2275 return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1608} 2276}
1609module_init(twl4030_modinit); 2277module_init(twl4030_modinit);
1610 2278
1611static void __exit twl4030_exit(void) 2279static void __exit twl4030_exit(void)
1612{ 2280{
1613 snd_soc_unregister_dai(&twl4030_dai); 2281 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
1614} 2282}
1615module_exit(twl4030_exit); 2283module_exit(twl4030_exit);
1616 2284
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index cb63765db1df..2b4bfa23f985 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -92,8 +92,9 @@
92#define TWL4030_REG_VIBRA_PWM_SET 0x47 92#define TWL4030_REG_VIBRA_PWM_SET 0x47
93#define TWL4030_REG_ANAMIC_GAIN 0x48 93#define TWL4030_REG_ANAMIC_GAIN 0x48
94#define TWL4030_REG_MISC_SET_2 0x49 94#define TWL4030_REG_MISC_SET_2 0x49
95#define TWL4030_REG_SW_SHADOW 0x4A
95 96
96#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) 97#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
97 98
98/* Bitfield Definitions */ 99/* Bitfield Definitions */
99 100
@@ -110,9 +111,22 @@
110#define TWL4030_APLL_RATE_44100 0x90 111#define TWL4030_APLL_RATE_44100 0x90
111#define TWL4030_APLL_RATE_48000 0xA0 112#define TWL4030_APLL_RATE_48000 0xA0
112#define TWL4030_APLL_RATE_96000 0xE0 113#define TWL4030_APLL_RATE_96000 0xE0
113#define TWL4030_SEL_16K 0x04 114#define TWL4030_SEL_16K 0x08
114#define TWL4030_CODECPDZ 0x02 115#define TWL4030_CODECPDZ 0x02
115#define TWL4030_OPT_MODE 0x01 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)
116 130
117/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */ 131/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
118 132
@@ -171,6 +185,17 @@
171#define TWL4030_CLK256FS_EN 0x02 185#define TWL4030_CLK256FS_EN 0x02
172#define TWL4030_AIF_EN 0x01 186#define TWL4030_AIF_EN 0x01
173 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
174/* EAR_CTL (0x21) */ 199/* EAR_CTL (0x21) */
175#define TWL4030_EAR_GAIN 0x30 200#define TWL4030_EAR_GAIN 0x30
176 201
@@ -236,7 +261,21 @@
236#define TWL4030_SMOOTH_ANAVOL_EN 0x02 261#define TWL4030_SMOOTH_ANAVOL_EN 0x02
237#define TWL4030_DIGMIC_LR_SWAP_EN 0x01 262#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
238 263
239extern struct snd_soc_dai twl4030_dai; 264/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
265#define TWL4030_HFL_EN 0x01
266#define TWL4030_HFR_EN 0x02
267
268#define TWL4030_DAI_HIFI 0
269#define TWL4030_DAI_VOICE 1
270
271extern struct snd_soc_dai twl4030_dai[2];
240extern struct snd_soc_codec_device soc_codec_dev_twl4030; 272extern struct snd_soc_codec_device soc_codec_dev_twl4030;
241 273
274struct twl4030_setup_data {
275 unsigned int ramp_delay_value;
276 unsigned int sysclk;
277 unsigned int hs_extmute:1;
278 void (*set_hs_extmute)(int mute);
279};
280
242#endif /* End of __TWL4030_AUDIO_H__ */ 281#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index ddefb8f80145..c33b92edbded 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -101,7 +101,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); 101 pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
102 102
103 if (reg >= UDA134X_REGS_NUM) { 103 if (reg >= UDA134X_REGS_NUM) {
104 printk(KERN_ERR "%s unkown register: reg: %d", 104 printk(KERN_ERR "%s unkown register: reg: %u",
105 __func__, reg); 105 __func__, reg);
106 return -EINVAL; 106 return -EINVAL;
107 } 107 }
@@ -163,7 +163,7 @@ static int uda134x_mute(struct snd_soc_dai *dai, int mute)
163 else 163 else
164 mute_reg &= ~(1<<2); 164 mute_reg &= ~(1<<2);
165 165
166 uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2)); 166 uda134x_write(codec, UDA134X_DATA010, mute_reg);
167 167
168 return 0; 168 return 0;
169} 169}
@@ -296,7 +296,7 @@ static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
296 struct snd_soc_codec *codec = codec_dai->codec; 296 struct snd_soc_codec *codec = codec_dai->codec;
297 struct uda134x_priv *uda134x = codec->private_data; 297 struct uda134x_priv *uda134x = codec->private_data;
298 298
299 pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__, 299 pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
300 clk_id, freq, dir); 300 clk_id, freq, dir);
301 301
302 /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable 302 /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 5b21594e0e58..92ec03442154 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -5,9 +5,7 @@
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 * 7 *
8 * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com> 8 * Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com>
9 * Improved support for DAPM and audio routing/mixing capabilities,
10 * added TLV support.
11 * 9 *
12 * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC 10 * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
13 * codec model. 11 * codec model.
@@ -19,26 +17,32 @@
19#include <linux/module.h> 17#include <linux/module.h>
20#include <linux/init.h> 18#include <linux/init.h>
21#include <linux/types.h> 19#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/slab.h> 20#include <linux/slab.h>
24#include <linux/errno.h> 21#include <linux/errno.h>
25#include <linux/ioctl.h> 22#include <linux/gpio.h>
26#include <linux/delay.h> 23#include <linux/delay.h>
27#include <linux/i2c.h> 24#include <linux/i2c.h>
28#include <linux/workqueue.h> 25#include <linux/workqueue.h>
29#include <sound/core.h> 26#include <sound/core.h>
30#include <sound/control.h> 27#include <sound/control.h>
31#include <sound/initval.h> 28#include <sound/initval.h>
32#include <sound/info.h>
33#include <sound/soc.h> 29#include <sound/soc.h>
34#include <sound/soc-dapm.h> 30#include <sound/soc-dapm.h>
35#include <sound/tlv.h> 31#include <sound/tlv.h>
32#include <sound/uda1380.h>
36 33
37#include "uda1380.h" 34#include "uda1380.h"
38 35
39static struct work_struct uda1380_work;
40static struct snd_soc_codec *uda1380_codec; 36static struct snd_soc_codec *uda1380_codec;
41 37
38/* codec private data */
39struct uda1380_priv {
40 struct snd_soc_codec codec;
41 u16 reg_cache[UDA1380_CACHEREGNUM];
42 unsigned int dac_clk;
43 struct work_struct work;
44};
45
42/* 46/*
43 * uda1380 register cache 47 * uda1380 register cache
44 */ 48 */
@@ -473,6 +477,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
473 struct snd_soc_pcm_runtime *rtd = substream->private_data; 477 struct snd_soc_pcm_runtime *rtd = substream->private_data;
474 struct snd_soc_device *socdev = rtd->socdev; 478 struct snd_soc_device *socdev = rtd->socdev;
475 struct snd_soc_codec *codec = socdev->card->codec; 479 struct snd_soc_codec *codec = socdev->card->codec;
480 struct uda1380_priv *uda1380 = codec->private_data;
476 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); 481 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
477 482
478 switch (cmd) { 483 switch (cmd) {
@@ -480,13 +485,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
480 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 485 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
481 uda1380_write_reg_cache(codec, UDA1380_MIXER, 486 uda1380_write_reg_cache(codec, UDA1380_MIXER,
482 mixer & ~R14_SILENCE); 487 mixer & ~R14_SILENCE);
483 schedule_work(&uda1380_work); 488 schedule_work(&uda1380->work);
484 break; 489 break;
485 case SNDRV_PCM_TRIGGER_STOP: 490 case SNDRV_PCM_TRIGGER_STOP:
486 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 491 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
487 uda1380_write_reg_cache(codec, UDA1380_MIXER, 492 uda1380_write_reg_cache(codec, UDA1380_MIXER,
488 mixer | R14_SILENCE); 493 mixer | R14_SILENCE);
489 schedule_work(&uda1380_work); 494 schedule_work(&uda1380->work);
490 break; 495 break;
491 } 496 }
492 return 0; 497 return 0;
@@ -670,44 +675,33 @@ static int uda1380_resume(struct platform_device *pdev)
670 return 0; 675 return 0;
671} 676}
672 677
673/* 678static int uda1380_probe(struct platform_device *pdev)
674 * initialise the UDA1380 driver
675 * register mixer and dsp interfaces with the kernel
676 */
677static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
678{ 679{
679 struct snd_soc_codec *codec = socdev->card->codec; 680 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
681 struct snd_soc_codec *codec;
682 struct uda1380_platform_data *pdata;
680 int ret = 0; 683 int ret = 0;
681 684
682 codec->name = "UDA1380"; 685 if (uda1380_codec == NULL) {
683 codec->owner = THIS_MODULE; 686 dev_err(&pdev->dev, "Codec device not registered\n");
684 codec->read = uda1380_read_reg_cache; 687 return -ENODEV;
685 codec->write = uda1380_write; 688 }
686 codec->set_bias_level = uda1380_set_bias_level;
687 codec->dai = uda1380_dai;
688 codec->num_dai = ARRAY_SIZE(uda1380_dai);
689 codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
690 GFP_KERNEL);
691 if (codec->reg_cache == NULL)
692 return -ENOMEM;
693 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
694 codec->reg_cache_step = 1;
695 uda1380_reset(codec);
696 689
697 uda1380_codec = codec; 690 socdev->card->codec = uda1380_codec;
698 INIT_WORK(&uda1380_work, uda1380_flush_work); 691 codec = uda1380_codec;
692 pdata = codec->dev->platform_data;
699 693
700 /* register pcms */ 694 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 695 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 696 if (ret < 0) {
703 pr_err("uda1380: failed to create pcms\n"); 697 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
704 goto pcm_err; 698 goto pcm_err;
705 } 699 }
706 700
707 /* power on device */ 701 /* power on device */
708 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 702 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
709 /* set clock input */ 703 /* set clock input */
710 switch (dac_clk) { 704 switch (pdata->dac_clk) {
711 case UDA1380_DAC_CLK_SYSCLK: 705 case UDA1380_DAC_CLK_SYSCLK:
712 uda1380_write(codec, UDA1380_CLK, 0); 706 uda1380_write(codec, UDA1380_CLK, 0);
713 break; 707 break;
@@ -716,13 +710,12 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
716 break; 710 break;
717 } 711 }
718 712
719 /* uda1380 init */
720 snd_soc_add_controls(codec, uda1380_snd_controls, 713 snd_soc_add_controls(codec, uda1380_snd_controls,
721 ARRAY_SIZE(uda1380_snd_controls)); 714 ARRAY_SIZE(uda1380_snd_controls));
722 uda1380_add_widgets(codec); 715 uda1380_add_widgets(codec);
723 ret = snd_soc_init_card(socdev); 716 ret = snd_soc_init_card(socdev);
724 if (ret < 0) { 717 if (ret < 0) {
725 pr_err("uda1380: failed to register card\n"); 718 dev_err(codec->dev, "failed to register card: %d\n", ret);
726 goto card_err; 719 goto card_err;
727 } 720 }
728 721
@@ -732,165 +725,201 @@ card_err:
732 snd_soc_free_pcms(socdev); 725 snd_soc_free_pcms(socdev);
733 snd_soc_dapm_free(socdev); 726 snd_soc_dapm_free(socdev);
734pcm_err: 727pcm_err:
735 kfree(codec->reg_cache);
736 return ret; 728 return ret;
737} 729}
738 730
739static struct snd_soc_device *uda1380_socdev; 731/* power down chip */
740 732static int uda1380_remove(struct platform_device *pdev)
741#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
742
743static int uda1380_i2c_probe(struct i2c_client *i2c,
744 const struct i2c_device_id *id)
745{ 733{
746 struct snd_soc_device *socdev = uda1380_socdev; 734 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
747 struct uda1380_setup_data *setup = socdev->codec_data;
748 struct snd_soc_codec *codec = socdev->card->codec; 735 struct snd_soc_codec *codec = socdev->card->codec;
749 int ret;
750
751 i2c_set_clientdata(i2c, codec);
752 codec->control_data = i2c;
753 736
754 ret = uda1380_init(socdev, setup->dac_clk); 737 if (codec->control_data)
755 if (ret < 0) 738 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
756 pr_err("uda1380: failed to initialise UDA1380\n");
757 739
758 return ret; 740 snd_soc_free_pcms(socdev);
759} 741 snd_soc_dapm_free(socdev);
760 742
761static int uda1380_i2c_remove(struct i2c_client *client)
762{
763 struct snd_soc_codec *codec = i2c_get_clientdata(client);
764 kfree(codec->reg_cache);
765 return 0; 743 return 0;
766} 744}
767 745
768static const struct i2c_device_id uda1380_i2c_id[] = { 746struct snd_soc_codec_device soc_codec_dev_uda1380 = {
769 { "uda1380", 0 }, 747 .probe = uda1380_probe,
770 { } 748 .remove = uda1380_remove,
771}; 749 .suspend = uda1380_suspend,
772MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); 750 .resume = uda1380_resume,
773
774static struct i2c_driver uda1380_i2c_driver = {
775 .driver = {
776 .name = "UDA1380 I2C Codec",
777 .owner = THIS_MODULE,
778 },
779 .probe = uda1380_i2c_probe,
780 .remove = uda1380_i2c_remove,
781 .id_table = uda1380_i2c_id,
782}; 751};
752EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
783 753
784static int uda1380_add_i2c_device(struct platform_device *pdev, 754static int uda1380_register(struct uda1380_priv *uda1380)
785 const struct uda1380_setup_data *setup)
786{ 755{
787 struct i2c_board_info info; 756 int ret, i;
788 struct i2c_adapter *adapter; 757 struct snd_soc_codec *codec = &uda1380->codec;
789 struct i2c_client *client; 758 struct uda1380_platform_data *pdata = codec->dev->platform_data;
790 int ret;
791 759
792 ret = i2c_add_driver(&uda1380_i2c_driver); 760 if (uda1380_codec) {
793 if (ret != 0) { 761 dev_err(codec->dev, "Another UDA1380 is registered\n");
794 dev_err(&pdev->dev, "can't add i2c driver\n"); 762 return -EINVAL;
795 return ret; 763 }
764
765 if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
766 return -EINVAL;
767
768 ret = gpio_request(pdata->gpio_power, "uda1380 power");
769 if (ret)
770 goto err_out;
771 ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
772 if (ret)
773 goto err_gpio;
774
775 gpio_direction_output(pdata->gpio_power, 1);
776
777 /* we may need to have the clock running here - pH5 */
778 gpio_direction_output(pdata->gpio_reset, 1);
779 udelay(5);
780 gpio_set_value(pdata->gpio_reset, 0);
781
782 mutex_init(&codec->mutex);
783 INIT_LIST_HEAD(&codec->dapm_widgets);
784 INIT_LIST_HEAD(&codec->dapm_paths);
785
786 codec->private_data = uda1380;
787 codec->name = "UDA1380";
788 codec->owner = THIS_MODULE;
789 codec->read = uda1380_read_reg_cache;
790 codec->write = uda1380_write;
791 codec->bias_level = SND_SOC_BIAS_OFF;
792 codec->set_bias_level = uda1380_set_bias_level;
793 codec->dai = uda1380_dai;
794 codec->num_dai = ARRAY_SIZE(uda1380_dai);
795 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
796 codec->reg_cache = &uda1380->reg_cache;
797 codec->reg_cache_step = 1;
798
799 memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
800
801 ret = uda1380_reset(codec);
802 if (ret < 0) {
803 dev_err(codec->dev, "Failed to issue reset\n");
804 goto err_reset;
796 } 805 }
797 806
798 memset(&info, 0, sizeof(struct i2c_board_info)); 807 INIT_WORK(&uda1380->work, uda1380_flush_work);
799 info.addr = setup->i2c_address; 808
800 strlcpy(info.type, "uda1380", I2C_NAME_SIZE); 809 for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
810 uda1380_dai[i].dev = codec->dev;
801 811
802 adapter = i2c_get_adapter(setup->i2c_bus); 812 uda1380_codec = codec;
803 if (!adapter) { 813
804 dev_err(&pdev->dev, "can't get i2c adapter %d\n", 814 ret = snd_soc_register_codec(codec);
805 setup->i2c_bus); 815 if (ret != 0) {
806 goto err_driver; 816 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
817 goto err_reset;
807 } 818 }
808 819
809 client = i2c_new_device(adapter, &info); 820 ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
810 i2c_put_adapter(adapter); 821 if (ret != 0) {
811 if (!client) { 822 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
812 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", 823 goto err_dai;
813 (unsigned int)info.addr);
814 goto err_driver;
815 } 824 }
816 825
817 return 0; 826 return 0;
818 827
819err_driver: 828err_dai:
820 i2c_del_driver(&uda1380_i2c_driver); 829 snd_soc_unregister_codec(codec);
821 return -ENODEV; 830err_reset:
831 gpio_set_value(pdata->gpio_power, 0);
832 gpio_free(pdata->gpio_reset);
833err_gpio:
834 gpio_free(pdata->gpio_power);
835err_out:
836 return ret;
822} 837}
823#endif
824 838
825static int uda1380_probe(struct platform_device *pdev) 839static void uda1380_unregister(struct uda1380_priv *uda1380)
826{ 840{
827 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 841 struct snd_soc_codec *codec = &uda1380->codec;
828 struct uda1380_setup_data *setup; 842 struct uda1380_platform_data *pdata = codec->dev->platform_data;
843
844 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
845 snd_soc_unregister_codec(&uda1380->codec);
846
847 gpio_set_value(pdata->gpio_power, 0);
848 gpio_free(pdata->gpio_reset);
849 gpio_free(pdata->gpio_power);
850
851 kfree(uda1380);
852 uda1380_codec = NULL;
853}
854
855#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
856static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
857 const struct i2c_device_id *id)
858{
859 struct uda1380_priv *uda1380;
829 struct snd_soc_codec *codec; 860 struct snd_soc_codec *codec;
830 int ret; 861 int ret;
831 862
832 setup = socdev->codec_data; 863 uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
833 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 864 if (uda1380 == NULL)
834 if (codec == NULL)
835 return -ENOMEM; 865 return -ENOMEM;
836 866
837 socdev->card->codec = codec; 867 codec = &uda1380->codec;
838 mutex_init(&codec->mutex); 868 codec->hw_write = (hw_write_t)i2c_master_send;
839 INIT_LIST_HEAD(&codec->dapm_widgets);
840 INIT_LIST_HEAD(&codec->dapm_paths);
841 869
842 uda1380_socdev = socdev; 870 i2c_set_clientdata(i2c, uda1380);
843 ret = -ENODEV; 871 codec->control_data = i2c;
844 872
845#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 873 codec->dev = &i2c->dev;
846 if (setup->i2c_address) {
847 codec->hw_write = (hw_write_t)i2c_master_send;
848 ret = uda1380_add_i2c_device(pdev, setup);
849 }
850#endif
851 874
875 ret = uda1380_register(uda1380);
852 if (ret != 0) 876 if (ret != 0)
853 kfree(codec); 877 kfree(uda1380);
878
854 return ret; 879 return ret;
855} 880}
856 881
857/* power down chip */ 882static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
858static int uda1380_remove(struct platform_device *pdev)
859{ 883{
860 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 884 struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
861 struct snd_soc_codec *codec = socdev->card->codec; 885 uda1380_unregister(uda1380);
862
863 if (codec->control_data)
864 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
865
866 snd_soc_free_pcms(socdev);
867 snd_soc_dapm_free(socdev);
868#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
869 i2c_unregister_device(codec->control_data);
870 i2c_del_driver(&uda1380_i2c_driver);
871#endif
872 kfree(codec);
873
874 return 0; 886 return 0;
875} 887}
876 888
877struct snd_soc_codec_device soc_codec_dev_uda1380 = { 889static const struct i2c_device_id uda1380_i2c_id[] = {
878 .probe = uda1380_probe, 890 { "uda1380", 0 },
879 .remove = uda1380_remove, 891 { }
880 .suspend = uda1380_suspend,
881 .resume = uda1380_resume,
882}; 892};
883EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); 893MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
894
895static struct i2c_driver uda1380_i2c_driver = {
896 .driver = {
897 .name = "UDA1380 I2C Codec",
898 .owner = THIS_MODULE,
899 },
900 .probe = uda1380_i2c_probe,
901 .remove = __devexit_p(uda1380_i2c_remove),
902 .id_table = uda1380_i2c_id,
903};
904#endif
884 905
885static int __init uda1380_modinit(void) 906static int __init uda1380_modinit(void)
886{ 907{
887 return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); 908 int ret;
909#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
910 ret = i2c_add_driver(&uda1380_i2c_driver);
911 if (ret != 0)
912 pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
913#endif
914 return 0;
888} 915}
889module_init(uda1380_modinit); 916module_init(uda1380_modinit);
890 917
891static void __exit uda1380_exit(void) 918static void __exit uda1380_exit(void)
892{ 919{
893 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); 920#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
921 i2c_del_driver(&uda1380_i2c_driver);
922#endif
894} 923}
895module_exit(uda1380_exit); 924module_exit(uda1380_exit);
896 925
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
index c55c17a52a12..9cefa8a54770 100644
--- a/sound/soc/codecs/uda1380.h
+++ b/sound/soc/codecs/uda1380.h
@@ -72,14 +72,6 @@
72#define R22_SKIP_DCFIL 0x0002 72#define R22_SKIP_DCFIL 0x0002
73#define R23_AGC_EN 0x0001 73#define R23_AGC_EN 0x0001
74 74
75struct uda1380_setup_data {
76 int i2c_bus;
77 unsigned short i2c_address;
78 int dac_clk;
79#define UDA1380_DAC_CLK_SYSCLK 0
80#define UDA1380_DAC_CLK_WSPLL 1
81};
82
83#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */ 75#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */
84#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ 76#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
85#define UDA1380_DAI_CAPTURE 2 /* capture DAI */ 77#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0275321ff8ab..4ded0e3a35e0 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -406,7 +406,6 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
406static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; 406static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
407static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; 407static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
408static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; 408static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
409static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
410static const char *wm8350_adcfilter[] = { "None", "High Pass" }; 409static const char *wm8350_adcfilter[] = { "None", "High Pass" };
411static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; 410static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
412static const char *wm8350_lr[] = { "Left", "Right" }; 411static const char *wm8350_lr[] = { "Left", "Right" };
@@ -416,7 +415,6 @@ static const struct soc_enum wm8350_enum[] = {
416 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), 415 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
417 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), 416 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
418 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), 417 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
419 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), 418 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
421 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), 419 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
422 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), 420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
@@ -444,10 +442,9 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
444 0, 255, 0, dac_pcm_tlv), 442 0, 255, 0, dac_pcm_tlv),
445 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), 443 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
446 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), 444 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
447 SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), 445 SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
448 SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), 446 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
449 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), 447 SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
450 SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
451 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", 448 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
452 WM8350_ADC_DIGITAL_VOLUME_L, 449 WM8350_ADC_DIGITAL_VOLUME_L,
453 WM8350_ADC_DIGITAL_VOLUME_R, 450 WM8350_ADC_DIGITAL_VOLUME_R,
@@ -993,6 +990,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
993 struct snd_soc_dai *codec_dai) 990 struct snd_soc_dai *codec_dai)
994{ 991{
995 struct snd_soc_codec *codec = codec_dai->codec; 992 struct snd_soc_codec *codec = codec_dai->codec;
993 struct wm8350 *wm8350 = codec->control_data;
996 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & 994 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
997 ~WM8350_AIF_WL_MASK; 995 ~WM8350_AIF_WL_MASK;
998 996
@@ -1012,6 +1010,19 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
1012 } 1010 }
1013 1011
1014 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); 1012 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
1013
1014 /* The sloping stopband filter is recommended for use with
1015 * lower sample rates to improve performance.
1016 */
1017 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1018 if (params_rate(params) < 24000)
1019 wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1020 WM8350_DAC_SB_FILT);
1021 else
1022 wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1023 WM8350_DAC_SB_FILT);
1024 }
1025
1015 return 0; 1026 return 0;
1016} 1027}
1017 1028
@@ -1108,7 +1119,7 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1108 if (ret < 0) 1119 if (ret < 0)
1109 return ret; 1120 return ret;
1110 dev_dbg(wm8350->dev, 1121 dev_dbg(wm8350->dev,
1111 "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d", 1122 "FLL in %u FLL out %u N 0x%x K 0x%x div %d ratio %d",
1112 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div, 1123 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
1113 fll_div.ratio); 1124 fll_div.ratio);
1114 1125
@@ -1660,6 +1671,21 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1660 return 0; 1671 return 0;
1661} 1672}
1662 1673
1674#ifdef CONFIG_PM
1675static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
1676{
1677 return snd_soc_suspend_device(&pdev->dev);
1678}
1679
1680static int wm8350_codec_resume(struct platform_device *pdev)
1681{
1682 return snd_soc_resume_device(&pdev->dev);
1683}
1684#else
1685#define wm8350_codec_suspend NULL
1686#define wm8350_codec_resume NULL
1687#endif
1688
1663static struct platform_driver wm8350_codec_driver = { 1689static struct platform_driver wm8350_codec_driver = {
1664 .driver = { 1690 .driver = {
1665 .name = "wm8350-codec", 1691 .name = "wm8350-codec",
@@ -1667,6 +1693,8 @@ static struct platform_driver wm8350_codec_driver = {
1667 }, 1693 },
1668 .probe = wm8350_codec_probe, 1694 .probe = wm8350_codec_probe,
1669 .remove = __devexit_p(wm8350_codec_remove), 1695 .remove = __devexit_p(wm8350_codec_remove),
1696 .suspend = wm8350_codec_suspend,
1697 .resume = wm8350_codec_resume,
1670}; 1698};
1671 1699
1672static __init int wm8350_init(void) 1700static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d11bd9288cf9..d088eb4b88bb 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -13,6 +13,7 @@
13#define _WM8350_H 13#define _WM8350_H
14 14
15#include <sound/soc.h> 15#include <sound/soc.h>
16#include <linux/mfd/wm8350/audio.h>
16 17
17extern struct snd_soc_dai wm8350_dai; 18extern struct snd_soc_dai wm8350_dai;
18extern struct snd_soc_codec_device soc_codec_dev_wm8350; 19extern struct snd_soc_codec_device soc_codec_dev_wm8350;
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 510efa604008..b9ef4d915221 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -954,7 +954,7 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
954 factors->outdiv *= 2; 954 factors->outdiv *= 2;
955 if (factors->outdiv > 32) { 955 if (factors->outdiv > 32) {
956 dev_err(wm8400->wm8400->dev, 956 dev_err(wm8400->wm8400->dev,
957 "Unsupported FLL output frequency %dHz\n", 957 "Unsupported FLL output frequency %uHz\n",
958 Fout); 958 Fout);
959 return -EINVAL; 959 return -EINVAL;
960 } 960 }
@@ -1003,7 +1003,7 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
1003 factors->k = K / 10; 1003 factors->k = K / 10;
1004 1004
1005 dev_dbg(wm8400->wm8400->dev, 1005 dev_dbg(wm8400->wm8400->dev,
1006 "FLL: Fref=%d Fout=%d N=%x K=%x, FRATIO=%x OUTDIV=%x\n", 1006 "FLL: Fref=%u Fout=%u N=%x K=%x, FRATIO=%x OUTDIV=%x\n",
1007 Fref, Fout, 1007 Fref, Fout,
1008 factors->n, factors->k, factors->fratio, factors->outdiv); 1008 factors->n, factors->k, factors->fratio, factors->outdiv);
1009 1009
@@ -1022,10 +1022,15 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1022 if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) 1022 if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out)
1023 return 0; 1023 return 0;
1024 1024
1025 if (freq_out != 0) { 1025 if (freq_out) {
1026 ret = fll_factors(wm8400, &factors, freq_in, freq_out); 1026 ret = fll_factors(wm8400, &factors, freq_in, freq_out);
1027 if (ret != 0) 1027 if (ret != 0)
1028 return ret; 1028 return ret;
1029 } else {
1030 /* Bodge GCC 4.4.0 uninitialised variable warning - it
1031 * doesn't seem capable of working out that we exit if
1032 * freq_out is 0 before any of the uses. */
1033 memset(&factors, 0, sizeof(factors));
1029 } 1034 }
1030 1035
1031 wm8400->fll_out = freq_out; 1036 wm8400->fll_out = freq_out;
@@ -1040,7 +1045,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1040 reg &= ~WM8400_FLL_OSC_ENA; 1045 reg &= ~WM8400_FLL_OSC_ENA;
1041 wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); 1046 wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
1042 1047
1043 if (freq_out == 0) 1048 if (!freq_out)
1044 return 0; 1049 return 0;
1045 1050
1046 reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); 1051 reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
@@ -1473,8 +1478,8 @@ static int wm8400_codec_probe(struct platform_device *dev)
1473 1478
1474 codec = &priv->codec; 1479 codec = &priv->codec;
1475 codec->private_data = priv; 1480 codec->private_data = priv;
1476 codec->control_data = dev->dev.driver_data; 1481 codec->control_data = dev_get_drvdata(&dev->dev);
1477 priv->wm8400 = dev->dev.driver_data; 1482 priv->wm8400 = dev_get_drvdata(&dev->dev);
1478 1483
1479 ret = regulator_bulk_get(priv->wm8400->dev, 1484 ret = regulator_bulk_get(priv->wm8400->dev,
1480 ARRAY_SIZE(power), &power[0]); 1485 ARRAY_SIZE(power), &power[0]);
@@ -1553,6 +1558,21 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
1553 return 0; 1558 return 0;
1554} 1559}
1555 1560
1561#ifdef CONFIG_PM
1562static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
1563{
1564 return snd_soc_suspend_device(&pdev->dev);
1565}
1566
1567static 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
1556static struct platform_driver wm8400_codec_driver = { 1576static struct platform_driver wm8400_codec_driver = {
1557 .driver = { 1577 .driver = {
1558 .name = "wm8400-codec", 1578 .name = "wm8400-codec",
@@ -1560,6 +1580,8 @@ static struct platform_driver wm8400_codec_driver = {
1560 }, 1580 },
1561 .probe = wm8400_codec_probe, 1581 .probe = wm8400_codec_probe,
1562 .remove = __exit_p(wm8400_codec_remove), 1582 .remove = __exit_p(wm8400_codec_remove),
1583 .suspend = wm8400_pdev_suspend,
1584 .resume = wm8400_pdev_resume,
1563}; 1585};
1564 1586
1565static int __init wm8400_codec_init(void) 1587static int __init wm8400_codec_init(void)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 6a4cea09c45d..060d5d06ba95 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
58#define WM8510_POWER1_BIASEN 0x08 58#define WM8510_POWER1_BIASEN 0x08
59#define WM8510_POWER1_BUFIOEN 0x10 59#define WM8510_POWER1_BUFIOEN 0x10
60 60
61/* 61#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
62 * read wm8510 register cache
63 */
64static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
65 unsigned int reg)
66{
67 u16 *cache = codec->reg_cache;
68 if (reg == WM8510_RESET)
69 return 0;
70 if (reg >= WM8510_CACHEREGNUM)
71 return -1;
72 return cache[reg];
73}
74
75/*
76 * write wm8510 register cache
77 */
78static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
79 u16 reg, unsigned int value)
80{
81 u16 *cache = codec->reg_cache;
82 if (reg >= WM8510_CACHEREGNUM)
83 return;
84 cache[reg] = value;
85}
86
87/*
88 * write to the WM8510 register space
89 */
90static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
91 unsigned int value)
92{
93 u8 data[2];
94
95 /* data is
96 * D15..D9 WM8510 register offset
97 * D8...D0 register data
98 */
99 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
100 data[1] = value & 0x00ff;
101
102 wm8510_write_reg_cache(codec, reg, value);
103 if (codec->hw_write(codec->control_data, data, 2) == 2)
104 return 0;
105 else
106 return -EIO;
107}
108
109#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0)
110 62
111static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; 63static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
112static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; 64static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
@@ -298,7 +250,7 @@ static void pll_factors(unsigned int target, unsigned int source)
298 250
299 if ((Ndiv < 6) || (Ndiv > 12)) 251 if ((Ndiv < 6) || (Ndiv > 12))
300 printk(KERN_WARNING 252 printk(KERN_WARNING
301 "WM8510 N value %d outwith recommended range!d\n", 253 "WM8510 N value %u outwith recommended range!d\n",
302 Ndiv); 254 Ndiv);
303 255
304 pll_div.n = Ndiv; 256 pll_div.n = Ndiv;
@@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
327 279
328 if (freq_in == 0 || freq_out == 0) { 280 if (freq_in == 0 || freq_out == 0) {
329 /* Clock CODEC directly from MCLK */ 281 /* Clock CODEC directly from MCLK */
330 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 282 reg = snd_soc_read(codec, WM8510_CLOCK);
331 wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff); 283 snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff);
332 284
333 /* Turn off PLL */ 285 /* Turn off PLL */
334 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 286 reg = snd_soc_read(codec, WM8510_POWER1);
335 wm8510_write(codec, WM8510_POWER1, reg & 0x1df); 287 snd_soc_write(codec, WM8510_POWER1, reg & 0x1df);
336 return 0; 288 return 0;
337 } 289 }
338 290
339 pll_factors(freq_out*4, freq_in); 291 pll_factors(freq_out*4, freq_in);
340 292
341 wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); 293 snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
342 wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); 294 snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18);
343 wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); 295 snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
344 wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); 296 snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
345 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 297 reg = snd_soc_read(codec, WM8510_POWER1);
346 wm8510_write(codec, WM8510_POWER1, reg | 0x020); 298 snd_soc_write(codec, WM8510_POWER1, reg | 0x020);
347 299
348 /* Run CODEC from PLL instead of MCLK */ 300 /* Run CODEC from PLL instead of MCLK */
349 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 301 reg = snd_soc_read(codec, WM8510_CLOCK);
350 wm8510_write(codec, WM8510_CLOCK, reg | 0x100); 302 snd_soc_write(codec, WM8510_CLOCK, reg | 0x100);
351 303
352 return 0; 304 return 0;
353} 305}
@@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
363 315
364 switch (div_id) { 316 switch (div_id) {
365 case WM8510_OPCLKDIV: 317 case WM8510_OPCLKDIV:
366 reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf; 318 reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf;
367 wm8510_write(codec, WM8510_GPIO, reg | div); 319 snd_soc_write(codec, WM8510_GPIO, reg | div);
368 break; 320 break;
369 case WM8510_MCLKDIV: 321 case WM8510_MCLKDIV:
370 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; 322 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f;
371 wm8510_write(codec, WM8510_CLOCK, reg | div); 323 snd_soc_write(codec, WM8510_CLOCK, reg | div);
372 break; 324 break;
373 case WM8510_ADCCLK: 325 case WM8510_ADCCLK:
374 reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7; 326 reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7;
375 wm8510_write(codec, WM8510_ADC, reg | div); 327 snd_soc_write(codec, WM8510_ADC, reg | div);
376 break; 328 break;
377 case WM8510_DACCLK: 329 case WM8510_DACCLK:
378 reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7; 330 reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7;
379 wm8510_write(codec, WM8510_DAC, reg | div); 331 snd_soc_write(codec, WM8510_DAC, reg | div);
380 break; 332 break;
381 case WM8510_BCLKDIV: 333 case WM8510_BCLKDIV:
382 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3; 334 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3;
383 wm8510_write(codec, WM8510_CLOCK, reg | div); 335 snd_soc_write(codec, WM8510_CLOCK, reg | div);
384 break; 336 break;
385 default: 337 default:
386 return -EINVAL; 338 return -EINVAL;
@@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
394{ 346{
395 struct snd_soc_codec *codec = codec_dai->codec; 347 struct snd_soc_codec *codec = codec_dai->codec;
396 u16 iface = 0; 348 u16 iface = 0;
397 u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe; 349 u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe;
398 350
399 /* set master/slave audio interface */ 351 /* set master/slave audio interface */
400 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 352 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
441 return -EINVAL; 393 return -EINVAL;
442 } 394 }
443 395
444 wm8510_write(codec, WM8510_IFACE, iface); 396 snd_soc_write(codec, WM8510_IFACE, iface);
445 wm8510_write(codec, WM8510_CLOCK, clk); 397 snd_soc_write(codec, WM8510_CLOCK, clk);
446 return 0; 398 return 0;
447} 399}
448 400
@@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
453 struct snd_soc_pcm_runtime *rtd = substream->private_data; 405 struct snd_soc_pcm_runtime *rtd = substream->private_data;
454 struct snd_soc_device *socdev = rtd->socdev; 406 struct snd_soc_device *socdev = rtd->socdev;
455 struct snd_soc_codec *codec = socdev->card->codec; 407 struct snd_soc_codec *codec = socdev->card->codec;
456 u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; 408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
457 u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; 409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
458 410
459 /* bit size */ 411 /* bit size */
460 switch (params_format(params)) { 412 switch (params_format(params)) {
@@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
493 break; 445 break;
494 } 446 }
495 447
496 wm8510_write(codec, WM8510_IFACE, iface); 448 snd_soc_write(codec, WM8510_IFACE, iface);
497 wm8510_write(codec, WM8510_ADD, adn); 449 snd_soc_write(codec, WM8510_ADD, adn);
498 return 0; 450 return 0;
499} 451}
500 452
501static int wm8510_mute(struct snd_soc_dai *dai, int mute) 453static int wm8510_mute(struct snd_soc_dai *dai, int mute)
502{ 454{
503 struct snd_soc_codec *codec = dai->codec; 455 struct snd_soc_codec *codec = dai->codec;
504 u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf; 456 u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf;
505 457
506 if (mute) 458 if (mute)
507 wm8510_write(codec, WM8510_DAC, mute_reg | 0x40); 459 snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40);
508 else 460 else
509 wm8510_write(codec, WM8510_DAC, mute_reg); 461 snd_soc_write(codec, WM8510_DAC, mute_reg);
510 return 0; 462 return 0;
511} 463}
512 464
@@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
514static int wm8510_set_bias_level(struct snd_soc_codec *codec, 466static int wm8510_set_bias_level(struct snd_soc_codec *codec,
515 enum snd_soc_bias_level level) 467 enum snd_soc_bias_level level)
516{ 468{
517 u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; 469 u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
518 470
519 switch (level) { 471 switch (level) {
520 case SND_SOC_BIAS_ON: 472 case SND_SOC_BIAS_ON:
521 case SND_SOC_BIAS_PREPARE: 473 case SND_SOC_BIAS_PREPARE:
522 power1 |= 0x1; /* VMID 50k */ 474 power1 |= 0x1; /* VMID 50k */
523 wm8510_write(codec, WM8510_POWER1, power1); 475 snd_soc_write(codec, WM8510_POWER1, power1);
524 break; 476 break;
525 477
526 case SND_SOC_BIAS_STANDBY: 478 case SND_SOC_BIAS_STANDBY:
@@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
528 480
529 if (codec->bias_level == SND_SOC_BIAS_OFF) { 481 if (codec->bias_level == SND_SOC_BIAS_OFF) {
530 /* Initial cap charge at VMID 5k */ 482 /* Initial cap charge at VMID 5k */
531 wm8510_write(codec, WM8510_POWER1, power1 | 0x3); 483 snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
532 mdelay(100); 484 mdelay(100);
533 } 485 }
534 486
535 power1 |= 0x2; /* VMID 500k */ 487 power1 |= 0x2; /* VMID 500k */
536 wm8510_write(codec, WM8510_POWER1, power1); 488 snd_soc_write(codec, WM8510_POWER1, power1);
537 break; 489 break;
538 490
539 case SND_SOC_BIAS_OFF: 491 case SND_SOC_BIAS_OFF:
540 wm8510_write(codec, WM8510_POWER1, 0); 492 snd_soc_write(codec, WM8510_POWER1, 0);
541 wm8510_write(codec, WM8510_POWER2, 0); 493 snd_soc_write(codec, WM8510_POWER2, 0);
542 wm8510_write(codec, WM8510_POWER3, 0); 494 snd_soc_write(codec, WM8510_POWER3, 0);
543 break; 495 break;
544 } 496 }
545 497
@@ -577,6 +529,7 @@ struct snd_soc_dai wm8510_dai = {
577 .rates = WM8510_RATES, 529 .rates = WM8510_RATES,
578 .formats = WM8510_FORMATS,}, 530 .formats = WM8510_FORMATS,},
579 .ops = &wm8510_dai_ops, 531 .ops = &wm8510_dai_ops,
532 .symmetric_rates = 1,
580}; 533};
581EXPORT_SYMBOL_GPL(wm8510_dai); 534EXPORT_SYMBOL_GPL(wm8510_dai);
582 535
@@ -612,15 +565,14 @@ static int wm8510_resume(struct platform_device *pdev)
612 * initialise the WM8510 driver 565 * initialise the WM8510 driver
613 * register the mixer and dsp interfaces with the kernel 566 * register the mixer and dsp interfaces with the kernel
614 */ 567 */
615static int wm8510_init(struct snd_soc_device *socdev) 568static int wm8510_init(struct snd_soc_device *socdev,
569 enum snd_soc_control_type control)
616{ 570{
617 struct snd_soc_codec *codec = socdev->card->codec; 571 struct snd_soc_codec *codec = socdev->card->codec;
618 int ret = 0; 572 int ret = 0;
619 573
620 codec->name = "WM8510"; 574 codec->name = "WM8510";
621 codec->owner = THIS_MODULE; 575 codec->owner = THIS_MODULE;
622 codec->read = wm8510_read_reg_cache;
623 codec->write = wm8510_write;
624 codec->set_bias_level = wm8510_set_bias_level; 576 codec->set_bias_level = wm8510_set_bias_level;
625 codec->dai = &wm8510_dai; 577 codec->dai = &wm8510_dai;
626 codec->num_dai = 1; 578 codec->num_dai = 1;
@@ -630,13 +582,20 @@ static int wm8510_init(struct snd_soc_device *socdev)
630 if (codec->reg_cache == NULL) 582 if (codec->reg_cache == NULL)
631 return -ENOMEM; 583 return -ENOMEM;
632 584
585 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
586 if (ret < 0) {
587 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
588 ret);
589 goto err;
590 }
591
633 wm8510_reset(codec); 592 wm8510_reset(codec);
634 593
635 /* register pcms */ 594 /* register pcms */
636 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 595 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
637 if (ret < 0) { 596 if (ret < 0) {
638 printk(KERN_ERR "wm8510: failed to create pcms\n"); 597 printk(KERN_ERR "wm8510: failed to create pcms\n");
639 goto pcm_err; 598 goto err;
640 } 599 }
641 600
642 /* power on device */ 601 /* power on device */
@@ -655,7 +614,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
655card_err: 614card_err:
656 snd_soc_free_pcms(socdev); 615 snd_soc_free_pcms(socdev);
657 snd_soc_dapm_free(socdev); 616 snd_soc_dapm_free(socdev);
658pcm_err: 617err:
659 kfree(codec->reg_cache); 618 kfree(codec->reg_cache);
660 return ret; 619 return ret;
661} 620}
@@ -678,7 +637,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c,
678 i2c_set_clientdata(i2c, codec); 637 i2c_set_clientdata(i2c, codec);
679 codec->control_data = i2c; 638 codec->control_data = i2c;
680 639
681 ret = wm8510_init(socdev); 640 ret = wm8510_init(socdev, SND_SOC_I2C);
682 if (ret < 0) 641 if (ret < 0)
683 pr_err("failed to initialise WM8510\n"); 642 pr_err("failed to initialise WM8510\n");
684 643
@@ -758,7 +717,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
758 717
759 codec->control_data = spi; 718 codec->control_data = spi;
760 719
761 ret = wm8510_init(socdev); 720 ret = wm8510_init(socdev, SND_SOC_SPI);
762 if (ret < 0) 721 if (ret < 0)
763 dev_err(&spi->dev, "failed to initialise WM8510\n"); 722 dev_err(&spi->dev, "failed to initialise WM8510\n");
764 723
@@ -779,30 +738,6 @@ static struct spi_driver wm8510_spi_driver = {
779 .probe = wm8510_spi_probe, 738 .probe = wm8510_spi_probe,
780 .remove = __devexit_p(wm8510_spi_remove), 739 .remove = __devexit_p(wm8510_spi_remove),
781}; 740};
782
783static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
784{
785 struct spi_transfer t;
786 struct spi_message m;
787 u8 msg[2];
788
789 if (len <= 0)
790 return 0;
791
792 msg[0] = data[0];
793 msg[1] = data[1];
794
795 spi_message_init(&m);
796 memset(&t, 0, (sizeof t));
797
798 t.tx_buf = &msg[0];
799 t.len = len;
800
801 spi_message_add_tail(&t, &m);
802 spi_sync(spi, &m);
803
804 return len;
805}
806#endif /* CONFIG_SPI_MASTER */ 741#endif /* CONFIG_SPI_MASTER */
807 742
808static int wm8510_probe(struct platform_device *pdev) 743static int wm8510_probe(struct platform_device *pdev)
@@ -827,13 +762,11 @@ static int wm8510_probe(struct platform_device *pdev)
827 wm8510_socdev = socdev; 762 wm8510_socdev = socdev;
828#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 763#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
829 if (setup->i2c_address) { 764 if (setup->i2c_address) {
830 codec->hw_write = (hw_write_t)i2c_master_send;
831 ret = wm8510_add_i2c_device(pdev, setup); 765 ret = wm8510_add_i2c_device(pdev, setup);
832 } 766 }
833#endif 767#endif
834#if defined(CONFIG_SPI_MASTER) 768#if defined(CONFIG_SPI_MASTER)
835 if (setup->spi) { 769 if (setup->spi) {
836 codec->hw_write = (hw_write_t)wm8510_spi_write;
837 ret = spi_register_driver(&wm8510_spi_driver); 770 ret = spi_register_driver(&wm8510_spi_driver);
838 if (ret != 0) 771 if (ret != 0)
839 printk(KERN_ERR "can't add spi driver"); 772 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
new file mode 100644
index 000000000000..25870a4652fb
--- /dev/null
+++ b/sound/soc/codecs/wm8523.c
@@ -0,0 +1,699 @@
1/*
2 * wm8523.c -- WM8523 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 <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
30#include "wm8523.h"
31
32static struct snd_soc_codec *wm8523_codec;
33struct snd_soc_codec_device soc_codec_dev_wm8523;
34
35#define WM8523_NUM_SUPPLIES 2
36static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
37 "AVDD",
38 "LINEVDD",
39};
40
41#define WM8523_NUM_RATES 7
42
43/* codec private data */
44struct wm8523_priv {
45 struct snd_soc_codec codec;
46 u16 reg_cache[WM8523_REGISTER_COUNT];
47 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
48 unsigned int sysclk;
49 unsigned int rate_constraint_list[WM8523_NUM_RATES];
50 struct snd_pcm_hw_constraint_list rate_constraint;
51};
52
53static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
54 0x8523, /* R0 - DEVICE_ID */
55 0x0001, /* R1 - REVISION */
56 0x0000, /* R2 - PSCTRL1 */
57 0x1812, /* R3 - AIF_CTRL1 */
58 0x0000, /* R4 - AIF_CTRL2 */
59 0x0001, /* R5 - DAC_CTRL3 */
60 0x0190, /* R6 - DAC_GAINL */
61 0x0190, /* R7 - DAC_GAINR */
62 0x0000, /* R8 - ZERO_DETECT */
63};
64
65static int wm8523_volatile_register(unsigned int reg)
66{
67 switch (reg) {
68 case WM8523_DEVICE_ID:
69 case WM8523_REVISION:
70 return 1;
71 default:
72 return 0;
73 }
74}
75
76static int wm8523_reset(struct snd_soc_codec *codec)
77{
78 return snd_soc_write(codec, WM8523_DEVICE_ID, 0);
79}
80
81static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
82
83static const char *wm8523_zd_count_text[] = {
84 "1024",
85 "2048",
86};
87
88static const struct soc_enum wm8523_zc_count =
89 SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
90
91static const struct snd_kcontrol_new wm8523_snd_controls[] = {
92SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
93 0, 448, 0, dac_tlv),
94SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
95SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
96SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
97SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
98SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
99SOC_ENUM("Zero Detect Count", wm8523_zc_count),
100};
101
102static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
103SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
104SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
105SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
106};
107
108static const struct snd_soc_dapm_route intercon[] = {
109 { "LINEVOUTL", NULL, "DAC" },
110 { "LINEVOUTR", NULL, "DAC" },
111};
112
113static int wm8523_add_widgets(struct snd_soc_codec *codec)
114{
115 snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets,
116 ARRAY_SIZE(wm8523_dapm_widgets));
117
118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
119
120 snd_soc_dapm_new_widgets(codec);
121 return 0;
122}
123
124static struct {
125 int value;
126 int ratio;
127} lrclk_ratios[WM8523_NUM_RATES] = {
128 { 1, 128 },
129 { 2, 192 },
130 { 3, 256 },
131 { 4, 384 },
132 { 5, 512 },
133 { 6, 768 },
134 { 7, 1152 },
135};
136
137static int wm8523_startup(struct snd_pcm_substream *substream,
138 struct snd_soc_dai *dai)
139{
140 struct snd_soc_codec *codec = dai->codec;
141 struct wm8523_priv *wm8523 = codec->private_data;
142
143 /* The set of sample rates that can be supported depends on the
144 * MCLK supplied to the CODEC - enforce this.
145 */
146 if (!wm8523->sysclk) {
147 dev_err(codec->dev,
148 "No MCLK configured, call set_sysclk() on init\n");
149 return -EINVAL;
150 }
151
152 return 0;
153 snd_pcm_hw_constraint_list(substream->runtime, 0,
154 SNDRV_PCM_HW_PARAM_RATE,
155 &wm8523->rate_constraint);
156
157 return 0;
158}
159
160static int wm8523_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params,
162 struct snd_soc_dai *dai)
163{
164 struct snd_soc_pcm_runtime *rtd = substream->private_data;
165 struct snd_soc_device *socdev = rtd->socdev;
166 struct snd_soc_codec *codec = socdev->card->codec;
167 struct wm8523_priv *wm8523 = codec->private_data;
168 int i;
169 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
170 u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2);
171
172 /* Find a supported LRCLK ratio */
173 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
174 if (wm8523->sysclk / params_rate(params) ==
175 lrclk_ratios[i].ratio)
176 break;
177 }
178
179 /* Should never happen, should be handled by constraints */
180 if (i == ARRAY_SIZE(lrclk_ratios)) {
181 dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
182 wm8523->sysclk / params_rate(params));
183 return -EINVAL;
184 }
185
186 aifctrl2 &= ~WM8523_SR_MASK;
187 aifctrl2 |= lrclk_ratios[i].value;
188
189 aifctrl1 &= ~WM8523_WL_MASK;
190 switch (params_format(params)) {
191 case SNDRV_PCM_FORMAT_S16_LE:
192 break;
193 case SNDRV_PCM_FORMAT_S20_3LE:
194 aifctrl1 |= 0x8;
195 break;
196 case SNDRV_PCM_FORMAT_S24_LE:
197 aifctrl1 |= 0x10;
198 break;
199 case SNDRV_PCM_FORMAT_S32_LE:
200 aifctrl1 |= 0x18;
201 break;
202 }
203
204 snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
205 snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2);
206
207 return 0;
208}
209
210static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
211 int clk_id, unsigned int freq, int dir)
212{
213 struct snd_soc_codec *codec = codec_dai->codec;
214 struct wm8523_priv *wm8523 = codec->private_data;
215 unsigned int val;
216 int i;
217
218 wm8523->sysclk = freq;
219
220 wm8523->rate_constraint.count = 0;
221 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
222 val = freq / lrclk_ratios[i].ratio;
223 /* Check that it's a standard rate since core can't
224 * cope with others and having the odd rates confuses
225 * constraint matching.
226 */
227 switch (val) {
228 case 8000:
229 case 11025:
230 case 16000:
231 case 22050:
232 case 32000:
233 case 44100:
234 case 48000:
235 case 64000:
236 case 88200:
237 case 96000:
238 case 176400:
239 case 192000:
240 dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
241 val);
242 wm8523->rate_constraint_list[i] = val;
243 wm8523->rate_constraint.count++;
244 break;
245 default:
246 dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
247 val);
248 }
249 }
250
251 /* Need at least one supported rate... */
252 if (wm8523->rate_constraint.count == 0)
253 return -EINVAL;
254
255 return 0;
256}
257
258
259static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
260 unsigned int fmt)
261{
262 struct snd_soc_codec *codec = codec_dai->codec;
263 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
264
265 aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
266 WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
267
268 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
269 case SND_SOC_DAIFMT_CBM_CFM:
270 aifctrl1 |= WM8523_AIF_MSTR;
271 break;
272 case SND_SOC_DAIFMT_CBS_CFS:
273 break;
274 default:
275 return -EINVAL;
276 }
277
278 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
279 case SND_SOC_DAIFMT_I2S:
280 aifctrl1 |= 0x0002;
281 break;
282 case SND_SOC_DAIFMT_RIGHT_J:
283 break;
284 case SND_SOC_DAIFMT_LEFT_J:
285 aifctrl1 |= 0x0001;
286 break;
287 case SND_SOC_DAIFMT_DSP_A:
288 aifctrl1 |= 0x0003;
289 break;
290 case SND_SOC_DAIFMT_DSP_B:
291 aifctrl1 |= 0x0023;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
298 case SND_SOC_DAIFMT_NB_NF:
299 break;
300 case SND_SOC_DAIFMT_IB_IF:
301 aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
302 break;
303 case SND_SOC_DAIFMT_IB_NF:
304 aifctrl1 |= WM8523_BCLK_INV;
305 break;
306 case SND_SOC_DAIFMT_NB_IF:
307 aifctrl1 |= WM8523_LRCLK_INV;
308 break;
309 default:
310 return -EINVAL;
311 }
312
313 snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
314
315 return 0;
316}
317
318static int wm8523_set_bias_level(struct snd_soc_codec *codec,
319 enum snd_soc_bias_level level)
320{
321 struct wm8523_priv *wm8523 = codec->private_data;
322 int ret, i;
323
324 switch (level) {
325 case SND_SOC_BIAS_ON:
326 break;
327
328 case SND_SOC_BIAS_PREPARE:
329 /* Full power on */
330 snd_soc_update_bits(codec, WM8523_PSCTRL1,
331 WM8523_SYS_ENA_MASK, 3);
332 break;
333
334 case SND_SOC_BIAS_STANDBY:
335 if (codec->bias_level == SND_SOC_BIAS_OFF) {
336 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
337 wm8523->supplies);
338 if (ret != 0) {
339 dev_err(codec->dev,
340 "Failed to enable supplies: %d\n",
341 ret);
342 return ret;
343 }
344
345 /* Initial power up */
346 snd_soc_update_bits(codec, WM8523_PSCTRL1,
347 WM8523_SYS_ENA_MASK, 1);
348
349 /* Sync back default/cached values */
350 for (i = WM8523_AIF_CTRL1;
351 i < WM8523_MAX_REGISTER; i++)
352 snd_soc_write(codec, i, wm8523->reg_cache[i]);
353
354
355 msleep(100);
356 }
357
358 /* Power up to mute */
359 snd_soc_update_bits(codec, WM8523_PSCTRL1,
360 WM8523_SYS_ENA_MASK, 2);
361
362 break;
363
364 case SND_SOC_BIAS_OFF:
365 /* The chip runs through the power down sequence for us. */
366 snd_soc_update_bits(codec, WM8523_PSCTRL1,
367 WM8523_SYS_ENA_MASK, 0);
368 msleep(100);
369
370 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
371 wm8523->supplies);
372 break;
373 }
374 codec->bias_level = level;
375 return 0;
376}
377
378#define WM8523_RATES SNDRV_PCM_RATE_8000_192000
379
380#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
381 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
382
383static struct snd_soc_dai_ops wm8523_dai_ops = {
384 .startup = wm8523_startup,
385 .hw_params = wm8523_hw_params,
386 .set_sysclk = wm8523_set_dai_sysclk,
387 .set_fmt = wm8523_set_dai_fmt,
388};
389
390struct snd_soc_dai wm8523_dai = {
391 .name = "WM8523",
392 .playback = {
393 .stream_name = "Playback",
394 .channels_min = 2, /* Mono modes not yet supported */
395 .channels_max = 2,
396 .rates = WM8523_RATES,
397 .formats = WM8523_FORMATS,
398 },
399 .ops = &wm8523_dai_ops,
400};
401EXPORT_SYMBOL_GPL(wm8523_dai);
402
403#ifdef CONFIG_PM
404static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
405{
406 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
407 struct snd_soc_codec *codec = socdev->card->codec;
408
409 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
410 return 0;
411}
412
413static int wm8523_resume(struct platform_device *pdev)
414{
415 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
416 struct snd_soc_codec *codec = socdev->card->codec;
417
418 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
419
420 return 0;
421}
422#else
423#define wm8523_suspend NULL
424#define wm8523_resume NULL
425#endif
426
427static int wm8523_probe(struct platform_device *pdev)
428{
429 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
430 struct snd_soc_codec *codec;
431 int ret = 0;
432
433 if (wm8523_codec == NULL) {
434 dev_err(&pdev->dev, "Codec device not registered\n");
435 return -ENODEV;
436 }
437
438 socdev->card->codec = wm8523_codec;
439 codec = wm8523_codec;
440
441 /* register pcms */
442 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
443 if (ret < 0) {
444 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
445 goto pcm_err;
446 }
447
448 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls));
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
457 return ret;
458
459card_err:
460 snd_soc_free_pcms(socdev);
461 snd_soc_dapm_free(socdev);
462pcm_err:
463 return ret;
464}
465
466static int wm8523_remove(struct platform_device *pdev)
467{
468 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
469
470 snd_soc_free_pcms(socdev);
471 snd_soc_dapm_free(socdev);
472
473 return 0;
474}
475
476struct snd_soc_codec_device soc_codec_dev_wm8523 = {
477 .probe = wm8523_probe,
478 .remove = wm8523_remove,
479 .suspend = wm8523_suspend,
480 .resume = wm8523_resume,
481};
482EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
483
484static int wm8523_register(struct wm8523_priv *wm8523,
485 enum snd_soc_control_type control)
486{
487 int ret;
488 struct snd_soc_codec *codec = &wm8523->codec;
489 int i;
490
491 if (wm8523_codec) {
492 dev_err(codec->dev, "Another WM8523 is registered\n");
493 return -EINVAL;
494 }
495
496 mutex_init(&codec->mutex);
497 INIT_LIST_HEAD(&codec->dapm_widgets);
498 INIT_LIST_HEAD(&codec->dapm_paths);
499
500 codec->private_data = wm8523;
501 codec->name = "WM8523";
502 codec->owner = THIS_MODULE;
503 codec->bias_level = SND_SOC_BIAS_OFF;
504 codec->set_bias_level = wm8523_set_bias_level;
505 codec->dai = &wm8523_dai;
506 codec->num_dai = 1;
507 codec->reg_cache_size = WM8523_REGISTER_COUNT;
508 codec->reg_cache = &wm8523->reg_cache;
509 codec->volatile_register = wm8523_volatile_register;
510
511 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
512 wm8523->rate_constraint.count =
513 ARRAY_SIZE(wm8523->rate_constraint_list);
514
515 memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
516
517 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
518 if (ret != 0) {
519 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
520 goto err;
521 }
522
523 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
524 wm8523->supplies[i].supply = wm8523_supply_names[i];
525
526 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
527 wm8523->supplies);
528 if (ret != 0) {
529 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
530 goto err;
531 }
532
533 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
534 wm8523->supplies);
535 if (ret != 0) {
536 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
537 goto err_get;
538 }
539
540 ret = snd_soc_read(codec, WM8523_DEVICE_ID);
541 if (ret < 0) {
542 dev_err(codec->dev, "Failed to read ID register\n");
543 goto err_enable;
544 }
545 if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
546 dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
547 ret = -EINVAL;
548 goto err_enable;
549 }
550
551 ret = snd_soc_read(codec, WM8523_REVISION);
552 if (ret < 0) {
553 dev_err(codec->dev, "Failed to read revision register\n");
554 goto err_enable;
555 }
556 dev_info(codec->dev, "revision %c\n",
557 (ret & WM8523_CHIP_REV_MASK) + 'A');
558
559 ret = wm8523_reset(codec);
560 if (ret < 0) {
561 dev_err(codec->dev, "Failed to issue reset\n");
562 goto err_enable;
563 }
564
565 wm8523_dai.dev = codec->dev;
566
567 /* Change some default settings - latch VU and enable ZC */
568 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
569 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
570
571 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
572
573 /* Bias level configuration will have done an extra enable */
574 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
575
576 wm8523_codec = codec;
577
578 ret = snd_soc_register_codec(codec);
579 if (ret != 0) {
580 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
581 return ret;
582 }
583
584 ret = snd_soc_register_dai(&wm8523_dai);
585 if (ret != 0) {
586 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
587 snd_soc_unregister_codec(codec);
588 return ret;
589 }
590
591 return 0;
592
593err_enable:
594 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
595err_get:
596 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
597err:
598 kfree(wm8523);
599 return ret;
600}
601
602static void wm8523_unregister(struct wm8523_priv *wm8523)
603{
604 wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
605 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
606 snd_soc_unregister_dai(&wm8523_dai);
607 snd_soc_unregister_codec(&wm8523->codec);
608 kfree(wm8523);
609 wm8523_codec = NULL;
610}
611
612#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
613static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
614 const struct i2c_device_id *id)
615{
616 struct wm8523_priv *wm8523;
617 struct snd_soc_codec *codec;
618
619 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
620 if (wm8523 == NULL)
621 return -ENOMEM;
622
623 codec = &wm8523->codec;
624 codec->hw_write = (hw_write_t)i2c_master_send;
625
626 i2c_set_clientdata(i2c, wm8523);
627 codec->control_data = i2c;
628
629 codec->dev = &i2c->dev;
630
631 return wm8523_register(wm8523, SND_SOC_I2C);
632}
633
634static __devexit int wm8523_i2c_remove(struct i2c_client *client)
635{
636 struct wm8523_priv *wm8523 = i2c_get_clientdata(client);
637 wm8523_unregister(wm8523);
638 return 0;
639}
640
641#ifdef CONFIG_PM
642static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
643{
644 return snd_soc_suspend_device(&i2c->dev);
645}
646
647static 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
656static const struct i2c_device_id wm8523_i2c_id[] = {
657 { "wm8523", 0 },
658 { }
659};
660MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
661
662static struct i2c_driver wm8523_i2c_driver = {
663 .driver = {
664 .name = "WM8523",
665 .owner = THIS_MODULE,
666 },
667 .probe = wm8523_i2c_probe,
668 .remove = __devexit_p(wm8523_i2c_remove),
669 .suspend = wm8523_i2c_suspend,
670 .resume = wm8523_i2c_resume,
671 .id_table = wm8523_i2c_id,
672};
673#endif
674
675static int __init wm8523_modinit(void)
676{
677 int ret;
678#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
679 ret = i2c_add_driver(&wm8523_i2c_driver);
680 if (ret != 0) {
681 printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
682 ret);
683 }
684#endif
685 return 0;
686}
687module_init(wm8523_modinit);
688
689static void __exit wm8523_exit(void)
690{
691#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
692 i2c_del_driver(&wm8523_i2c_driver);
693#endif
694}
695module_exit(wm8523_exit);
696
697MODULE_DESCRIPTION("ASoC WM8523 driver");
698MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
699MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h
new file mode 100644
index 000000000000..1aa9ce3e1357
--- /dev/null
+++ b/sound/soc/codecs/wm8523.h
@@ -0,0 +1,160 @@
1/*
2 * wm8523.h -- WM8423 ASoC driver
3 *
4 * Copyright 2009 Wolfson Microelectronics, plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * Based on wm8753.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 _WM8523_H
16#define _WM8523_H
17
18/*
19 * Register values.
20 */
21#define WM8523_DEVICE_ID 0x00
22#define WM8523_REVISION 0x01
23#define WM8523_PSCTRL1 0x02
24#define WM8523_AIF_CTRL1 0x03
25#define WM8523_AIF_CTRL2 0x04
26#define WM8523_DAC_CTRL3 0x05
27#define WM8523_DAC_GAINL 0x06
28#define WM8523_DAC_GAINR 0x07
29#define WM8523_ZERO_DETECT 0x08
30
31#define WM8523_REGISTER_COUNT 9
32#define WM8523_MAX_REGISTER 0x08
33
34/*
35 * Field Definitions.
36 */
37
38/*
39 * R0 (0x00) - DEVICE_ID
40 */
41#define WM8523_CHIP_ID_MASK 0xFFFF /* CHIP_ID - [15:0] */
42#define WM8523_CHIP_ID_SHIFT 0 /* CHIP_ID - [15:0] */
43#define WM8523_CHIP_ID_WIDTH 16 /* CHIP_ID - [15:0] */
44
45/*
46 * R1 (0x01) - REVISION
47 */
48#define WM8523_CHIP_REV_MASK 0x0007 /* CHIP_REV - [2:0] */
49#define WM8523_CHIP_REV_SHIFT 0 /* CHIP_REV - [2:0] */
50#define WM8523_CHIP_REV_WIDTH 3 /* CHIP_REV - [2:0] */
51
52/*
53 * R2 (0x02) - PSCTRL1
54 */
55#define WM8523_SYS_ENA_MASK 0x0003 /* SYS_ENA - [1:0] */
56#define WM8523_SYS_ENA_SHIFT 0 /* SYS_ENA - [1:0] */
57#define WM8523_SYS_ENA_WIDTH 2 /* SYS_ENA - [1:0] */
58
59/*
60 * R3 (0x03) - AIF_CTRL1
61 */
62#define WM8523_TDM_MODE_MASK 0x1800 /* TDM_MODE - [12:11] */
63#define WM8523_TDM_MODE_SHIFT 11 /* TDM_MODE - [12:11] */
64#define WM8523_TDM_MODE_WIDTH 2 /* TDM_MODE - [12:11] */
65#define WM8523_TDM_SLOT_MASK 0x0600 /* TDM_SLOT - [10:9] */
66#define WM8523_TDM_SLOT_SHIFT 9 /* TDM_SLOT - [10:9] */
67#define WM8523_TDM_SLOT_WIDTH 2 /* TDM_SLOT - [10:9] */
68#define WM8523_DEEMPH 0x0100 /* DEEMPH */
69#define WM8523_DEEMPH_MASK 0x0100 /* DEEMPH */
70#define WM8523_DEEMPH_SHIFT 8 /* DEEMPH */
71#define WM8523_DEEMPH_WIDTH 1 /* DEEMPH */
72#define WM8523_AIF_MSTR 0x0080 /* AIF_MSTR */
73#define WM8523_AIF_MSTR_MASK 0x0080 /* AIF_MSTR */
74#define WM8523_AIF_MSTR_SHIFT 7 /* AIF_MSTR */
75#define WM8523_AIF_MSTR_WIDTH 1 /* AIF_MSTR */
76#define WM8523_LRCLK_INV 0x0040 /* LRCLK_INV */
77#define WM8523_LRCLK_INV_MASK 0x0040 /* LRCLK_INV */
78#define WM8523_LRCLK_INV_SHIFT 6 /* LRCLK_INV */
79#define WM8523_LRCLK_INV_WIDTH 1 /* LRCLK_INV */
80#define WM8523_BCLK_INV 0x0020 /* BCLK_INV */
81#define WM8523_BCLK_INV_MASK 0x0020 /* BCLK_INV */
82#define WM8523_BCLK_INV_SHIFT 5 /* BCLK_INV */
83#define WM8523_BCLK_INV_WIDTH 1 /* BCLK_INV */
84#define WM8523_WL_MASK 0x0018 /* WL - [4:3] */
85#define WM8523_WL_SHIFT 3 /* WL - [4:3] */
86#define WM8523_WL_WIDTH 2 /* WL - [4:3] */
87#define WM8523_FMT_MASK 0x0007 /* FMT - [2:0] */
88#define WM8523_FMT_SHIFT 0 /* FMT - [2:0] */
89#define WM8523_FMT_WIDTH 3 /* FMT - [2:0] */
90
91/*
92 * R4 (0x04) - AIF_CTRL2
93 */
94#define WM8523_DAC_OP_MUX_MASK 0x00C0 /* DAC_OP_MUX - [7:6] */
95#define WM8523_DAC_OP_MUX_SHIFT 6 /* DAC_OP_MUX - [7:6] */
96#define WM8523_DAC_OP_MUX_WIDTH 2 /* DAC_OP_MUX - [7:6] */
97#define WM8523_BCLKDIV_MASK 0x0038 /* BCLKDIV - [5:3] */
98#define WM8523_BCLKDIV_SHIFT 3 /* BCLKDIV - [5:3] */
99#define WM8523_BCLKDIV_WIDTH 3 /* BCLKDIV - [5:3] */
100#define WM8523_SR_MASK 0x0007 /* SR - [2:0] */
101#define WM8523_SR_SHIFT 0 /* SR - [2:0] */
102#define WM8523_SR_WIDTH 3 /* SR - [2:0] */
103
104/*
105 * R5 (0x05) - DAC_CTRL3
106 */
107#define WM8523_ZC 0x0010 /* ZC */
108#define WM8523_ZC_MASK 0x0010 /* ZC */
109#define WM8523_ZC_SHIFT 4 /* ZC */
110#define WM8523_ZC_WIDTH 1 /* ZC */
111#define WM8523_DACR 0x0008 /* DACR */
112#define WM8523_DACR_MASK 0x0008 /* DACR */
113#define WM8523_DACR_SHIFT 3 /* DACR */
114#define WM8523_DACR_WIDTH 1 /* DACR */
115#define WM8523_DACL 0x0004 /* DACL */
116#define WM8523_DACL_MASK 0x0004 /* DACL */
117#define WM8523_DACL_SHIFT 2 /* DACL */
118#define WM8523_DACL_WIDTH 1 /* DACL */
119#define WM8523_VOL_UP_RAMP 0x0002 /* VOL_UP_RAMP */
120#define WM8523_VOL_UP_RAMP_MASK 0x0002 /* VOL_UP_RAMP */
121#define WM8523_VOL_UP_RAMP_SHIFT 1 /* VOL_UP_RAMP */
122#define WM8523_VOL_UP_RAMP_WIDTH 1 /* VOL_UP_RAMP */
123#define WM8523_VOL_DOWN_RAMP 0x0001 /* VOL_DOWN_RAMP */
124#define WM8523_VOL_DOWN_RAMP_MASK 0x0001 /* VOL_DOWN_RAMP */
125#define WM8523_VOL_DOWN_RAMP_SHIFT 0 /* VOL_DOWN_RAMP */
126#define WM8523_VOL_DOWN_RAMP_WIDTH 1 /* VOL_DOWN_RAMP */
127
128/*
129 * R6 (0x06) - DAC_GAINL
130 */
131#define WM8523_DACL_VU 0x0200 /* DACL_VU */
132#define WM8523_DACL_VU_MASK 0x0200 /* DACL_VU */
133#define WM8523_DACL_VU_SHIFT 9 /* DACL_VU */
134#define WM8523_DACL_VU_WIDTH 1 /* DACL_VU */
135#define WM8523_DACL_VOL_MASK 0x01FF /* DACL_VOL - [8:0] */
136#define WM8523_DACL_VOL_SHIFT 0 /* DACL_VOL - [8:0] */
137#define WM8523_DACL_VOL_WIDTH 9 /* DACL_VOL - [8:0] */
138
139/*
140 * R7 (0x07) - DAC_GAINR
141 */
142#define WM8523_DACR_VU 0x0200 /* DACR_VU */
143#define WM8523_DACR_VU_MASK 0x0200 /* DACR_VU */
144#define WM8523_DACR_VU_SHIFT 9 /* DACR_VU */
145#define WM8523_DACR_VU_WIDTH 1 /* DACR_VU */
146#define WM8523_DACR_VOL_MASK 0x01FF /* DACR_VOL - [8:0] */
147#define WM8523_DACR_VOL_SHIFT 0 /* DACR_VOL - [8:0] */
148#define WM8523_DACR_VOL_WIDTH 9 /* DACR_VOL - [8:0] */
149
150/*
151 * R8 (0x08) - ZERO_DETECT
152 */
153#define WM8523_ZD_COUNT_MASK 0x0003 /* ZD_COUNT - [1:0] */
154#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */
155#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */
156
157extern struct snd_soc_dai wm8523_dai;
158extern struct snd_soc_codec_device soc_codec_dev_wm8523;
159
160#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 9f6be3d31ac0..d5473473a1e3 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -24,6 +24,8 @@
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/regulator/consumer.h>
28
27#include <sound/core.h> 29#include <sound/core.h>
28#include <sound/pcm.h> 30#include <sound/pcm.h>
29#include <sound/pcm_params.h> 31#include <sound/pcm_params.h>
@@ -187,82 +189,22 @@ struct pll_state {
187 unsigned int out; 189 unsigned int out;
188}; 190};
189 191
192#define WM8580_NUM_SUPPLIES 3
193static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
194 "AVDD",
195 "DVDD",
196 "PVDD",
197};
198
190/* codec private data */ 199/* codec private data */
191struct wm8580_priv { 200struct wm8580_priv {
192 struct snd_soc_codec codec; 201 struct snd_soc_codec codec;
202 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
193 u16 reg_cache[WM8580_MAX_REGISTER + 1]; 203 u16 reg_cache[WM8580_MAX_REGISTER + 1];
194 struct pll_state a; 204 struct pll_state a;
195 struct pll_state b; 205 struct pll_state b;
196}; 206};
197 207
198
199/*
200 * read wm8580 register cache
201 */
202static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
203 unsigned int reg)
204{
205 u16 *cache = codec->reg_cache;
206 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
207 return cache[reg];
208}
209
210/*
211 * write wm8580 register cache
212 */
213static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec,
214 unsigned int reg, unsigned int value)
215{
216 u16 *cache = codec->reg_cache;
217
218 cache[reg] = value;
219}
220
221/*
222 * write to the WM8580 register space
223 */
224static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
225 unsigned int value)
226{
227 u8 data[2];
228
229 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
230
231 /* Registers are 9 bits wide */
232 value &= 0x1ff;
233
234 switch (reg) {
235 case WM8580_RESET:
236 /* Uncached */
237 break;
238 default:
239 if (value == wm8580_read_reg_cache(codec, reg))
240 return 0;
241 }
242
243 /* data is
244 * D15..D9 WM8580 register offset
245 * D8...D0 register data
246 */
247 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
248 data[1] = value & 0x00ff;
249
250 wm8580_write_reg_cache(codec, reg, value);
251 if (codec->hw_write(codec->control_data, data, 2) == 2)
252 return 0;
253 else
254 return -EIO;
255}
256
257static inline unsigned int wm8580_read(struct snd_soc_codec *codec,
258 unsigned int reg)
259{
260 switch (reg) {
261 default:
262 return wm8580_read_reg_cache(codec, reg);
263 }
264}
265
266static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 208static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
267 209
268static int wm8580_out_vu(struct snd_kcontrol *kcontrol, 210static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
@@ -271,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
271 struct soc_mixer_control *mc = 213 struct soc_mixer_control *mc =
272 (struct soc_mixer_control *)kcontrol->private_value; 214 (struct soc_mixer_control *)kcontrol->private_value;
273 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 215 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
216 u16 *reg_cache = codec->reg_cache;
274 unsigned int reg = mc->reg; 217 unsigned int reg = mc->reg;
275 unsigned int reg2 = mc->rreg; 218 unsigned int reg2 = mc->rreg;
276 int ret; 219 int ret;
277 u16 val;
278 220
279 /* Clear the register cache so we write without VU set */ 221 /* Clear the register cache so we write without VU set */
280 wm8580_write_reg_cache(codec, reg, 0); 222 reg_cache[reg] = 0;
281 wm8580_write_reg_cache(codec, reg2, 0); 223 reg_cache[reg2] = 0;
282 224
283 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); 225 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
284 if (ret < 0) 226 if (ret < 0)
285 return ret; 227 return ret;
286 228
287 /* Now write again with the volume update bit set */ 229 /* Now write again with the volume update bit set */
288 val = wm8580_read_reg_cache(codec, reg); 230 snd_soc_update_bits(codec, reg, 0x100, 0x100);
289 wm8580_write(codec, reg, val | 0x0100); 231 snd_soc_update_bits(codec, reg2, 0x100, 0x100);
290
291 val = wm8580_read_reg_cache(codec, reg2);
292 wm8580_write(codec, reg2, val | 0x0100);
293 232
294 return 0; 233 return 0;
295} 234}
@@ -415,7 +354,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
415 unsigned int K, Ndiv, Nmod; 354 unsigned int K, Ndiv, Nmod;
416 int i; 355 int i;
417 356
418 pr_debug("wm8580: PLL %dHz->%dHz\n", source, target); 357 pr_debug("wm8580: PLL %uHz->%uHz\n", source, target);
419 358
420 /* Scale the output frequency up; the PLL should run in the 359 /* Scale the output frequency up; the PLL should run in the
421 * region of 90-100MHz. 360 * region of 90-100MHz.
@@ -447,7 +386,7 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
447 386
448 if ((Ndiv < 5) || (Ndiv > 13)) { 387 if ((Ndiv < 5) || (Ndiv > 13)) {
449 printk(KERN_ERR 388 printk(KERN_ERR
450 "WM8580 N=%d outside supported range\n", Ndiv); 389 "WM8580 N=%u outside supported range\n", Ndiv);
451 return -EINVAL; 390 return -EINVAL;
452 } 391 }
453 392
@@ -512,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
512 /* Always disable the PLL - it is not safe to leave it running 451 /* Always disable the PLL - it is not safe to leave it running
513 * while reprogramming it. 452 * while reprogramming it.
514 */ 453 */
515 reg = wm8580_read(codec, WM8580_PWRDN2); 454 reg = snd_soc_read(codec, WM8580_PWRDN2);
516 wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); 455 snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
517 456
518 if (!freq_in || !freq_out) 457 if (!freq_in || !freq_out)
519 return 0; 458 return 0;
520 459
521 wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); 460 snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
522 wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); 461 snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff);
523 wm8580_write(codec, WM8580_PLLA3 + offset, 462 snd_soc_write(codec, WM8580_PLLA3 + offset,
524 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); 463 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
525 464
526 reg = wm8580_read(codec, WM8580_PLLA4 + offset); 465 reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
527 reg &= ~0x3f; 466 reg &= ~0x3f;
528 reg |= pll_div.prescale | pll_div.postscale << 1 | 467 reg |= pll_div.prescale | pll_div.postscale << 1 |
529 pll_div.freqmode << 3; 468 pll_div.freqmode << 3;
530 469
531 wm8580_write(codec, WM8580_PLLA4 + offset, reg); 470 snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
532 471
533 /* All done, turn it on */ 472 /* All done, turn it on */
534 reg = wm8580_read(codec, WM8580_PWRDN2); 473 reg = snd_soc_read(codec, WM8580_PWRDN2);
535 wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); 474 snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
536 475
537 return 0; 476 return 0;
538} 477}
@@ -547,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
547 struct snd_soc_pcm_runtime *rtd = substream->private_data; 486 struct snd_soc_pcm_runtime *rtd = substream->private_data;
548 struct snd_soc_device *socdev = rtd->socdev; 487 struct snd_soc_device *socdev = rtd->socdev;
549 struct snd_soc_codec *codec = socdev->card->codec; 488 struct snd_soc_codec *codec = socdev->card->codec;
550 u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); 489 u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
551 490
552 paifb &= ~WM8580_AIF_LENGTH_MASK; 491 paifb &= ~WM8580_AIF_LENGTH_MASK;
553 /* bit size */ 492 /* bit size */
@@ -567,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
567 return -EINVAL; 506 return -EINVAL;
568 } 507 }
569 508
570 wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); 509 snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
571 return 0; 510 return 0;
572} 511}
573 512
@@ -579,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
579 unsigned int aifb; 518 unsigned int aifb;
580 int can_invert_lrclk; 519 int can_invert_lrclk;
581 520
582 aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); 521 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
583 aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); 522 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
584 523
585 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); 524 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
586 525
@@ -646,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
646 return -EINVAL; 585 return -EINVAL;
647 } 586 }
648 587
649 wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); 588 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
650 wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); 589 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
651 590
652 return 0; 591 return 0;
653} 592}
@@ -660,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
660 599
661 switch (div_id) { 600 switch (div_id) {
662 case WM8580_MCLK: 601 case WM8580_MCLK:
663 reg = wm8580_read(codec, WM8580_PLLB4); 602 reg = snd_soc_read(codec, WM8580_PLLB4);
664 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; 603 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
665 604
666 switch (div) { 605 switch (div) {
@@ -682,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
682 default: 621 default:
683 return -EINVAL; 622 return -EINVAL;
684 } 623 }
685 wm8580_write(codec, WM8580_PLLB4, reg); 624 snd_soc_write(codec, WM8580_PLLB4, reg);
686 break; 625 break;
687 626
688 case WM8580_DAC_CLKSEL: 627 case WM8580_DAC_CLKSEL:
689 reg = wm8580_read(codec, WM8580_CLKSEL); 628 reg = snd_soc_read(codec, WM8580_CLKSEL);
690 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; 629 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
691 630
692 switch (div) { 631 switch (div) {
@@ -704,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
704 default: 643 default:
705 return -EINVAL; 644 return -EINVAL;
706 } 645 }
707 wm8580_write(codec, WM8580_CLKSEL, reg); 646 snd_soc_write(codec, WM8580_CLKSEL, reg);
708 break; 647 break;
709 648
710 case WM8580_CLKOUTSRC: 649 case WM8580_CLKOUTSRC:
711 reg = wm8580_read(codec, WM8580_PLLB4); 650 reg = snd_soc_read(codec, WM8580_PLLB4);
712 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; 651 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
713 652
714 switch (div) { 653 switch (div) {
@@ -730,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
730 default: 669 default:
731 return -EINVAL; 670 return -EINVAL;
732 } 671 }
733 wm8580_write(codec, WM8580_PLLB4, reg); 672 snd_soc_write(codec, WM8580_PLLB4, reg);
734 break; 673 break;
735 674
736 default: 675 default:
@@ -745,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
745 struct snd_soc_codec *codec = codec_dai->codec; 684 struct snd_soc_codec *codec = codec_dai->codec;
746 unsigned int reg; 685 unsigned int reg;
747 686
748 reg = wm8580_read(codec, WM8580_DAC_CONTROL5); 687 reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
749 688
750 if (mute) 689 if (mute)
751 reg |= WM8580_DAC_CONTROL5_MUTEALL; 690 reg |= WM8580_DAC_CONTROL5_MUTEALL;
752 else 691 else
753 reg &= ~WM8580_DAC_CONTROL5_MUTEALL; 692 reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
754 693
755 wm8580_write(codec, WM8580_DAC_CONTROL5, reg); 694 snd_soc_write(codec, WM8580_DAC_CONTROL5, reg);
756 695
757 return 0; 696 return 0;
758} 697}
@@ -769,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
769 case SND_SOC_BIAS_STANDBY: 708 case SND_SOC_BIAS_STANDBY:
770 if (codec->bias_level == SND_SOC_BIAS_OFF) { 709 if (codec->bias_level == SND_SOC_BIAS_OFF) {
771 /* Power up and get individual control of the DACs */ 710 /* Power up and get individual control of the DACs */
772 reg = wm8580_read(codec, WM8580_PWRDN1); 711 reg = snd_soc_read(codec, WM8580_PWRDN1);
773 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); 712 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
774 wm8580_write(codec, WM8580_PWRDN1, reg); 713 snd_soc_write(codec, WM8580_PWRDN1, reg);
775 714
776 /* Make VMID high impedence */ 715 /* Make VMID high impedence */
777 reg = wm8580_read(codec, WM8580_ADC_CONTROL1); 716 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
778 reg &= ~0x100; 717 reg &= ~0x100;
779 wm8580_write(codec, WM8580_ADC_CONTROL1, reg); 718 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
780 } 719 }
781 break; 720 break;
782 721
783 case SND_SOC_BIAS_OFF: 722 case SND_SOC_BIAS_OFF:
784 reg = wm8580_read(codec, WM8580_PWRDN1); 723 reg = snd_soc_read(codec, WM8580_PWRDN1);
785 wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); 724 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
786 break; 725 break;
787 } 726 }
788 codec->bias_level = level; 727 codec->bias_level = level;
@@ -893,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
893}; 832};
894EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); 833EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
895 834
896static int wm8580_register(struct wm8580_priv *wm8580) 835static int wm8580_register(struct wm8580_priv *wm8580,
836 enum snd_soc_control_type control)
897{ 837{
898 int ret, i; 838 int ret, i;
899 struct snd_soc_codec *codec = &wm8580->codec; 839 struct snd_soc_codec *codec = &wm8580->codec;
@@ -911,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580)
911 codec->private_data = wm8580; 851 codec->private_data = wm8580;
912 codec->name = "WM8580"; 852 codec->name = "WM8580";
913 codec->owner = THIS_MODULE; 853 codec->owner = THIS_MODULE;
914 codec->read = wm8580_read_reg_cache;
915 codec->write = wm8580_write;
916 codec->bias_level = SND_SOC_BIAS_OFF; 854 codec->bias_level = SND_SOC_BIAS_OFF;
917 codec->set_bias_level = wm8580_set_bias_level; 855 codec->set_bias_level = wm8580_set_bias_level;
918 codec->dai = wm8580_dai; 856 codec->dai = wm8580_dai;
@@ -922,11 +860,34 @@ static int wm8580_register(struct wm8580_priv *wm8580)
922 860
923 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); 861 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
924 862
863 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
864 if (ret < 0) {
865 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
866 goto err;
867 }
868
869 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
870 wm8580->supplies[i].supply = wm8580_supply_names[i];
871
872 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
873 wm8580->supplies);
874 if (ret != 0) {
875 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
876 goto err;
877 }
878
879 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
880 wm8580->supplies);
881 if (ret != 0) {
882 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
883 goto err_regulator_get;
884 }
885
925 /* Get the codec into a known state */ 886 /* Get the codec into a known state */
926 ret = wm8580_write(codec, WM8580_RESET, 0); 887 ret = snd_soc_write(codec, WM8580_RESET, 0);
927 if (ret != 0) { 888 if (ret != 0) {
928 dev_err(codec->dev, "Failed to reset codec: %d\n", ret); 889 dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
929 goto err; 890 goto err_regulator_enable;
930 } 891 }
931 892
932 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) 893 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
@@ -939,7 +900,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
939 ret = snd_soc_register_codec(codec); 900 ret = snd_soc_register_codec(codec);
940 if (ret != 0) { 901 if (ret != 0) {
941 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 902 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
942 goto err; 903 goto err_regulator_enable;
943 } 904 }
944 905
945 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 906 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
@@ -952,6 +913,10 @@ static int wm8580_register(struct wm8580_priv *wm8580)
952 913
953err_codec: 914err_codec:
954 snd_soc_unregister_codec(codec); 915 snd_soc_unregister_codec(codec);
916err_regulator_enable:
917 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
918err_regulator_get:
919 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
955err: 920err:
956 kfree(wm8580); 921 kfree(wm8580);
957 return ret; 922 return ret;
@@ -962,6 +927,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580)
962 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); 927 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
963 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 928 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
964 snd_soc_unregister_codec(&wm8580->codec); 929 snd_soc_unregister_codec(&wm8580->codec);
930 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
931 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
965 kfree(wm8580); 932 kfree(wm8580);
966 wm8580_codec = NULL; 933 wm8580_codec = NULL;
967} 934}
@@ -978,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
978 return -ENOMEM; 945 return -ENOMEM;
979 946
980 codec = &wm8580->codec; 947 codec = &wm8580->codec;
981 codec->hw_write = (hw_write_t)i2c_master_send;
982 948
983 i2c_set_clientdata(i2c, wm8580); 949 i2c_set_clientdata(i2c, wm8580);
984 codec->control_data = i2c; 950 codec->control_data = i2c;
985 951
986 codec->dev = &i2c->dev; 952 codec->dev = &i2c->dev;
987 953
988 return wm8580_register(wm8580); 954 return wm8580_register(wm8580, SND_SOC_I2C);
989} 955}
990 956
991static int wm8580_i2c_remove(struct i2c_client *client) 957static int wm8580_i2c_remove(struct i2c_client *client)
@@ -995,6 +961,21 @@ static int wm8580_i2c_remove(struct i2c_client *client)
995 return 0; 961 return 0;
996} 962}
997 963
964#ifdef CONFIG_PM
965static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
966{
967 return snd_soc_suspend_device(&client->dev);
968}
969
970static 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
998static const struct i2c_device_id wm8580_i2c_id[] = { 979static const struct i2c_device_id wm8580_i2c_id[] = {
999 { "wm8580", 0 }, 980 { "wm8580", 0 },
1000 { } 981 { }
@@ -1008,6 +989,8 @@ static struct i2c_driver wm8580_i2c_driver = {
1008 }, 989 },
1009 .probe = wm8580_i2c_probe, 990 .probe = wm8580_i2c_probe,
1010 .remove = wm8580_i2c_remove, 991 .remove = wm8580_i2c_remove,
992 .suspend = wm8580_i2c_suspend,
993 .resume = wm8580_i2c_resume,
1011 .id_table = wm8580_i2c_id, 994 .id_table = wm8580_i2c_id,
1012}; 995};
1013#endif 996#endif
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index e7ff2121ede9..16e969a762c3 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
43 0x100, 43 0x100,
44}; 44};
45 45
46static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
47 unsigned int reg)
48{
49 u16 *cache = codec->reg_cache;
50 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
51 return cache[reg];
52}
53
54static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
55 u16 reg, unsigned int value)
56{
57 u16 *cache = codec->reg_cache;
58 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
59 cache[reg] = value;
60}
61
62/*
63 * write to the WM8728 register space
64 */
65static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
66 unsigned int value)
67{
68 u8 data[2];
69
70 /* data is
71 * D15..D9 WM8728 register offset
72 * D8...D0 register data
73 */
74 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
75 data[1] = value & 0x00ff;
76
77 wm8728_write_reg_cache(codec, reg, value);
78
79 if (codec->hw_write(codec->control_data, data, 2) == 2)
80 return 0;
81 else
82 return -EIO;
83}
84
85static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); 46static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
86 47
87static const struct snd_kcontrol_new wm8728_snd_controls[] = { 48static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
121static int wm8728_mute(struct snd_soc_dai *dai, int mute) 82static int wm8728_mute(struct snd_soc_dai *dai, int mute)
122{ 83{
123 struct snd_soc_codec *codec = dai->codec; 84 struct snd_soc_codec *codec = dai->codec;
124 u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 85 u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL);
125 86
126 if (mute) 87 if (mute)
127 wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); 88 snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1);
128 else 89 else
129 wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); 90 snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1);
130 91
131 return 0; 92 return 0;
132} 93}
@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
138 struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 struct snd_soc_pcm_runtime *rtd = substream->private_data;
139 struct snd_soc_device *socdev = rtd->socdev; 100 struct snd_soc_device *socdev = rtd->socdev;
140 struct snd_soc_codec *codec = socdev->card->codec; 101 struct snd_soc_codec *codec = socdev->card->codec;
141 u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); 102 u16 dac = snd_soc_read(codec, WM8728_DACCTL);
142 103
143 dac &= ~0x18; 104 dac &= ~0x18;
144 105
@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
155 return -EINVAL; 116 return -EINVAL;
156 } 117 }
157 118
158 wm8728_write(codec, WM8728_DACCTL, dac); 119 snd_soc_write(codec, WM8728_DACCTL, dac);
159 120
160 return 0; 121 return 0;
161} 122}
@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
164 unsigned int fmt) 125 unsigned int fmt)
165{ 126{
166 struct snd_soc_codec *codec = codec_dai->codec; 127 struct snd_soc_codec *codec = codec_dai->codec;
167 u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); 128 u16 iface = snd_soc_read(codec, WM8728_IFCTL);
168 129
169 /* Currently only I2S is supported by the driver, though the 130 /* Currently only I2S is supported by the driver, though the
170 * hardware is more flexible. 131 * hardware is more flexible.
@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
204 return -EINVAL; 165 return -EINVAL;
205 } 166 }
206 167
207 wm8728_write(codec, WM8728_IFCTL, iface); 168 snd_soc_write(codec, WM8728_IFCTL, iface);
208 return 0; 169 return 0;
209} 170}
210 171
@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
220 case SND_SOC_BIAS_STANDBY: 181 case SND_SOC_BIAS_STANDBY:
221 if (codec->bias_level == SND_SOC_BIAS_OFF) { 182 if (codec->bias_level == SND_SOC_BIAS_OFF) {
222 /* Power everything up... */ 183 /* Power everything up... */
223 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 184 reg = snd_soc_read(codec, WM8728_DACCTL);
224 wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); 185 snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
225 186
226 /* ..then sync in the register cache. */ 187 /* ..then sync in the register cache. */
227 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) 188 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
228 wm8728_write(codec, i, 189 snd_soc_write(codec, i,
229 wm8728_read_reg_cache(codec, i)); 190 snd_soc_read(codec, i));
230 } 191 }
231 break; 192 break;
232 193
233 case SND_SOC_BIAS_OFF: 194 case SND_SOC_BIAS_OFF:
234 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 195 reg = snd_soc_read(codec, WM8728_DACCTL);
235 wm8728_write(codec, WM8728_DACCTL, reg | 0x4); 196 snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
236 break; 197 break;
237 } 198 }
238 codec->bias_level = level; 199 codec->bias_level = level;
@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev)
287 * initialise the WM8728 driver 248 * initialise the WM8728 driver
288 * register the mixer and dsp interfaces with the kernel 249 * register the mixer and dsp interfaces with the kernel
289 */ 250 */
290static int wm8728_init(struct snd_soc_device *socdev) 251static int wm8728_init(struct snd_soc_device *socdev,
252 enum snd_soc_control_type control)
291{ 253{
292 struct snd_soc_codec *codec = socdev->card->codec; 254 struct snd_soc_codec *codec = socdev->card->codec;
293 int ret = 0; 255 int ret = 0;
294 256
295 codec->name = "WM8728"; 257 codec->name = "WM8728";
296 codec->owner = THIS_MODULE; 258 codec->owner = THIS_MODULE;
297 codec->read = wm8728_read_reg_cache;
298 codec->write = wm8728_write;
299 codec->set_bias_level = wm8728_set_bias_level; 259 codec->set_bias_level = wm8728_set_bias_level;
300 codec->dai = &wm8728_dai; 260 codec->dai = &wm8728_dai;
301 codec->num_dai = 1; 261 codec->num_dai = 1;
@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
307 if (codec->reg_cache == NULL) 267 if (codec->reg_cache == NULL)
308 return -ENOMEM; 268 return -ENOMEM;
309 269
270 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
271 if (ret < 0) {
272 printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
273 ret);
274 goto err;
275 }
276
310 /* register pcms */ 277 /* register pcms */
311 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 278 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
312 if (ret < 0) { 279 if (ret < 0) {
313 printk(KERN_ERR "wm8728: failed to create pcms\n"); 280 printk(KERN_ERR "wm8728: failed to create pcms\n");
314 goto pcm_err; 281 goto err;
315 } 282 }
316 283
317 /* power on device */ 284 /* power on device */
@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
331card_err: 298card_err:
332 snd_soc_free_pcms(socdev); 299 snd_soc_free_pcms(socdev);
333 snd_soc_dapm_free(socdev); 300 snd_soc_dapm_free(socdev);
334pcm_err: 301err:
335 kfree(codec->reg_cache); 302 kfree(codec->reg_cache);
336 return ret; 303 return ret;
337} 304}
@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c,
357 i2c_set_clientdata(i2c, codec); 324 i2c_set_clientdata(i2c, codec);
358 codec->control_data = i2c; 325 codec->control_data = i2c;
359 326
360 ret = wm8728_init(socdev); 327 ret = wm8728_init(socdev, SND_SOC_I2C);
361 if (ret < 0) 328 if (ret < 0)
362 pr_err("failed to initialise WM8728\n"); 329 pr_err("failed to initialise WM8728\n");
363 330
@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
437 404
438 codec->control_data = spi; 405 codec->control_data = spi;
439 406
440 ret = wm8728_init(socdev); 407 ret = wm8728_init(socdev, SND_SOC_SPI);
441 if (ret < 0) 408 if (ret < 0)
442 dev_err(&spi->dev, "failed to initialise WM8728\n"); 409 dev_err(&spi->dev, "failed to initialise WM8728\n");
443 410
@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = {
458 .probe = wm8728_spi_probe, 425 .probe = wm8728_spi_probe,
459 .remove = __devexit_p(wm8728_spi_remove), 426 .remove = __devexit_p(wm8728_spi_remove),
460}; 427};
461
462static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
463{
464 struct spi_transfer t;
465 struct spi_message m;
466 u8 msg[2];
467
468 if (len <= 0)
469 return 0;
470
471 msg[0] = data[0];
472 msg[1] = data[1];
473
474 spi_message_init(&m);
475 memset(&t, 0, (sizeof t));
476
477 t.tx_buf = &msg[0];
478 t.len = len;
479
480 spi_message_add_tail(&t, &m);
481 spi_sync(spi, &m);
482
483 return len;
484}
485#endif /* CONFIG_SPI_MASTER */ 428#endif /* CONFIG_SPI_MASTER */
486 429
487static int wm8728_probe(struct platform_device *pdev) 430static int wm8728_probe(struct platform_device *pdev)
@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev)
506 449
507#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 450#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
508 if (setup->i2c_address) { 451 if (setup->i2c_address) {
509 codec->hw_write = (hw_write_t)i2c_master_send;
510 ret = wm8728_add_i2c_device(pdev, setup); 452 ret = wm8728_add_i2c_device(pdev, setup);
511 } 453 }
512#endif 454#endif
513#if defined(CONFIG_SPI_MASTER) 455#if defined(CONFIG_SPI_MASTER)
514 if (setup->spi) { 456 if (setup->spi) {
515 codec->hw_write = (hw_write_t)wm8728_spi_write;
516 ret = spi_register_driver(&wm8728_spi_driver); 457 ret = spi_register_driver(&wm8728_spi_driver);
517 if (ret != 0) 458 if (ret != 0)
518 printk(KERN_ERR "can't add spi driver"); 459 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index e043e3f60008..d3fd4f28d96e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -26,6 +26,7 @@
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/soc-dapm.h> 27#include <sound/soc-dapm.h>
28#include <sound/initval.h> 28#include <sound/initval.h>
29#include <sound/tlv.h>
29 30
30#include "wm8731.h" 31#include "wm8731.h"
31 32
@@ -39,9 +40,6 @@ struct wm8731_priv {
39 unsigned int sysclk; 40 unsigned int sysclk;
40}; 41};
41 42
42#ifdef CONFIG_SPI_MASTER
43static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
44#endif
45 43
46/* 44/*
47 * wm8731 register cache 45 * wm8731 register cache
@@ -50,60 +48,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
50 * There is no point in caching the reset register 48 * There is no point in caching the reset register
51 */ 49 */
52static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { 50static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
53 0x0097, 0x0097, 0x0079, 0x0079, 51 0x0097, 0x0097, 0x0079, 0x0079,
54 0x000a, 0x0008, 0x009f, 0x000a, 52 0x000a, 0x0008, 0x009f, 0x000a,
55 0x0000, 0x0000 53 0x0000, 0x0000
56}; 54};
57 55
58/* 56#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
59 * read wm8731 register cache
60 */
61static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg == WM8731_RESET)
66 return 0;
67 if (reg >= WM8731_CACHEREGNUM)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8731 register cache
74 */
75static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
76 u16 reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg >= WM8731_CACHEREGNUM)
80 return;
81 cache[reg] = value;
82}
83
84/*
85 * write to the WM8731 register space
86 */
87static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
88 unsigned int value)
89{
90 u8 data[2];
91
92 /* data is
93 * D15..D9 WM8731 register offset
94 * D8...D0 register data
95 */
96 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
97 data[1] = value & 0x00ff;
98
99 wm8731_write_reg_cache(codec, reg, value);
100 if (codec->hw_write(codec->control_data, data, 2) == 2)
101 return 0;
102 else
103 return -EIO;
104}
105
106#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
107 57
108static const char *wm8731_input_select[] = {"Line In", "Mic"}; 58static const char *wm8731_input_select[] = {"Line In", "Mic"};
109static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 59static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -113,20 +63,26 @@ static const struct soc_enum wm8731_enum[] = {
113 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), 63 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
114}; 64};
115 65
66static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
67static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
68static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
69
116static const struct snd_kcontrol_new wm8731_snd_controls[] = { 70static const struct snd_kcontrol_new wm8731_snd_controls[] = {
117 71
118SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, 72SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
119 0, 127, 0), 73 0, 127, 0, out_tlv),
120SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 74SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
121 7, 1, 0), 75 7, 1, 0),
122 76
123SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0), 77SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
78 in_tlv),
124SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), 79SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
125 80
126SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), 81SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
127SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1), 82SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
128 83
129SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1), 84SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
85 sidetone_tlv),
130 86
131SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), 87SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
132SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), 88SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
@@ -260,12 +216,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
260 struct snd_soc_device *socdev = rtd->socdev; 216 struct snd_soc_device *socdev = rtd->socdev;
261 struct snd_soc_codec *codec = socdev->card->codec; 217 struct snd_soc_codec *codec = socdev->card->codec;
262 struct wm8731_priv *wm8731 = codec->private_data; 218 struct wm8731_priv *wm8731 = codec->private_data;
263 u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; 219 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
264 int i = get_coeff(wm8731->sysclk, params_rate(params)); 220 int i = get_coeff(wm8731->sysclk, params_rate(params));
265 u16 srate = (coeff_div[i].sr << 2) | 221 u16 srate = (coeff_div[i].sr << 2) |
266 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 222 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
267 223
268 wm8731_write(codec, WM8731_SRATE, srate); 224 snd_soc_write(codec, WM8731_SRATE, srate);
269 225
270 /* bit size */ 226 /* bit size */
271 switch (params_format(params)) { 227 switch (params_format(params)) {
@@ -279,7 +235,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
279 break; 235 break;
280 } 236 }
281 237
282 wm8731_write(codec, WM8731_IFACE, iface); 238 snd_soc_write(codec, WM8731_IFACE, iface);
283 return 0; 239 return 0;
284} 240}
285 241
@@ -291,7 +247,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
291 struct snd_soc_codec *codec = socdev->card->codec; 247 struct snd_soc_codec *codec = socdev->card->codec;
292 248
293 /* set active */ 249 /* set active */
294 wm8731_write(codec, WM8731_ACTIVE, 0x0001); 250 snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
295 251
296 return 0; 252 return 0;
297} 253}
@@ -306,19 +262,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
306 /* deactivate */ 262 /* deactivate */
307 if (!codec->active) { 263 if (!codec->active) {
308 udelay(50); 264 udelay(50);
309 wm8731_write(codec, WM8731_ACTIVE, 0x0); 265 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
310 } 266 }
311} 267}
312 268
313static int wm8731_mute(struct snd_soc_dai *dai, int mute) 269static int wm8731_mute(struct snd_soc_dai *dai, int mute)
314{ 270{
315 struct snd_soc_codec *codec = dai->codec; 271 struct snd_soc_codec *codec = dai->codec;
316 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; 272 u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
317 273
318 if (mute) 274 if (mute)
319 wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); 275 snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
320 else 276 else
321 wm8731_write(codec, WM8731_APDIGI, mute_reg); 277 snd_soc_write(codec, WM8731_APDIGI, mute_reg);
322 return 0; 278 return 0;
323} 279}
324 280
@@ -396,7 +352,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
396 } 352 }
397 353
398 /* set iface */ 354 /* set iface */
399 wm8731_write(codec, WM8731_IFACE, iface); 355 snd_soc_write(codec, WM8731_IFACE, iface);
400 return 0; 356 return 0;
401} 357}
402 358
@@ -412,12 +368,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
412 break; 368 break;
413 case SND_SOC_BIAS_STANDBY: 369 case SND_SOC_BIAS_STANDBY:
414 /* Clear PWROFF, gate CLKOUT, everything else as-is */ 370 /* Clear PWROFF, gate CLKOUT, everything else as-is */
415 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; 371 reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
416 wm8731_write(codec, WM8731_PWR, reg | 0x0040); 372 snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
417 break; 373 break;
418 case SND_SOC_BIAS_OFF: 374 case SND_SOC_BIAS_OFF:
419 wm8731_write(codec, WM8731_ACTIVE, 0x0); 375 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
420 wm8731_write(codec, WM8731_PWR, 0xffff); 376 snd_soc_write(codec, WM8731_PWR, 0xffff);
421 break; 377 break;
422 } 378 }
423 codec->bias_level = level; 379 codec->bias_level = level;
@@ -457,15 +413,17 @@ struct snd_soc_dai wm8731_dai = {
457 .rates = WM8731_RATES, 413 .rates = WM8731_RATES,
458 .formats = WM8731_FORMATS,}, 414 .formats = WM8731_FORMATS,},
459 .ops = &wm8731_dai_ops, 415 .ops = &wm8731_dai_ops,
416 .symmetric_rates = 1,
460}; 417};
461EXPORT_SYMBOL_GPL(wm8731_dai); 418EXPORT_SYMBOL_GPL(wm8731_dai);
462 419
420#ifdef CONFIG_PM
463static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) 421static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
464{ 422{
465 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 423 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
466 struct snd_soc_codec *codec = socdev->card->codec; 424 struct snd_soc_codec *codec = socdev->card->codec;
467 425
468 wm8731_write(codec, WM8731_ACTIVE, 0x0); 426 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
469 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
470 return 0; 428 return 0;
471} 429}
@@ -488,6 +446,10 @@ static int wm8731_resume(struct platform_device *pdev)
488 wm8731_set_bias_level(codec, codec->suspend_bias_level); 446 wm8731_set_bias_level(codec, codec->suspend_bias_level);
489 return 0; 447 return 0;
490} 448}
449#else
450#define wm8731_suspend NULL
451#define wm8731_resume NULL
452#endif
491 453
492static int wm8731_probe(struct platform_device *pdev) 454static int wm8731_probe(struct platform_device *pdev)
493{ 455{
@@ -547,15 +509,16 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
547}; 509};
548EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); 510EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
549 511
550static int wm8731_register(struct wm8731_priv *wm8731) 512static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control)
551{ 514{
552 int ret; 515 int ret;
553 struct snd_soc_codec *codec = &wm8731->codec; 516 struct snd_soc_codec *codec = &wm8731->codec;
554 u16 reg;
555 517
556 if (wm8731_codec) { 518 if (wm8731_codec) {
557 dev_err(codec->dev, "Another WM8731 is registered\n"); 519 dev_err(codec->dev, "Another WM8731 is registered\n");
558 return -EINVAL; 520 ret = -EINVAL;
521 goto err;
559 } 522 }
560 523
561 mutex_init(&codec->mutex); 524 mutex_init(&codec->mutex);
@@ -565,8 +528,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
565 codec->private_data = wm8731; 528 codec->private_data = wm8731;
566 codec->name = "WM8731"; 529 codec->name = "WM8731";
567 codec->owner = THIS_MODULE; 530 codec->owner = THIS_MODULE;
568 codec->read = wm8731_read_reg_cache;
569 codec->write = wm8731_write;
570 codec->bias_level = SND_SOC_BIAS_OFF; 531 codec->bias_level = SND_SOC_BIAS_OFF;
571 codec->set_bias_level = wm8731_set_bias_level; 532 codec->set_bias_level = wm8731_set_bias_level;
572 codec->dai = &wm8731_dai; 533 codec->dai = &wm8731_dai;
@@ -576,10 +537,16 @@ static int wm8731_register(struct wm8731_priv *wm8731)
576 537
577 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); 538 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
578 539
540 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
541 if (ret < 0) {
542 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
543 goto err;
544 }
545
579 ret = wm8731_reset(codec); 546 ret = wm8731_reset(codec);
580 if (ret < 0) { 547 if (ret < 0) {
581 dev_err(codec->dev, "Failed to issue reset\n"); 548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
582 return ret; 549 goto err;
583 } 550 }
584 551
585 wm8731_dai.dev = codec->dev; 552 wm8731_dai.dev = codec->dev;
@@ -587,35 +554,36 @@ static int wm8731_register(struct wm8731_priv *wm8731)
587 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 554 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
588 555
589 /* Latch the update bits */ 556 /* Latch the update bits */
590 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); 557 snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
591 wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); 558 snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
592 reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); 559 snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
593 wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); 560 snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
594 reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
595 wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
596 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
597 wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
598 561
599 /* Disable bypass path by default */ 562 /* Disable bypass path by default */
600 reg = wm8731_read_reg_cache(codec, WM8731_APANA); 563 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
601 wm8731_write(codec, WM8731_APANA, reg & ~0x4);
602 564
603 wm8731_codec = codec; 565 wm8731_codec = codec;
604 566
605 ret = snd_soc_register_codec(codec); 567 ret = snd_soc_register_codec(codec);
606 if (ret != 0) { 568 if (ret != 0) {
607 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 569 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
608 return ret; 570 goto err;
609 } 571 }
610 572
611 ret = snd_soc_register_dai(&wm8731_dai); 573 ret = snd_soc_register_dai(&wm8731_dai);
612 if (ret != 0) { 574 if (ret != 0) {
613 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 575 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
614 snd_soc_unregister_codec(codec); 576 snd_soc_unregister_codec(codec);
615 return ret; 577 goto err_codec;
616 } 578 }
617 579
618 return 0; 580 return 0;
581
582err_codec:
583 snd_soc_unregister_codec(codec);
584err:
585 kfree(wm8731);
586 return ret;
619} 587}
620 588
621static void wm8731_unregister(struct wm8731_priv *wm8731) 589static void wm8731_unregister(struct wm8731_priv *wm8731)
@@ -628,30 +596,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
628} 596}
629 597
630#if defined(CONFIG_SPI_MASTER) 598#if defined(CONFIG_SPI_MASTER)
631static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
632{
633 struct spi_transfer t;
634 struct spi_message m;
635 u8 msg[2];
636
637 if (len <= 0)
638 return 0;
639
640 msg[0] = data[0];
641 msg[1] = data[1];
642
643 spi_message_init(&m);
644 memset(&t, 0, (sizeof t));
645
646 t.tx_buf = &msg[0];
647 t.len = len;
648
649 spi_message_add_tail(&t, &m);
650 spi_sync(spi, &m);
651
652 return len;
653}
654
655static int __devinit wm8731_spi_probe(struct spi_device *spi) 599static int __devinit wm8731_spi_probe(struct spi_device *spi)
656{ 600{
657 struct snd_soc_codec *codec; 601 struct snd_soc_codec *codec;
@@ -663,23 +607,37 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
663 607
664 codec = &wm8731->codec; 608 codec = &wm8731->codec;
665 codec->control_data = spi; 609 codec->control_data = spi;
666 codec->hw_write = (hw_write_t)wm8731_spi_write;
667 codec->dev = &spi->dev; 610 codec->dev = &spi->dev;
668 611
669 spi->dev.driver_data = wm8731; 612 dev_set_drvdata(&spi->dev, wm8731);
670 613
671 return wm8731_register(wm8731); 614 return wm8731_register(wm8731, SND_SOC_SPI);
672} 615}
673 616
674static int __devexit wm8731_spi_remove(struct spi_device *spi) 617static int __devexit wm8731_spi_remove(struct spi_device *spi)
675{ 618{
676 struct wm8731_priv *wm8731 = spi->dev.driver_data; 619 struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev);
677 620
678 wm8731_unregister(wm8731); 621 wm8731_unregister(wm8731);
679 622
680 return 0; 623 return 0;
681} 624}
682 625
626#ifdef CONFIG_PM
627static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
628{
629 return snd_soc_suspend_device(&spi->dev);
630}
631
632static 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
683static struct spi_driver wm8731_spi_driver = { 641static struct spi_driver wm8731_spi_driver = {
684 .driver = { 642 .driver = {
685 .name = "wm8731", 643 .name = "wm8731",
@@ -687,6 +645,8 @@ static struct spi_driver wm8731_spi_driver = {
687 .owner = THIS_MODULE, 645 .owner = THIS_MODULE,
688 }, 646 },
689 .probe = wm8731_spi_probe, 647 .probe = wm8731_spi_probe,
648 .suspend = wm8731_spi_suspend,
649 .resume = wm8731_spi_resume,
690 .remove = __devexit_p(wm8731_spi_remove), 650 .remove = __devexit_p(wm8731_spi_remove),
691}; 651};
692#endif /* CONFIG_SPI_MASTER */ 652#endif /* CONFIG_SPI_MASTER */
@@ -703,14 +663,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
703 return -ENOMEM; 663 return -ENOMEM;
704 664
705 codec = &wm8731->codec; 665 codec = &wm8731->codec;
706 codec->hw_write = (hw_write_t)i2c_master_send;
707 666
708 i2c_set_clientdata(i2c, wm8731); 667 i2c_set_clientdata(i2c, wm8731);
709 codec->control_data = i2c; 668 codec->control_data = i2c;
710 669
711 codec->dev = &i2c->dev; 670 codec->dev = &i2c->dev;
712 671
713 return wm8731_register(wm8731); 672 return wm8731_register(wm8731, SND_SOC_I2C);
714} 673}
715 674
716static __devexit int wm8731_i2c_remove(struct i2c_client *client) 675static __devexit int wm8731_i2c_remove(struct i2c_client *client)
@@ -720,6 +679,21 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
720 return 0; 679 return 0;
721} 680}
722 681
682#ifdef CONFIG_PM
683static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
684{
685 return snd_soc_suspend_device(&i2c->dev);
686}
687
688static 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
723static const struct i2c_device_id wm8731_i2c_id[] = { 697static const struct i2c_device_id wm8731_i2c_id[] = {
724 { "wm8731", 0 }, 698 { "wm8731", 0 },
725 { } 699 { }
@@ -733,6 +707,8 @@ static struct i2c_driver wm8731_i2c_driver = {
733 }, 707 },
734 .probe = wm8731_i2c_probe, 708 .probe = wm8731_i2c_probe,
735 .remove = __devexit_p(wm8731_i2c_remove), 709 .remove = __devexit_p(wm8731_i2c_remove),
710 .suspend = wm8731_i2c_suspend,
711 .resume = wm8731_i2c_resume,
736 .id_table = wm8731_i2c_id, 712 .id_table = wm8731_i2c_id,
737}; 713};
738#endif 714#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index b64509b01a49..4ba1e7e93fb4 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
55 0x0079, 0x0079, 0x0079, /* 40 */ 55 0x0079, 0x0079, 0x0079, /* 40 */
56}; 56};
57 57
58/* 58#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
59 * read wm8750 register cache
60 */
61static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg > WM8750_CACHE_REGNUM)
66 return -1;
67 return cache[reg];
68}
69
70/*
71 * write wm8750 register cache
72 */
73static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
74 unsigned int reg, unsigned int value)
75{
76 u16 *cache = codec->reg_cache;
77 if (reg > WM8750_CACHE_REGNUM)
78 return;
79 cache[reg] = value;
80}
81
82static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
83 unsigned int value)
84{
85 u8 data[2];
86
87 /* data is
88 * D15..D9 WM8753 register offset
89 * D8...D0 register data
90 */
91 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
92 data[1] = value & 0x00ff;
93
94 wm8750_write_reg_cache(codec, reg, value);
95 if (codec->hw_write(codec->control_data, data, 2) == 2)
96 return 0;
97 else
98 return -EIO;
99}
100
101#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
102 59
103/* 60/*
104 * WM8750 Controls 61 * WM8750 Controls
@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
594 return -EINVAL; 551 return -EINVAL;
595 } 552 }
596 553
597 wm8750_write(codec, WM8750_IFACE, iface); 554 snd_soc_write(codec, WM8750_IFACE, iface);
598 return 0; 555 return 0;
599} 556}
600 557
@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
606 struct snd_soc_device *socdev = rtd->socdev; 563 struct snd_soc_device *socdev = rtd->socdev;
607 struct snd_soc_codec *codec = socdev->card->codec; 564 struct snd_soc_codec *codec = socdev->card->codec;
608 struct wm8750_priv *wm8750 = codec->private_data; 565 struct wm8750_priv *wm8750 = codec->private_data;
609 u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; 566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
610 u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; 567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
611 int coeff = get_coeff(wm8750->sysclk, params_rate(params)); 568 int coeff = get_coeff(wm8750->sysclk, params_rate(params));
612 569
613 /* bit size */ 570 /* bit size */
@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
626 } 583 }
627 584
628 /* set iface & srate */ 585 /* set iface & srate */
629 wm8750_write(codec, WM8750_IFACE, iface); 586 snd_soc_write(codec, WM8750_IFACE, iface);
630 if (coeff >= 0) 587 if (coeff >= 0)
631 wm8750_write(codec, WM8750_SRATE, srate | 588 snd_soc_write(codec, WM8750_SRATE, srate |
632 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 589 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
633 590
634 return 0; 591 return 0;
@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
637static int wm8750_mute(struct snd_soc_dai *dai, int mute) 594static int wm8750_mute(struct snd_soc_dai *dai, int mute)
638{ 595{
639 struct snd_soc_codec *codec = dai->codec; 596 struct snd_soc_codec *codec = dai->codec;
640 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; 597 u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
641 598
642 if (mute) 599 if (mute)
643 wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); 600 snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
644 else 601 else
645 wm8750_write(codec, WM8750_ADCDAC, mute_reg); 602 snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
646 return 0; 603 return 0;
647} 604}
648 605
649static int wm8750_set_bias_level(struct snd_soc_codec *codec, 606static int wm8750_set_bias_level(struct snd_soc_codec *codec,
650 enum snd_soc_bias_level level) 607 enum snd_soc_bias_level level)
651{ 608{
652 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; 609 u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
653 610
654 switch (level) { 611 switch (level) {
655 case SND_SOC_BIAS_ON: 612 case SND_SOC_BIAS_ON:
656 /* set vmid to 50k and unmute dac */ 613 /* set vmid to 50k and unmute dac */
657 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 614 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
658 break; 615 break;
659 case SND_SOC_BIAS_PREPARE: 616 case SND_SOC_BIAS_PREPARE:
660 /* set vmid to 5k for quick power up */ 617 /* set vmid to 5k for quick power up */
661 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); 618 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
662 break; 619 break;
663 case SND_SOC_BIAS_STANDBY: 620 case SND_SOC_BIAS_STANDBY:
664 /* mute dac and set vmid to 500k, enable VREF */ 621 /* mute dac and set vmid to 500k, enable VREF */
665 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 622 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
666 break; 623 break;
667 case SND_SOC_BIAS_OFF: 624 case SND_SOC_BIAS_OFF:
668 wm8750_write(codec, WM8750_PWR1, 0x0001); 625 snd_soc_write(codec, WM8750_PWR1, 0x0001);
669 break; 626 break;
670 } 627 }
671 codec->bias_level = level; 628 codec->bias_level = level;
@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev)
754 * initialise the WM8750 driver 711 * initialise the WM8750 driver
755 * register the mixer and dsp interfaces with the kernel 712 * register the mixer and dsp interfaces with the kernel
756 */ 713 */
757static int wm8750_init(struct snd_soc_device *socdev) 714static int wm8750_init(struct snd_soc_device *socdev,
715 enum snd_soc_control_type control)
758{ 716{
759 struct snd_soc_codec *codec = socdev->card->codec; 717 struct snd_soc_codec *codec = socdev->card->codec;
760 int reg, ret = 0; 718 int reg, ret = 0;
761 719
762 codec->name = "WM8750"; 720 codec->name = "WM8750";
763 codec->owner = THIS_MODULE; 721 codec->owner = THIS_MODULE;
764 codec->read = wm8750_read_reg_cache;
765 codec->write = wm8750_write;
766 codec->set_bias_level = wm8750_set_bias_level; 722 codec->set_bias_level = wm8750_set_bias_level;
767 codec->dai = &wm8750_dai; 723 codec->dai = &wm8750_dai;
768 codec->num_dai = 1; 724 codec->num_dai = 1;
@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
771 if (codec->reg_cache == NULL) 727 if (codec->reg_cache == NULL)
772 return -ENOMEM; 728 return -ENOMEM;
773 729
774 wm8750_reset(codec); 730 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
731 if (ret < 0) {
732 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
733 goto err;
734 }
735
736 ret = wm8750_reset(codec);
737 if (ret < 0) {
738 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
739 goto err;
740 }
775 741
776 /* register pcms */ 742 /* register pcms */
777 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 743 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
778 if (ret < 0) { 744 if (ret < 0) {
779 printk(KERN_ERR "wm8750: failed to create pcms\n"); 745 printk(KERN_ERR "wm8750: failed to create pcms\n");
780 goto pcm_err; 746 goto err;
781 } 747 }
782 748
783 /* charge output caps */ 749 /* charge output caps */
@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
786 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); 752 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
787 753
788 /* set the update bits */ 754 /* set the update bits */
789 reg = wm8750_read_reg_cache(codec, WM8750_LDAC); 755 reg = snd_soc_read(codec, WM8750_LDAC);
790 wm8750_write(codec, WM8750_LDAC, reg | 0x0100); 756 snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
791 reg = wm8750_read_reg_cache(codec, WM8750_RDAC); 757 reg = snd_soc_read(codec, WM8750_RDAC);
792 wm8750_write(codec, WM8750_RDAC, reg | 0x0100); 758 snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
793 reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); 759 reg = snd_soc_read(codec, WM8750_LOUT1V);
794 wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); 760 snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
795 reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); 761 reg = snd_soc_read(codec, WM8750_ROUT1V);
796 wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); 762 snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
797 reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); 763 reg = snd_soc_read(codec, WM8750_LOUT2V);
798 wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); 764 snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
799 reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); 765 reg = snd_soc_read(codec, WM8750_ROUT2V);
800 wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); 766 snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
801 reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); 767 reg = snd_soc_read(codec, WM8750_LINVOL);
802 wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); 768 snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
803 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); 769 reg = snd_soc_read(codec, WM8750_RINVOL);
804 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); 770 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
805 771
806 snd_soc_add_controls(codec, wm8750_snd_controls, 772 snd_soc_add_controls(codec, wm8750_snd_controls,
807 ARRAY_SIZE(wm8750_snd_controls)); 773 ARRAY_SIZE(wm8750_snd_controls));
@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
816card_err: 782card_err:
817 snd_soc_free_pcms(socdev); 783 snd_soc_free_pcms(socdev);
818 snd_soc_dapm_free(socdev); 784 snd_soc_dapm_free(socdev);
819pcm_err: 785err:
820 kfree(codec->reg_cache); 786 kfree(codec->reg_cache);
821 return ret; 787 return ret;
822} 788}
@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c,
844 i2c_set_clientdata(i2c, codec); 810 i2c_set_clientdata(i2c, codec);
845 codec->control_data = i2c; 811 codec->control_data = i2c;
846 812
847 ret = wm8750_init(socdev); 813 ret = wm8750_init(socdev, SND_SOC_I2C);
848 if (ret < 0) 814 if (ret < 0)
849 pr_err("failed to initialise WM8750\n"); 815 pr_err("failed to initialise WM8750\n");
850 816
@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
924 890
925 codec->control_data = spi; 891 codec->control_data = spi;
926 892
927 ret = wm8750_init(socdev); 893 ret = wm8750_init(socdev, SND_SOC_SPI);
928 if (ret < 0) 894 if (ret < 0)
929 dev_err(&spi->dev, "failed to initialise WM8750\n"); 895 dev_err(&spi->dev, "failed to initialise WM8750\n");
930 896
@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = {
945 .probe = wm8750_spi_probe, 911 .probe = wm8750_spi_probe,
946 .remove = __devexit_p(wm8750_spi_remove), 912 .remove = __devexit_p(wm8750_spi_remove),
947}; 913};
948
949static int wm8750_spi_write(struct spi_device *spi, const char *data, int len)
950{
951 struct spi_transfer t;
952 struct spi_message m;
953 u8 msg[2];
954
955 if (len <= 0)
956 return 0;
957
958 msg[0] = data[0];
959 msg[1] = data[1];
960
961 spi_message_init(&m);
962 memset(&t, 0, (sizeof t));
963
964 t.tx_buf = &msg[0];
965 t.len = len;
966
967 spi_message_add_tail(&t, &m);
968 spi_sync(spi, &m);
969
970 return len;
971}
972#endif 914#endif
973 915
974static int wm8750_probe(struct platform_device *pdev) 916static int wm8750_probe(struct platform_device *pdev)
@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev)
1002 944
1003#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 945#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1004 if (setup->i2c_address) { 946 if (setup->i2c_address) {
1005 codec->hw_write = (hw_write_t)i2c_master_send;
1006 ret = wm8750_add_i2c_device(pdev, setup); 947 ret = wm8750_add_i2c_device(pdev, setup);
1007 } 948 }
1008#endif 949#endif
1009#if defined(CONFIG_SPI_MASTER) 950#if defined(CONFIG_SPI_MASTER)
1010 if (setup->spi) { 951 if (setup->spi) {
1011 codec->hw_write = (hw_write_t)wm8750_spi_write;
1012 ret = spi_register_driver(&wm8750_spi_driver); 952 ret = spi_register_driver(&wm8750_spi_driver);
1013 if (ret != 0) 953 if (ret != 0)
1014 printk(KERN_ERR "can't add spi driver"); 954 printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a6e8f3f7f052..d80d414cfbbd 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = {
79 0x0097, 0x0097, 0x0000, 0x0004, 79 0x0097, 0x0097, 0x0000, 0x0004,
80 0x0000, 0x0083, 0x0024, 0x01ba, 80 0x0000, 0x0083, 0x0024, 0x01ba,
81 0x0000, 0x0083, 0x0024, 0x01ba, 81 0x0000, 0x0083, 0x0024, 0x01ba,
82 0x0000, 0x0000 82 0x0000, 0x0000, 0x0000
83}; 83};
84 84
85/* codec private data */ 85/* codec private data */
@@ -703,7 +703,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
703 703
704 if ((Ndiv < 6) || (Ndiv > 12)) 704 if ((Ndiv < 6) || (Ndiv > 12))
705 printk(KERN_WARNING 705 printk(KERN_WARNING
706 "wm8753: unsupported N = %d\n", Ndiv); 706 "wm8753: unsupported N = %u\n", Ndiv);
707 707
708 pll_div->n = Ndiv; 708 pll_div->n = Ndiv;
709 Nmod = target % source; 709 Nmod = target % source;
@@ -1660,11 +1660,11 @@ static int wm8753_register(struct wm8753_priv *wm8753)
1660 codec->set_bias_level = wm8753_set_bias_level; 1660 codec->set_bias_level = wm8753_set_bias_level;
1661 codec->dai = wm8753_dai; 1661 codec->dai = wm8753_dai;
1662 codec->num_dai = 2; 1662 codec->num_dai = 2;
1663 codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); 1663 codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
1664 codec->reg_cache = &wm8753->reg_cache; 1664 codec->reg_cache = &wm8753->reg_cache;
1665 codec->private_data = wm8753; 1665 codec->private_data = wm8753;
1666 1666
1667 memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); 1667 memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
1668 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); 1668 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
1669 1669
1670 ret = wm8753_reset(codec); 1670 ret = wm8753_reset(codec);
@@ -1766,6 +1766,21 @@ static int wm8753_i2c_remove(struct i2c_client *client)
1766 return 0; 1766 return 0;
1767} 1767}
1768 1768
1769#ifdef CONFIG_PM
1770static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1771{
1772 return snd_soc_suspend_device(&client->dev);
1773}
1774
1775static int wm8753_i2c_resume(struct i2c_client *client)
1776{
1777 return snd_soc_resume_device(&client->dev);
1778}
1779#else
1780#define wm8753_i2c_suspend NULL
1781#define wm8753_i2c_resume NULL
1782#endif
1783
1769static const struct i2c_device_id wm8753_i2c_id[] = { 1784static const struct i2c_device_id wm8753_i2c_id[] = {
1770 { "wm8753", 0 }, 1785 { "wm8753", 0 },
1771 { } 1786 { }
@@ -1779,6 +1794,8 @@ static struct i2c_driver wm8753_i2c_driver = {
1779 }, 1794 },
1780 .probe = wm8753_i2c_probe, 1795 .probe = wm8753_i2c_probe,
1781 .remove = wm8753_i2c_remove, 1796 .remove = wm8753_i2c_remove,
1797 .suspend = wm8753_i2c_suspend,
1798 .resume = wm8753_i2c_resume,
1782 .id_table = wm8753_i2c_id, 1799 .id_table = wm8753_i2c_id,
1783}; 1800};
1784#endif 1801#endif
@@ -1822,18 +1839,34 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
1822 codec->hw_write = (hw_write_t)wm8753_spi_write; 1839 codec->hw_write = (hw_write_t)wm8753_spi_write;
1823 codec->dev = &spi->dev; 1840 codec->dev = &spi->dev;
1824 1841
1825 spi->dev.driver_data = wm8753; 1842 dev_set_drvdata(&spi->dev, wm8753);
1826 1843
1827 return wm8753_register(wm8753); 1844 return wm8753_register(wm8753);
1828} 1845}
1829 1846
1830static int __devexit wm8753_spi_remove(struct spi_device *spi) 1847static int __devexit wm8753_spi_remove(struct spi_device *spi)
1831{ 1848{
1832 struct wm8753_priv *wm8753 = spi->dev.driver_data; 1849 struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev);
1833 wm8753_unregister(wm8753); 1850 wm8753_unregister(wm8753);
1834 return 0; 1851 return 0;
1835} 1852}
1836 1853
1854#ifdef CONFIG_PM
1855static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
1856{
1857 return snd_soc_suspend_device(&spi->dev);
1858}
1859
1860static int wm8753_spi_resume(struct spi_device *spi)
1861{
1862 return snd_soc_resume_device(&spi->dev);
1863}
1864
1865#else
1866#define wm8753_spi_suspend NULL
1867#define wm8753_spi_resume NULL
1868#endif
1869
1837static struct spi_driver wm8753_spi_driver = { 1870static struct spi_driver wm8753_spi_driver = {
1838 .driver = { 1871 .driver = {
1839 .name = "wm8753", 1872 .name = "wm8753",
@@ -1842,6 +1875,8 @@ static struct spi_driver wm8753_spi_driver = {
1842 }, 1875 },
1843 .probe = wm8753_spi_probe, 1876 .probe = wm8753_spi_probe,
1844 .remove = __devexit_p(wm8753_spi_remove), 1877 .remove = __devexit_p(wm8753_spi_remove),
1878 .suspend = wm8753_spi_suspend,
1879 .resume = wm8753_spi_resume,
1845}; 1880};
1846#endif 1881#endif
1847 1882
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
new file mode 100644
index 000000000000..a9829aa26e53
--- /dev/null
+++ b/sound/soc/codecs/wm8776.c
@@ -0,0 +1,744 @@
1/*
2 * wm8776.c -- WM8776 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 * TODO: Input ALC/limiter support
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 <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 "wm8776.h"
32
33static struct snd_soc_codec *wm8776_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8776;
35
36/* codec private data */
37struct wm8776_priv {
38 struct snd_soc_codec codec;
39 u16 reg_cache[WM8776_CACHEREGNUM];
40 int sysclk[2];
41};
42
43#ifdef CONFIG_SPI_MASTER
44static int wm8776_spi_write(struct spi_device *spi, const char *data, int len);
45#endif
46
47static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {
48 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */
49 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */
50 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */
51 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */
52 0xa6, 0x01, 0x01
53};
54
55static int wm8776_reset(struct snd_soc_codec *codec)
56{
57 return snd_soc_write(codec, WM8776_RESET, 0);
58}
59
60static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1);
61static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
62static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);
63
64static const struct snd_kcontrol_new wm8776_snd_controls[] = {
65SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL,
66 0, 127, 0, hp_tlv),
67SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL,
68 0, 255, 0, dac_tlv),
69SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0),
70
71SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0),
72
73SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL,
74 0, 255, 0, adc_tlv),
75SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1),
76SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0),
77SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1),
78};
79
80static const struct snd_kcontrol_new inmix_controls[] = {
81SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0),
82SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0),
83SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0),
84SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0),
85SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0),
86};
87
88static const struct snd_kcontrol_new outmix_controls[] = {
89SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0),
90SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0),
91SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0),
92};
93
94static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
95SND_SOC_DAPM_INPUT("AUX"),
96SND_SOC_DAPM_INPUT("AUX"),
97
98SND_SOC_DAPM_INPUT("AIN1"),
99SND_SOC_DAPM_INPUT("AIN2"),
100SND_SOC_DAPM_INPUT("AIN3"),
101SND_SOC_DAPM_INPUT("AIN4"),
102SND_SOC_DAPM_INPUT("AIN5"),
103
104SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1,
105 inmix_controls, ARRAY_SIZE(inmix_controls)),
106
107SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1),
108SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1),
109
110SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
111 outmix_controls, ARRAY_SIZE(outmix_controls)),
112
113SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0),
114
115SND_SOC_DAPM_OUTPUT("VOUT"),
116
117SND_SOC_DAPM_OUTPUT("HPOUTL"),
118SND_SOC_DAPM_OUTPUT("HPOUTR"),
119};
120
121static const struct snd_soc_dapm_route routes[] = {
122 { "Input Mixer", "AIN1 Switch", "AIN1" },
123 { "Input Mixer", "AIN2 Switch", "AIN2" },
124 { "Input Mixer", "AIN3 Switch", "AIN3" },
125 { "Input Mixer", "AIN4 Switch", "AIN4" },
126 { "Input Mixer", "AIN5 Switch", "AIN5" },
127
128 { "ADC", NULL, "Input Mixer" },
129
130 { "Output Mixer", "DAC Switch", "DAC" },
131 { "Output Mixer", "AUX Switch", "AUX" },
132 { "Output Mixer", "Bypass Switch", "Input Mixer" },
133
134 { "VOUT", NULL, "Output Mixer" },
135
136 { "Headphone PGA", NULL, "Output Mixer" },
137
138 { "HPOUTL", NULL, "Headphone PGA" },
139 { "HPOUTR", NULL, "Headphone PGA" },
140};
141
142static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
143{
144 struct snd_soc_codec *codec = dai->codec;
145 int reg, iface, master;
146
147 switch (dai->id) {
148 case WM8776_DAI_DAC:
149 reg = WM8776_DACIFCTRL;
150 master = 0x80;
151 break;
152 case WM8776_DAI_ADC:
153 reg = WM8776_ADCIFCTRL;
154 master = 0x100;
155 break;
156 default:
157 return -EINVAL;
158 }
159
160 iface = 0;
161
162 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
163 case SND_SOC_DAIFMT_CBM_CFM:
164 break;
165 case SND_SOC_DAIFMT_CBS_CFS:
166 master = 0;
167 break;
168 default:
169 return -EINVAL;
170 }
171
172 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
173 case SND_SOC_DAIFMT_I2S:
174 iface |= 0x0002;
175 break;
176 case SND_SOC_DAIFMT_RIGHT_J:
177 break;
178 case SND_SOC_DAIFMT_LEFT_J:
179 iface |= 0x0001;
180 break;
181 /* FIXME: CHECK A/B */
182 case SND_SOC_DAIFMT_DSP_A:
183 iface |= 0x0003;
184 break;
185 case SND_SOC_DAIFMT_DSP_B:
186 iface |= 0x0007;
187 break;
188 default:
189 return -EINVAL;
190 }
191
192 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
193 case SND_SOC_DAIFMT_NB_NF:
194 break;
195 case SND_SOC_DAIFMT_IB_IF:
196 iface |= 0x00c;
197 break;
198 case SND_SOC_DAIFMT_IB_NF:
199 iface |= 0x008;
200 break;
201 case SND_SOC_DAIFMT_NB_IF:
202 iface |= 0x004;
203 break;
204 default:
205 return -EINVAL;
206 }
207
208 /* Finally, write out the values */
209 snd_soc_update_bits(codec, reg, 0xf, iface);
210 snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master);
211
212 return 0;
213}
214
215static int mclk_ratios[] = {
216 128,
217 192,
218 256,
219 384,
220 512,
221 768,
222};
223
224static int wm8776_hw_params(struct snd_pcm_substream *substream,
225 struct snd_pcm_hw_params *params,
226 struct snd_soc_dai *dai)
227{
228 struct snd_soc_codec *codec = dai->codec;
229 struct wm8776_priv *wm8776 = codec->private_data;
230 int iface_reg, iface;
231 int ratio_shift, master;
232 int i;
233
234 iface = 0;
235
236 switch (dai->id) {
237 case WM8776_DAI_DAC:
238 iface_reg = WM8776_DACIFCTRL;
239 master = 0x80;
240 ratio_shift = 4;
241 break;
242 case WM8776_DAI_ADC:
243 iface_reg = WM8776_ADCIFCTRL;
244 master = 0x100;
245 ratio_shift = 0;
246 break;
247 default:
248 return -EINVAL;
249 }
250
251
252 /* Set word length */
253 switch (params_format(params)) {
254 case SNDRV_PCM_FORMAT_S16_LE:
255 break;
256 case SNDRV_PCM_FORMAT_S20_3LE:
257 iface |= 0x10;
258 break;
259 case SNDRV_PCM_FORMAT_S24_LE:
260 iface |= 0x20;
261 break;
262 case SNDRV_PCM_FORMAT_S32_LE:
263 iface |= 0x30;
264 break;
265 }
266
267 /* Only need to set MCLK/LRCLK ratio if we're master */
268 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
269 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
270 if (wm8776->sysclk[dai->id] / params_rate(params)
271 == mclk_ratios[i])
272 break;
273 }
274
275 if (i == ARRAY_SIZE(mclk_ratios)) {
276 dev_err(codec->dev,
277 "Unable to configure MCLK ratio %d/%d\n",
278 wm8776->sysclk[dai->id], params_rate(params));
279 return -EINVAL;
280 }
281
282 dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
283
284 snd_soc_update_bits(codec, WM8776_MSTRCTRL,
285 0x7 << ratio_shift, i << ratio_shift);
286 } else {
287 dev_dbg(codec->dev, "DAI in slave mode\n");
288 }
289
290 snd_soc_update_bits(codec, iface_reg, 0x30, iface);
291
292 return 0;
293}
294
295static int wm8776_mute(struct snd_soc_dai *dai, int mute)
296{
297 struct snd_soc_codec *codec = dai->codec;
298
299 return snd_soc_write(codec, WM8776_DACMUTE, !!mute);
300}
301
302static int wm8776_set_sysclk(struct snd_soc_dai *dai,
303 int clk_id, unsigned int freq, int dir)
304{
305 struct snd_soc_codec *codec = dai->codec;
306 struct wm8776_priv *wm8776 = codec->private_data;
307
308 BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
309
310 wm8776->sysclk[dai->id] = freq;
311
312 return 0;
313}
314
315static int wm8776_set_bias_level(struct snd_soc_codec *codec,
316 enum snd_soc_bias_level level)
317{
318 switch (level) {
319 case SND_SOC_BIAS_ON:
320 break;
321 case SND_SOC_BIAS_PREPARE:
322 break;
323 case SND_SOC_BIAS_STANDBY:
324 if (codec->bias_level == SND_SOC_BIAS_OFF) {
325 /* Disable the global powerdown; DAPM does the rest */
326 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
327 }
328
329 break;
330 case SND_SOC_BIAS_OFF:
331 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1);
332 break;
333 }
334
335 codec->bias_level = level;
336 return 0;
337}
338
339#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
340 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
341 SNDRV_PCM_RATE_96000)
342
343
344#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
345 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
346
347static struct snd_soc_dai_ops wm8776_dac_ops = {
348 .digital_mute = wm8776_mute,
349 .hw_params = wm8776_hw_params,
350 .set_fmt = wm8776_set_fmt,
351 .set_sysclk = wm8776_set_sysclk,
352};
353
354static struct snd_soc_dai_ops wm8776_adc_ops = {
355 .hw_params = wm8776_hw_params,
356 .set_fmt = wm8776_set_fmt,
357 .set_sysclk = wm8776_set_sysclk,
358};
359
360struct snd_soc_dai wm8776_dai[] = {
361 {
362 .name = "WM8776 Playback",
363 .id = WM8776_DAI_DAC,
364 .playback = {
365 .stream_name = "Playback",
366 .channels_min = 2,
367 .channels_max = 2,
368 .rates = WM8776_RATES,
369 .formats = WM8776_FORMATS,
370 },
371 .ops = &wm8776_dac_ops,
372 },
373 {
374 .name = "WM8776 Capture",
375 .id = WM8776_DAI_ADC,
376 .capture = {
377 .stream_name = "Capture",
378 .channels_min = 2,
379 .channels_max = 2,
380 .rates = WM8776_RATES,
381 .formats = WM8776_FORMATS,
382 },
383 .ops = &wm8776_adc_ops,
384 },
385};
386EXPORT_SYMBOL_GPL(wm8776_dai);
387
388#ifdef CONFIG_PM
389static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
390{
391 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
392 struct snd_soc_codec *codec = socdev->card->codec;
393
394 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
395
396 return 0;
397}
398
399static int wm8776_resume(struct platform_device *pdev)
400{
401 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
402 struct snd_soc_codec *codec = socdev->card->codec;
403 int i;
404 u8 data[2];
405 u16 *cache = codec->reg_cache;
406
407 /* Sync reg_cache with the hardware */
408 for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
409 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
410 data[1] = cache[i] & 0x00ff;
411 codec->hw_write(codec->control_data, data, 2);
412 }
413
414 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
415
416 return 0;
417}
418#else
419#define wm8776_suspend NULL
420#define wm8776_resume NULL
421#endif
422
423static int wm8776_probe(struct platform_device *pdev)
424{
425 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
426 struct snd_soc_codec *codec;
427 int ret = 0;
428
429 if (wm8776_codec == NULL) {
430 dev_err(&pdev->dev, "Codec device not registered\n");
431 return -ENODEV;
432 }
433
434 socdev->card->codec = wm8776_codec;
435 codec = wm8776_codec;
436
437 /* register pcms */
438 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
439 if (ret < 0) {
440 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
441 goto pcm_err;
442 }
443
444 snd_soc_add_controls(codec, wm8776_snd_controls,
445 ARRAY_SIZE(wm8776_snd_controls));
446 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
447 ARRAY_SIZE(wm8776_dapm_widgets));
448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
449
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;
457
458card_err:
459 snd_soc_free_pcms(socdev);
460 snd_soc_dapm_free(socdev);
461pcm_err:
462 return ret;
463}
464
465/* power down chip */
466static int wm8776_remove(struct platform_device *pdev)
467{
468 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
469
470 snd_soc_free_pcms(socdev);
471 snd_soc_dapm_free(socdev);
472
473 return 0;
474}
475
476struct snd_soc_codec_device soc_codec_dev_wm8776 = {
477 .probe = wm8776_probe,
478 .remove = wm8776_remove,
479 .suspend = wm8776_suspend,
480 .resume = wm8776_resume,
481};
482EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
483
484static int wm8776_register(struct wm8776_priv *wm8776,
485 enum snd_soc_control_type control)
486{
487 int ret, i;
488 struct snd_soc_codec *codec = &wm8776->codec;
489
490 if (wm8776_codec) {
491 dev_err(codec->dev, "Another WM8776 is registered\n");
492 ret = -EINVAL;
493 goto err;
494 }
495
496 mutex_init(&codec->mutex);
497 INIT_LIST_HEAD(&codec->dapm_widgets);
498 INIT_LIST_HEAD(&codec->dapm_paths);
499
500 codec->private_data = wm8776;
501 codec->name = "WM8776";
502 codec->owner = THIS_MODULE;
503 codec->bias_level = SND_SOC_BIAS_OFF;
504 codec->set_bias_level = wm8776_set_bias_level;
505 codec->dai = wm8776_dai;
506 codec->num_dai = ARRAY_SIZE(wm8776_dai);
507 codec->reg_cache_size = WM8776_CACHEREGNUM;
508 codec->reg_cache = &wm8776->reg_cache;
509
510 memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
511
512 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
513 if (ret < 0) {
514 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
515 goto err;
516 }
517
518 for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
519 wm8776_dai[i].dev = codec->dev;
520
521 ret = wm8776_reset(codec);
522 if (ret < 0) {
523 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
524 goto err;
525 }
526
527 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
528
529 /* Latch the update bits; right channel only since we always
530 * update both. */
531 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
532 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
533
534 wm8776_codec = codec;
535
536 ret = snd_soc_register_codec(codec);
537 if (ret != 0) {
538 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
539 goto err;
540 }
541
542 ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
543 if (ret != 0) {
544 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
545 goto err_codec;
546 }
547
548 return 0;
549
550err_codec:
551 snd_soc_unregister_codec(codec);
552err:
553 kfree(wm8776);
554 return ret;
555}
556
557static void wm8776_unregister(struct wm8776_priv *wm8776)
558{
559 wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
560 snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
561 snd_soc_unregister_codec(&wm8776->codec);
562 kfree(wm8776);
563 wm8776_codec = NULL;
564}
565
566#if defined(CONFIG_SPI_MASTER)
567static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
568{
569 struct spi_transfer t;
570 struct spi_message m;
571 u8 msg[2];
572
573 if (len <= 0)
574 return 0;
575
576 msg[0] = data[0];
577 msg[1] = data[1];
578
579 spi_message_init(&m);
580 memset(&t, 0, (sizeof t));
581
582 t.tx_buf = &msg[0];
583 t.len = len;
584
585 spi_message_add_tail(&t, &m);
586 spi_sync(spi, &m);
587
588 return len;
589}
590
591static int __devinit wm8776_spi_probe(struct spi_device *spi)
592{
593 struct snd_soc_codec *codec;
594 struct wm8776_priv *wm8776;
595
596 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
597 if (wm8776 == NULL)
598 return -ENOMEM;
599
600 codec = &wm8776->codec;
601 codec->control_data = spi;
602 codec->hw_write = (hw_write_t)wm8776_spi_write;
603 codec->dev = &spi->dev;
604
605 dev_set_drvdata(&spi->dev, wm8776);
606
607 return wm8776_register(wm8776, SND_SOC_SPI);
608}
609
610static int __devexit wm8776_spi_remove(struct spi_device *spi)
611{
612 struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
613
614 wm8776_unregister(wm8776);
615
616 return 0;
617}
618
619#ifdef CONFIG_PM
620static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
621{
622 return snd_soc_suspend_device(&spi->dev);
623}
624
625static 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
634static struct spi_driver wm8776_spi_driver = {
635 .driver = {
636 .name = "wm8776",
637 .bus = &spi_bus_type,
638 .owner = THIS_MODULE,
639 },
640 .probe = wm8776_spi_probe,
641 .suspend = wm8776_spi_suspend,
642 .resume = wm8776_spi_resume,
643 .remove = __devexit_p(wm8776_spi_remove),
644};
645#endif /* CONFIG_SPI_MASTER */
646
647#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
648static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
649 const struct i2c_device_id *id)
650{
651 struct wm8776_priv *wm8776;
652 struct snd_soc_codec *codec;
653
654 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
655 if (wm8776 == NULL)
656 return -ENOMEM;
657
658 codec = &wm8776->codec;
659 codec->hw_write = (hw_write_t)i2c_master_send;
660
661 i2c_set_clientdata(i2c, wm8776);
662 codec->control_data = i2c;
663
664 codec->dev = &i2c->dev;
665
666 return wm8776_register(wm8776, SND_SOC_I2C);
667}
668
669static __devexit int wm8776_i2c_remove(struct i2c_client *client)
670{
671 struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
672 wm8776_unregister(wm8776);
673 return 0;
674}
675
676#ifdef CONFIG_PM
677static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
678{
679 return snd_soc_suspend_device(&i2c->dev);
680}
681
682static 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
691static const struct i2c_device_id wm8776_i2c_id[] = {
692 { "wm8776", 0 },
693 { }
694};
695MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
696
697static struct i2c_driver wm8776_i2c_driver = {
698 .driver = {
699 .name = "wm8776",
700 .owner = THIS_MODULE,
701 },
702 .probe = wm8776_i2c_probe,
703 .remove = __devexit_p(wm8776_i2c_remove),
704 .suspend = wm8776_i2c_suspend,
705 .resume = wm8776_i2c_resume,
706 .id_table = wm8776_i2c_id,
707};
708#endif
709
710static int __init wm8776_modinit(void)
711{
712 int ret;
713#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
714 ret = i2c_add_driver(&wm8776_i2c_driver);
715 if (ret != 0) {
716 printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n",
717 ret);
718 }
719#endif
720#if defined(CONFIG_SPI_MASTER)
721 ret = spi_register_driver(&wm8776_spi_driver);
722 if (ret != 0) {
723 printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n",
724 ret);
725 }
726#endif
727 return 0;
728}
729module_init(wm8776_modinit);
730
731static void __exit wm8776_exit(void)
732{
733#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
734 i2c_del_driver(&wm8776_i2c_driver);
735#endif
736#if defined(CONFIG_SPI_MASTER)
737 spi_unregister_driver(&wm8776_spi_driver);
738#endif
739}
740module_exit(wm8776_exit);
741
742MODULE_DESCRIPTION("ASoC WM8776 driver");
743MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
744MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h
new file mode 100644
index 000000000000..6606d25d2d83
--- /dev/null
+++ b/sound/soc/codecs/wm8776.h
@@ -0,0 +1,51 @@
1/*
2 * wm8776.h -- WM8776 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 _WM8776_H
14#define _WM8776_H
15
16/* Registers */
17
18#define WM8776_HPLVOL 0x00
19#define WM8776_HPRVOL 0x01
20#define WM8776_HPMASTER 0x02
21#define WM8776_DACLVOL 0x03
22#define WM8776_DACRVOL 0x04
23#define WM8776_DACMASTER 0x05
24#define WM8776_PHASESWAP 0x06
25#define WM8776_DACCTRL1 0x07
26#define WM8776_DACMUTE 0x08
27#define WM8776_DACCTRL2 0x09
28#define WM8776_DACIFCTRL 0x0a
29#define WM8776_ADCIFCTRL 0x0b
30#define WM8776_MSTRCTRL 0x0c
31#define WM8776_PWRDOWN 0x0d
32#define WM8776_ADCLVOL 0x0e
33#define WM8776_ADCRVOL 0x0f
34#define WM8776_ALCCTRL1 0x10
35#define WM8776_ALCCTRL2 0x11
36#define WM8776_ALCCTRL3 0x12
37#define WM8776_NOISEGATE 0x13
38#define WM8776_LIMITER 0x14
39#define WM8776_ADCMUX 0x15
40#define WM8776_OUTMUX 0x16
41#define WM8776_RESET 0x17
42
43#define WM8776_CACHEREGNUM 0x17
44
45#define WM8776_DAI_DAC 0
46#define WM8776_DAI_ADC 1
47
48extern struct snd_soc_dai wm8776_dai[];
49extern struct snd_soc_codec_device soc_codec_dev_wm8776;
50
51#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 46c5ea1ff921..5e9c855c0036 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -116,6 +116,7 @@
116#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c 116#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
117 117
118#define WM8900_REG_DACCTRL_MUTE 0x004 118#define WM8900_REG_DACCTRL_MUTE 0x004
119#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100
119#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 120#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
120 121
121#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 122#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800
@@ -182,111 +183,20 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
182 /* Remaining registers all zero */ 183 /* Remaining registers all zero */
183}; 184};
184 185
185/* 186static int wm8900_volatile_register(unsigned int reg)
186 * read wm8900 register cache
187 */
188static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec,
189 unsigned int reg)
190{
191 u16 *cache = codec->reg_cache;
192
193 BUG_ON(reg >= WM8900_MAXREG);
194
195 if (reg == WM8900_REG_ID)
196 return 0;
197
198 return cache[reg];
199}
200
201/*
202 * write wm8900 register cache
203 */
204static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec,
205 u16 reg, unsigned int value)
206{
207 u16 *cache = codec->reg_cache;
208
209 BUG_ON(reg >= WM8900_MAXREG);
210
211 cache[reg] = value;
212}
213
214/*
215 * write to the WM8900 register space
216 */
217static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg,
218 unsigned int value)
219{
220 u8 data[3];
221
222 if (value == wm8900_read_reg_cache(codec, reg))
223 return 0;
224
225 /* data is
226 * D15..D9 WM8900 register offset
227 * D8...D0 register data
228 */
229 data[0] = reg;
230 data[1] = value >> 8;
231 data[2] = value & 0x00ff;
232
233 wm8900_write_reg_cache(codec, reg, value);
234 if (codec->hw_write(codec->control_data, data, 3) == 3)
235 return 0;
236 else
237 return -EIO;
238}
239
240/*
241 * Read from the wm8900.
242 */
243static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg)
244{
245 struct i2c_msg xfer[2];
246 u16 data;
247 int ret;
248 struct i2c_client *client = codec->control_data;
249
250 BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1);
251
252 /* Write register */
253 xfer[0].addr = client->addr;
254 xfer[0].flags = 0;
255 xfer[0].len = 1;
256 xfer[0].buf = &reg;
257
258 /* Read data */
259 xfer[1].addr = client->addr;
260 xfer[1].flags = I2C_M_RD;
261 xfer[1].len = 2;
262 xfer[1].buf = (u8 *)&data;
263
264 ret = i2c_transfer(client->adapter, xfer, 2);
265 if (ret != 2) {
266 printk(KERN_CRIT "i2c_transfer returned %d\n", ret);
267 return 0;
268 }
269
270 return (data >> 8) | ((data & 0xff) << 8);
271}
272
273/*
274 * Read from the WM8900 register space. Most registers can't be read
275 * and are therefore supplied from cache.
276 */
277static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg)
278{ 187{
279 switch (reg) { 188 switch (reg) {
280 case WM8900_REG_ID: 189 case WM8900_REG_ID:
281 return wm8900_chip_read(codec, reg); 190 case WM8900_REG_POWER1:
191 return 1;
282 default: 192 default:
283 return wm8900_read_reg_cache(codec, reg); 193 return 0;
284 } 194 }
285} 195}
286 196
287static void wm8900_reset(struct snd_soc_codec *codec) 197static void wm8900_reset(struct snd_soc_codec *codec)
288{ 198{
289 wm8900_write(codec, WM8900_REG_RESET, 0); 199 snd_soc_write(codec, WM8900_REG_RESET, 0);
290 200
291 memcpy(codec->reg_cache, wm8900_reg_defaults, 201 memcpy(codec->reg_cache, wm8900_reg_defaults,
292 sizeof(codec->reg_cache)); 202 sizeof(codec->reg_cache));
@@ -296,14 +206,14 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
296 struct snd_kcontrol *kcontrol, int event) 206 struct snd_kcontrol *kcontrol, int event)
297{ 207{
298 struct snd_soc_codec *codec = w->codec; 208 struct snd_soc_codec *codec = w->codec;
299 u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1); 209 u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
300 210
301 switch (event) { 211 switch (event) {
302 case SND_SOC_DAPM_PRE_PMU: 212 case SND_SOC_DAPM_PRE_PMU:
303 /* Clamp headphone outputs */ 213 /* Clamp headphone outputs */
304 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP | 214 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
305 WM8900_REG_HPCTL1_HP_CLAMP_OP; 215 WM8900_REG_HPCTL1_HP_CLAMP_OP;
306 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 216 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
307 break; 217 break;
308 218
309 case SND_SOC_DAPM_POST_PMU: 219 case SND_SOC_DAPM_POST_PMU:
@@ -312,41 +222,41 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
312 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT | 222 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
313 WM8900_REG_HPCTL1_HP_SHORT2 | 223 WM8900_REG_HPCTL1_HP_SHORT2 |
314 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; 224 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
315 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 225 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
316 226
317 msleep(400); 227 msleep(400);
318 228
319 /* Enable the output stage */ 229 /* Enable the output stage */
320 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP; 230 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
321 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; 231 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
322 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 232 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
323 233
324 /* Remove the shorts */ 234 /* Remove the shorts */
325 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2; 235 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
326 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 236 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
327 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT; 237 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
328 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 238 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
329 break; 239 break;
330 240
331 case SND_SOC_DAPM_PRE_PMD: 241 case SND_SOC_DAPM_PRE_PMD:
332 /* Short the output */ 242 /* Short the output */
333 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT; 243 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
334 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 244 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
335 245
336 /* Disable the output stage */ 246 /* Disable the output stage */
337 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; 247 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
338 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 248 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
339 249
340 /* Clamp the outputs and power down input */ 250 /* Clamp the outputs and power down input */
341 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP | 251 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
342 WM8900_REG_HPCTL1_HP_CLAMP_OP; 252 WM8900_REG_HPCTL1_HP_CLAMP_OP;
343 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; 253 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
344 wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); 254 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
345 break; 255 break;
346 256
347 case SND_SOC_DAPM_POST_PMD: 257 case SND_SOC_DAPM_POST_PMD:
348 /* Disable everything */ 258 /* Disable everything */
349 wm8900_write(codec, WM8900_REG_HPCTL1, 0); 259 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
350 break; 260 break;
351 261
352 default: 262 default:
@@ -439,7 +349,6 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
439SOC_ENUM("DAC Mute Rate", dac_mute_rate), 349SOC_ENUM("DAC Mute Rate", dac_mute_rate),
440SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), 350SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
441SOC_ENUM("DAC Deemphasis", dac_deemphasis), 351SOC_ENUM("DAC Deemphasis", dac_deemphasis),
442SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0),
443SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, 352SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
444 12, 1, 0), 353 12, 1, 0),
445 354
@@ -723,7 +632,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
723 struct snd_soc_codec *codec = socdev->card->codec; 632 struct snd_soc_codec *codec = socdev->card->codec;
724 u16 reg; 633 u16 reg;
725 634
726 reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; 635 reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
727 636
728 switch (params_format(params)) { 637 switch (params_format(params)) {
729 case SNDRV_PCM_FORMAT_S16_LE: 638 case SNDRV_PCM_FORMAT_S16_LE:
@@ -741,7 +650,18 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
741 return -EINVAL; 650 return -EINVAL;
742 } 651 }
743 652
744 wm8900_write(codec, WM8900_REG_AUDIO1, reg); 653 snd_soc_write(codec, WM8900_REG_AUDIO1, reg);
654
655 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
656 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
657
658 if (params_rate(params) <= 24000)
659 reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
660 else
661 reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
662
663 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
664 }
745 665
746 return 0; 666 return 0;
747} 667}
@@ -778,11 +698,11 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
778 } 698 }
779 699
780 if (target > 100000000) 700 if (target > 100000000)
781 printk(KERN_WARNING "wm8900: FLL rate %d out of range, Fref=%d" 701 printk(KERN_WARNING "wm8900: FLL rate %u out of range, Fref=%u"
782 " Fout=%d\n", target, Fref, Fout); 702 " Fout=%u\n", target, Fref, Fout);
783 if (div > 32) { 703 if (div > 32) {
784 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, " 704 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, "
785 "Fref=%d, Fout=%d, target=%d\n", 705 "Fref=%u, Fout=%u, target=%u\n",
786 div, Fref, Fout, target); 706 div, Fref, Fout, target);
787 return -EINVAL; 707 return -EINVAL;
788 } 708 }
@@ -834,18 +754,18 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
834 return 0; 754 return 0;
835 755
836 /* The digital side should be disabled during any change. */ 756 /* The digital side should be disabled during any change. */
837 reg = wm8900_read(codec, WM8900_REG_POWER1); 757 reg = snd_soc_read(codec, WM8900_REG_POWER1);
838 wm8900_write(codec, WM8900_REG_POWER1, 758 snd_soc_write(codec, WM8900_REG_POWER1,
839 reg & (~WM8900_REG_POWER1_FLL_ENA)); 759 reg & (~WM8900_REG_POWER1_FLL_ENA));
840 760
841 /* Disable the FLL? */ 761 /* Disable the FLL? */
842 if (!freq_in || !freq_out) { 762 if (!freq_in || !freq_out) {
843 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 763 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
844 wm8900_write(codec, WM8900_REG_CLOCKING1, 764 snd_soc_write(codec, WM8900_REG_CLOCKING1,
845 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC)); 765 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
846 766
847 reg = wm8900_read(codec, WM8900_REG_FLLCTL1); 767 reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
848 wm8900_write(codec, WM8900_REG_FLLCTL1, 768 snd_soc_write(codec, WM8900_REG_FLLCTL1,
849 reg & (~WM8900_REG_FLLCTL1_OSC_ENA)); 769 reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
850 770
851 wm8900->fll_in = freq_in; 771 wm8900->fll_in = freq_in;
@@ -862,33 +782,33 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
862 782
863 /* The osclilator *MUST* be enabled before we enable the 783 /* The osclilator *MUST* be enabled before we enable the
864 * digital circuit. */ 784 * digital circuit. */
865 wm8900_write(codec, WM8900_REG_FLLCTL1, 785 snd_soc_write(codec, WM8900_REG_FLLCTL1,
866 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA); 786 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA);
867 787
868 wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); 788 snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
869 wm8900_write(codec, WM8900_REG_FLLCTL5, 789 snd_soc_write(codec, WM8900_REG_FLLCTL5,
870 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f)); 790 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f));
871 791
872 if (fll_div.k) { 792 if (fll_div.k) {
873 wm8900_write(codec, WM8900_REG_FLLCTL2, 793 snd_soc_write(codec, WM8900_REG_FLLCTL2,
874 (fll_div.k >> 8) | 0x100); 794 (fll_div.k >> 8) | 0x100);
875 wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); 795 snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
876 } else 796 } else
877 wm8900_write(codec, WM8900_REG_FLLCTL2, 0); 797 snd_soc_write(codec, WM8900_REG_FLLCTL2, 0);
878 798
879 if (fll_div.fll_slow_lock_ref) 799 if (fll_div.fll_slow_lock_ref)
880 wm8900_write(codec, WM8900_REG_FLLCTL6, 800 snd_soc_write(codec, WM8900_REG_FLLCTL6,
881 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF); 801 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF);
882 else 802 else
883 wm8900_write(codec, WM8900_REG_FLLCTL6, 0); 803 snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
884 804
885 reg = wm8900_read(codec, WM8900_REG_POWER1); 805 reg = snd_soc_read(codec, WM8900_REG_POWER1);
886 wm8900_write(codec, WM8900_REG_POWER1, 806 snd_soc_write(codec, WM8900_REG_POWER1,
887 reg | WM8900_REG_POWER1_FLL_ENA); 807 reg | WM8900_REG_POWER1_FLL_ENA);
888 808
889reenable: 809reenable:
890 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 810 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
891 wm8900_write(codec, WM8900_REG_CLOCKING1, 811 snd_soc_write(codec, WM8900_REG_CLOCKING1,
892 reg | WM8900_REG_CLOCKING1_MCLK_SRC); 812 reg | WM8900_REG_CLOCKING1_MCLK_SRC);
893 813
894 return 0; 814 return 0;
@@ -908,38 +828,38 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
908 828
909 switch (div_id) { 829 switch (div_id) {
910 case WM8900_BCLK_DIV: 830 case WM8900_BCLK_DIV:
911 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 831 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
912 wm8900_write(codec, WM8900_REG_CLOCKING1, 832 snd_soc_write(codec, WM8900_REG_CLOCKING1,
913 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK)); 833 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
914 break; 834 break;
915 case WM8900_OPCLK_DIV: 835 case WM8900_OPCLK_DIV:
916 reg = wm8900_read(codec, WM8900_REG_CLOCKING1); 836 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
917 wm8900_write(codec, WM8900_REG_CLOCKING1, 837 snd_soc_write(codec, WM8900_REG_CLOCKING1,
918 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK)); 838 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
919 break; 839 break;
920 case WM8900_DAC_LRCLK: 840 case WM8900_DAC_LRCLK:
921 reg = wm8900_read(codec, WM8900_REG_AUDIO4); 841 reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
922 wm8900_write(codec, WM8900_REG_AUDIO4, 842 snd_soc_write(codec, WM8900_REG_AUDIO4,
923 div | (reg & WM8900_LRC_MASK)); 843 div | (reg & WM8900_LRC_MASK));
924 break; 844 break;
925 case WM8900_ADC_LRCLK: 845 case WM8900_ADC_LRCLK:
926 reg = wm8900_read(codec, WM8900_REG_AUDIO3); 846 reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
927 wm8900_write(codec, WM8900_REG_AUDIO3, 847 snd_soc_write(codec, WM8900_REG_AUDIO3,
928 div | (reg & WM8900_LRC_MASK)); 848 div | (reg & WM8900_LRC_MASK));
929 break; 849 break;
930 case WM8900_DAC_CLKDIV: 850 case WM8900_DAC_CLKDIV:
931 reg = wm8900_read(codec, WM8900_REG_CLOCKING2); 851 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
932 wm8900_write(codec, WM8900_REG_CLOCKING2, 852 snd_soc_write(codec, WM8900_REG_CLOCKING2,
933 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV)); 853 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
934 break; 854 break;
935 case WM8900_ADC_CLKDIV: 855 case WM8900_ADC_CLKDIV:
936 reg = wm8900_read(codec, WM8900_REG_CLOCKING2); 856 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
937 wm8900_write(codec, WM8900_REG_CLOCKING2, 857 snd_soc_write(codec, WM8900_REG_CLOCKING2,
938 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV)); 858 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
939 break; 859 break;
940 case WM8900_LRCLK_MODE: 860 case WM8900_LRCLK_MODE:
941 reg = wm8900_read(codec, WM8900_REG_DACCTRL); 861 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
942 wm8900_write(codec, WM8900_REG_DACCTRL, 862 snd_soc_write(codec, WM8900_REG_DACCTRL,
943 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE)); 863 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
944 break; 864 break;
945 default: 865 default:
@@ -956,10 +876,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
956 struct snd_soc_codec *codec = codec_dai->codec; 876 struct snd_soc_codec *codec = codec_dai->codec;
957 unsigned int clocking1, aif1, aif3, aif4; 877 unsigned int clocking1, aif1, aif3, aif4;
958 878
959 clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1); 879 clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1);
960 aif1 = wm8900_read(codec, WM8900_REG_AUDIO1); 880 aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1);
961 aif3 = wm8900_read(codec, WM8900_REG_AUDIO3); 881 aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3);
962 aif4 = wm8900_read(codec, WM8900_REG_AUDIO4); 882 aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4);
963 883
964 /* set master/slave audio interface */ 884 /* set master/slave audio interface */
965 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 885 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1055,10 +975,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
1055 return -EINVAL; 975 return -EINVAL;
1056 } 976 }
1057 977
1058 wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1); 978 snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1);
1059 wm8900_write(codec, WM8900_REG_AUDIO1, aif1); 979 snd_soc_write(codec, WM8900_REG_AUDIO1, aif1);
1060 wm8900_write(codec, WM8900_REG_AUDIO3, aif3); 980 snd_soc_write(codec, WM8900_REG_AUDIO3, aif3);
1061 wm8900_write(codec, WM8900_REG_AUDIO4, aif4); 981 snd_soc_write(codec, WM8900_REG_AUDIO4, aif4);
1062 982
1063 return 0; 983 return 0;
1064} 984}
@@ -1068,14 +988,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1068 struct snd_soc_codec *codec = codec_dai->codec; 988 struct snd_soc_codec *codec = codec_dai->codec;
1069 u16 reg; 989 u16 reg;
1070 990
1071 reg = wm8900_read(codec, WM8900_REG_DACCTRL); 991 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
1072 992
1073 if (mute) 993 if (mute)
1074 reg |= WM8900_REG_DACCTRL_MUTE; 994 reg |= WM8900_REG_DACCTRL_MUTE;
1075 else 995 else
1076 reg &= ~WM8900_REG_DACCTRL_MUTE; 996 reg &= ~WM8900_REG_DACCTRL_MUTE;
1077 997
1078 wm8900_write(codec, WM8900_REG_DACCTRL, reg); 998 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
1079 999
1080 return 0; 1000 return 0;
1081} 1001}
@@ -1124,11 +1044,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1124 switch (level) { 1044 switch (level) {
1125 case SND_SOC_BIAS_ON: 1045 case SND_SOC_BIAS_ON:
1126 /* Enable thermal shutdown */ 1046 /* Enable thermal shutdown */
1127 reg = wm8900_read(codec, WM8900_REG_GPIO); 1047 reg = snd_soc_read(codec, WM8900_REG_GPIO);
1128 wm8900_write(codec, WM8900_REG_GPIO, 1048 snd_soc_write(codec, WM8900_REG_GPIO,
1129 reg | WM8900_REG_GPIO_TEMP_ENA); 1049 reg | WM8900_REG_GPIO_TEMP_ENA);
1130 reg = wm8900_read(codec, WM8900_REG_ADDCTL); 1050 reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
1131 wm8900_write(codec, WM8900_REG_ADDCTL, 1051 snd_soc_write(codec, WM8900_REG_ADDCTL,
1132 reg | WM8900_REG_ADDCTL_TEMP_SD); 1052 reg | WM8900_REG_ADDCTL_TEMP_SD);
1133 break; 1053 break;
1134 1054
@@ -1139,69 +1059,69 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1139 /* Charge capacitors if initial power up */ 1059 /* Charge capacitors if initial power up */
1140 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1060 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1141 /* STARTUP_BIAS_ENA on */ 1061 /* STARTUP_BIAS_ENA on */
1142 wm8900_write(codec, WM8900_REG_POWER1, 1062 snd_soc_write(codec, WM8900_REG_POWER1,
1143 WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1063 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1144 1064
1145 /* Startup bias mode */ 1065 /* Startup bias mode */
1146 wm8900_write(codec, WM8900_REG_ADDCTL, 1066 snd_soc_write(codec, WM8900_REG_ADDCTL,
1147 WM8900_REG_ADDCTL_BIAS_SRC | 1067 WM8900_REG_ADDCTL_BIAS_SRC |
1148 WM8900_REG_ADDCTL_VMID_SOFTST); 1068 WM8900_REG_ADDCTL_VMID_SOFTST);
1149 1069
1150 /* VMID 2x50k */ 1070 /* VMID 2x50k */
1151 wm8900_write(codec, WM8900_REG_POWER1, 1071 snd_soc_write(codec, WM8900_REG_POWER1,
1152 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1); 1072 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1);
1153 1073
1154 /* Allow capacitors to charge */ 1074 /* Allow capacitors to charge */
1155 schedule_timeout_interruptible(msecs_to_jiffies(400)); 1075 schedule_timeout_interruptible(msecs_to_jiffies(400));
1156 1076
1157 /* Enable bias */ 1077 /* Enable bias */
1158 wm8900_write(codec, WM8900_REG_POWER1, 1078 snd_soc_write(codec, WM8900_REG_POWER1,
1159 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 1079 WM8900_REG_POWER1_STARTUP_BIAS_ENA |
1160 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1080 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1161 1081
1162 wm8900_write(codec, WM8900_REG_ADDCTL, 0); 1082 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
1163 1083
1164 wm8900_write(codec, WM8900_REG_POWER1, 1084 snd_soc_write(codec, WM8900_REG_POWER1,
1165 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1085 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1166 } 1086 }
1167 1087
1168 reg = wm8900_read(codec, WM8900_REG_POWER1); 1088 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1169 wm8900_write(codec, WM8900_REG_POWER1, 1089 snd_soc_write(codec, WM8900_REG_POWER1,
1170 (reg & WM8900_REG_POWER1_FLL_ENA) | 1090 (reg & WM8900_REG_POWER1_FLL_ENA) |
1171 WM8900_REG_POWER1_BIAS_ENA | 0x1); 1091 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1172 wm8900_write(codec, WM8900_REG_POWER2, 1092 snd_soc_write(codec, WM8900_REG_POWER2,
1173 WM8900_REG_POWER2_SYSCLK_ENA); 1093 WM8900_REG_POWER2_SYSCLK_ENA);
1174 wm8900_write(codec, WM8900_REG_POWER3, 0); 1094 snd_soc_write(codec, WM8900_REG_POWER3, 0);
1175 break; 1095 break;
1176 1096
1177 case SND_SOC_BIAS_OFF: 1097 case SND_SOC_BIAS_OFF:
1178 /* Startup bias enable */ 1098 /* Startup bias enable */
1179 reg = wm8900_read(codec, WM8900_REG_POWER1); 1099 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1180 wm8900_write(codec, WM8900_REG_POWER1, 1100 snd_soc_write(codec, WM8900_REG_POWER1,
1181 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1101 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1182 wm8900_write(codec, WM8900_REG_ADDCTL, 1102 snd_soc_write(codec, WM8900_REG_ADDCTL,
1183 WM8900_REG_ADDCTL_BIAS_SRC | 1103 WM8900_REG_ADDCTL_BIAS_SRC |
1184 WM8900_REG_ADDCTL_VMID_SOFTST); 1104 WM8900_REG_ADDCTL_VMID_SOFTST);
1185 1105
1186 /* Discharge caps */ 1106 /* Discharge caps */
1187 wm8900_write(codec, WM8900_REG_POWER1, 1107 snd_soc_write(codec, WM8900_REG_POWER1,
1188 WM8900_REG_POWER1_STARTUP_BIAS_ENA); 1108 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1189 schedule_timeout_interruptible(msecs_to_jiffies(500)); 1109 schedule_timeout_interruptible(msecs_to_jiffies(500));
1190 1110
1191 /* Remove clamp */ 1111 /* Remove clamp */
1192 wm8900_write(codec, WM8900_REG_HPCTL1, 0); 1112 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
1193 1113
1194 /* Power down */ 1114 /* Power down */
1195 wm8900_write(codec, WM8900_REG_ADDCTL, 0); 1115 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
1196 wm8900_write(codec, WM8900_REG_POWER1, 0); 1116 snd_soc_write(codec, WM8900_REG_POWER1, 0);
1197 wm8900_write(codec, WM8900_REG_POWER2, 0); 1117 snd_soc_write(codec, WM8900_REG_POWER2, 0);
1198 wm8900_write(codec, WM8900_REG_POWER3, 0); 1118 snd_soc_write(codec, WM8900_REG_POWER3, 0);
1199 1119
1200 /* Need to let things settle before stopping the clock 1120 /* Need to let things settle before stopping the clock
1201 * to ensure that restart works, see "Stopping the 1121 * to ensure that restart works, see "Stopping the
1202 * master clock" in the datasheet. */ 1122 * master clock" in the datasheet. */
1203 schedule_timeout_interruptible(msecs_to_jiffies(1)); 1123 schedule_timeout_interruptible(msecs_to_jiffies(1));
1204 wm8900_write(codec, WM8900_REG_POWER2, 1124 snd_soc_write(codec, WM8900_REG_POWER2,
1205 WM8900_REG_POWER2_SYSCLK_ENA); 1125 WM8900_REG_POWER2_SYSCLK_ENA);
1206 break; 1126 break;
1207 } 1127 }
@@ -1264,7 +1184,7 @@ static int wm8900_resume(struct platform_device *pdev)
1264 1184
1265 if (cache) { 1185 if (cache) {
1266 for (i = 0; i < WM8900_MAXREG; i++) 1186 for (i = 0; i < WM8900_MAXREG; i++)
1267 wm8900_write(codec, i, cache[i]); 1187 snd_soc_write(codec, i, cache[i]);
1268 kfree(cache); 1188 kfree(cache);
1269 } else 1189 } else
1270 dev_err(&pdev->dev, "Unable to allocate register cache\n"); 1190 dev_err(&pdev->dev, "Unable to allocate register cache\n");
@@ -1297,16 +1217,20 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1297 1217
1298 codec->name = "WM8900"; 1218 codec->name = "WM8900";
1299 codec->owner = THIS_MODULE; 1219 codec->owner = THIS_MODULE;
1300 codec->read = wm8900_read;
1301 codec->write = wm8900_write;
1302 codec->dai = &wm8900_dai; 1220 codec->dai = &wm8900_dai;
1303 codec->num_dai = 1; 1221 codec->num_dai = 1;
1304 codec->hw_write = (hw_write_t)i2c_master_send;
1305 codec->control_data = i2c; 1222 codec->control_data = i2c;
1306 codec->set_bias_level = wm8900_set_bias_level; 1223 codec->set_bias_level = wm8900_set_bias_level;
1224 codec->volatile_register = wm8900_volatile_register;
1307 codec->dev = &i2c->dev; 1225 codec->dev = &i2c->dev;
1308 1226
1309 reg = wm8900_read(codec, WM8900_REG_ID); 1227 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1228 if (ret != 0) {
1229 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
1230 goto err;
1231 }
1232
1233 reg = snd_soc_read(codec, WM8900_REG_ID);
1310 if (reg != 0x8900) { 1234 if (reg != 0x8900) {
1311 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); 1235 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
1312 ret = -ENODEV; 1236 ret = -ENODEV;
@@ -1314,7 +1238,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1314 } 1238 }
1315 1239
1316 /* Read back from the chip */ 1240 /* Read back from the chip */
1317 reg = wm8900_chip_read(codec, WM8900_REG_POWER1); 1241 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1318 reg = (reg >> 12) & 0xf; 1242 reg = (reg >> 12) & 0xf;
1319 dev_info(&i2c->dev, "WM8900 revision %d\n", reg); 1243 dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
1320 1244
@@ -1324,29 +1248,29 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1324 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1248 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1325 1249
1326 /* Latch the volume update bits */ 1250 /* Latch the volume update bits */
1327 wm8900_write(codec, WM8900_REG_LINVOL, 1251 snd_soc_write(codec, WM8900_REG_LINVOL,
1328 wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); 1252 snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
1329 wm8900_write(codec, WM8900_REG_RINVOL, 1253 snd_soc_write(codec, WM8900_REG_RINVOL,
1330 wm8900_read(codec, WM8900_REG_RINVOL) | 0x100); 1254 snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
1331 wm8900_write(codec, WM8900_REG_LOUT1CTL, 1255 snd_soc_write(codec, WM8900_REG_LOUT1CTL,
1332 wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100); 1256 snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
1333 wm8900_write(codec, WM8900_REG_ROUT1CTL, 1257 snd_soc_write(codec, WM8900_REG_ROUT1CTL,
1334 wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100); 1258 snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
1335 wm8900_write(codec, WM8900_REG_LOUT2CTL, 1259 snd_soc_write(codec, WM8900_REG_LOUT2CTL,
1336 wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100); 1260 snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
1337 wm8900_write(codec, WM8900_REG_ROUT2CTL, 1261 snd_soc_write(codec, WM8900_REG_ROUT2CTL,
1338 wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100); 1262 snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
1339 wm8900_write(codec, WM8900_REG_LDAC_DV, 1263 snd_soc_write(codec, WM8900_REG_LDAC_DV,
1340 wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100); 1264 snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
1341 wm8900_write(codec, WM8900_REG_RDAC_DV, 1265 snd_soc_write(codec, WM8900_REG_RDAC_DV,
1342 wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100); 1266 snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
1343 wm8900_write(codec, WM8900_REG_LADC_DV, 1267 snd_soc_write(codec, WM8900_REG_LADC_DV,
1344 wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100); 1268 snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
1345 wm8900_write(codec, WM8900_REG_RADC_DV, 1269 snd_soc_write(codec, WM8900_REG_RADC_DV,
1346 wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100); 1270 snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
1347 1271
1348 /* Set the DAC and mixer output bias */ 1272 /* Set the DAC and mixer output bias */
1349 wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); 1273 snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
1350 1274
1351 wm8900_dai.dev = &i2c->dev; 1275 wm8900_dai.dev = &i2c->dev;
1352 1276
@@ -1388,6 +1312,21 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1388 return 0; 1312 return 0;
1389} 1313}
1390 1314
1315#ifdef CONFIG_PM
1316static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1317{
1318 return snd_soc_suspend_device(&client->dev);
1319}
1320
1321static 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
1391static const struct i2c_device_id wm8900_i2c_id[] = { 1330static const struct i2c_device_id wm8900_i2c_id[] = {
1392 { "wm8900", 0 }, 1331 { "wm8900", 0 },
1393 { } 1332 { }
@@ -1401,6 +1340,8 @@ static struct i2c_driver wm8900_i2c_driver = {
1401 }, 1340 },
1402 .probe = wm8900_i2c_probe, 1341 .probe = wm8900_i2c_probe,
1403 .remove = __devexit_p(wm8900_i2c_remove), 1342 .remove = __devexit_p(wm8900_i2c_remove),
1343 .suspend = wm8900_i2c_suspend,
1344 .resume = wm8900_i2c_resume,
1404 .id_table = wm8900_i2c_id, 1345 .id_table = wm8900_i2c_id,
1405}; 1346};
1406 1347
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 8cf571f1a803..fe1307b500cf 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -217,7 +217,6 @@ struct wm8903_priv {
217 int sysclk; 217 int sysclk;
218 218
219 /* Reference counts */ 219 /* Reference counts */
220 int charge_pump_users;
221 int class_w_users; 220 int class_w_users;
222 int playback_active; 221 int playback_active;
223 int capture_active; 222 int capture_active;
@@ -226,94 +225,18 @@ struct wm8903_priv {
226 struct snd_pcm_substream *slave_substream; 225 struct snd_pcm_substream *slave_substream;
227}; 226};
228 227
229 228static int wm8903_volatile_register(unsigned int reg)
230static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
231 unsigned int reg)
232{
233 u16 *cache = codec->reg_cache;
234
235 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
236
237 return cache[reg];
238}
239
240static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg)
241{
242 struct i2c_msg xfer[2];
243 u16 data;
244 int ret;
245 struct i2c_client *client = codec->control_data;
246
247 /* Write register */
248 xfer[0].addr = client->addr;
249 xfer[0].flags = 0;
250 xfer[0].len = 1;
251 xfer[0].buf = &reg;
252
253 /* Read data */
254 xfer[1].addr = client->addr;
255 xfer[1].flags = I2C_M_RD;
256 xfer[1].len = 2;
257 xfer[1].buf = (u8 *)&data;
258
259 ret = i2c_transfer(client->adapter, xfer, 2);
260 if (ret != 2) {
261 pr_err("i2c_transfer returned %d\n", ret);
262 return 0;
263 }
264
265 return (data >> 8) | ((data & 0xff) << 8);
266}
267
268static unsigned int wm8903_read(struct snd_soc_codec *codec,
269 unsigned int reg)
270{ 229{
271 switch (reg) { 230 switch (reg) {
272 case WM8903_SW_RESET_AND_ID: 231 case WM8903_SW_RESET_AND_ID:
273 case WM8903_REVISION_NUMBER: 232 case WM8903_REVISION_NUMBER:
274 case WM8903_INTERRUPT_STATUS_1: 233 case WM8903_INTERRUPT_STATUS_1:
275 case WM8903_WRITE_SEQUENCER_4: 234 case WM8903_WRITE_SEQUENCER_4:
276 return wm8903_hw_read(codec, reg); 235 return 1;
277
278 default:
279 return wm8903_read_reg_cache(codec, reg);
280 }
281}
282
283static void wm8903_write_reg_cache(struct snd_soc_codec *codec,
284 u16 reg, unsigned int value)
285{
286 u16 *cache = codec->reg_cache;
287
288 BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
289
290 switch (reg) {
291 case WM8903_SW_RESET_AND_ID:
292 case WM8903_REVISION_NUMBER:
293 break;
294 236
295 default: 237 default:
296 cache[reg] = value;
297 break;
298 }
299}
300
301static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg,
302 unsigned int value)
303{
304 u8 data[3];
305
306 wm8903_write_reg_cache(codec, reg, value);
307
308 /* Data format is 1 byte of address followed by 2 bytes of data */
309 data[0] = reg;
310 data[1] = (value >> 8) & 0xff;
311 data[2] = value & 0xff;
312
313 if (codec->hw_write(codec->control_data, data, 3) == 2)
314 return 0; 238 return 0;
315 else 239 }
316 return -EIO;
317} 240}
318 241
319static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) 242static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
@@ -324,13 +247,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
324 BUG_ON(start > 48); 247 BUG_ON(start > 48);
325 248
326 /* Enable the sequencer */ 249 /* Enable the sequencer */
327 reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0); 250 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
328 reg[0] |= WM8903_WSEQ_ENA; 251 reg[0] |= WM8903_WSEQ_ENA;
329 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); 252 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
330 253
331 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); 254 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
332 255
333 wm8903_write(codec, WM8903_WRITE_SEQUENCER_3, 256 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
334 start | WM8903_WSEQ_START); 257 start | WM8903_WSEQ_START);
335 258
336 /* Wait for it to complete. If we have the interrupt wired up then 259 /* Wait for it to complete. If we have the interrupt wired up then
@@ -340,13 +263,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
340 do { 263 do {
341 msleep(10); 264 msleep(10);
342 265
343 reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4); 266 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
344 } while (reg[4] & WM8903_WSEQ_BUSY); 267 } while (reg[4] & WM8903_WSEQ_BUSY);
345 268
346 dev_dbg(&i2c->dev, "Sequence complete\n"); 269 dev_dbg(&i2c->dev, "Sequence complete\n");
347 270
348 /* Disable the sequencer again */ 271 /* Disable the sequencer again */
349 wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 272 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
350 reg[0] & ~WM8903_WSEQ_ENA); 273 reg[0] & ~WM8903_WSEQ_ENA);
351 274
352 return 0; 275 return 0;
@@ -358,12 +281,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
358 281
359 /* There really ought to be something better we can do here :/ */ 282 /* There really ought to be something better we can do here :/ */
360 for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) 283 for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
361 cache[i] = wm8903_hw_read(codec, i); 284 cache[i] = codec->hw_read(codec, i);
362} 285}
363 286
364static void wm8903_reset(struct snd_soc_codec *codec) 287static void wm8903_reset(struct snd_soc_codec *codec)
365{ 288{
366 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); 289 snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
367 memcpy(codec->reg_cache, wm8903_reg_defaults, 290 memcpy(codec->reg_cache, wm8903_reg_defaults,
368 sizeof(wm8903_reg_defaults)); 291 sizeof(wm8903_reg_defaults));
369} 292}
@@ -373,6 +296,15 @@ static void wm8903_reset(struct snd_soc_codec *codec)
373#define WM8903_OUTPUT_INT 0x2 296#define WM8903_OUTPUT_INT 0x2
374#define WM8903_OUTPUT_IN 0x1 297#define WM8903_OUTPUT_IN 0x1
375 298
299static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event)
301{
302 WARN_ON(event != SND_SOC_DAPM_POST_PMU);
303 mdelay(4);
304
305 return 0;
306}
307
376/* 308/*
377 * Event for headphone and line out amplifier power changes. Special 309 * Event for headphone and line out amplifier power changes. Special
378 * power up/down sequences are required in order to maximise pop/click 310 * power up/down sequences are required in order to maximise pop/click
@@ -382,19 +314,20 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
382 struct snd_kcontrol *kcontrol, int event) 314 struct snd_kcontrol *kcontrol, int event)
383{ 315{
384 struct snd_soc_codec *codec = w->codec; 316 struct snd_soc_codec *codec = w->codec;
385 struct wm8903_priv *wm8903 = codec->private_data;
386 struct i2c_client *i2c = codec->control_data;
387 u16 val; 317 u16 val;
388 u16 reg; 318 u16 reg;
319 u16 dcs_reg;
320 u16 dcs_bit;
389 int shift; 321 int shift;
390 u16 cp_reg = wm8903_read(codec, WM8903_CHARGE_PUMP_0);
391 322
392 switch (w->reg) { 323 switch (w->reg) {
393 case WM8903_POWER_MANAGEMENT_2: 324 case WM8903_POWER_MANAGEMENT_2:
394 reg = WM8903_ANALOGUE_HP_0; 325 reg = WM8903_ANALOGUE_HP_0;
326 dcs_bit = 0 + w->shift;
395 break; 327 break;
396 case WM8903_POWER_MANAGEMENT_3: 328 case WM8903_POWER_MANAGEMENT_3:
397 reg = WM8903_ANALOGUE_LINEOUT_0; 329 reg = WM8903_ANALOGUE_LINEOUT_0;
330 dcs_bit = 2 + w->shift;
398 break; 331 break;
399 default: 332 default:
400 BUG(); 333 BUG();
@@ -414,67 +347,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
414 } 347 }
415 348
416 if (event & SND_SOC_DAPM_PRE_PMU) { 349 if (event & SND_SOC_DAPM_PRE_PMU) {
417 val = wm8903_read(codec, reg); 350 val = snd_soc_read(codec, reg);
418 351
419 /* Short the output */ 352 /* Short the output */
420 val &= ~(WM8903_OUTPUT_SHORT << shift); 353 val &= ~(WM8903_OUTPUT_SHORT << shift);
421 wm8903_write(codec, reg, val); 354 snd_soc_write(codec, reg, val);
422
423 wm8903->charge_pump_users++;
424
425 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
426 wm8903->charge_pump_users);
427
428 if (wm8903->charge_pump_users == 1) {
429 dev_dbg(&i2c->dev, "Enabling charge pump\n");
430 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
431 cp_reg | WM8903_CP_ENA);
432 mdelay(4);
433 }
434 } 355 }
435 356
436 if (event & SND_SOC_DAPM_POST_PMU) { 357 if (event & SND_SOC_DAPM_POST_PMU) {
437 val = wm8903_read(codec, reg); 358 val = snd_soc_read(codec, reg);
438 359
439 val |= (WM8903_OUTPUT_IN << shift); 360 val |= (WM8903_OUTPUT_IN << shift);
440 wm8903_write(codec, reg, val); 361 snd_soc_write(codec, reg, val);
441 362
442 val |= (WM8903_OUTPUT_INT << shift); 363 val |= (WM8903_OUTPUT_INT << shift);
443 wm8903_write(codec, reg, val); 364 snd_soc_write(codec, reg, val);
444 365
445 /* Turn on the output ENA_OUTP */ 366 /* Turn on the output ENA_OUTP */
446 val |= (WM8903_OUTPUT_OUT << shift); 367 val |= (WM8903_OUTPUT_OUT << shift);
447 wm8903_write(codec, reg, val); 368 snd_soc_write(codec, reg, val);
369
370 /* Enable the DC servo */
371 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
372 dcs_reg |= dcs_bit;
373 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
448 374
449 /* Remove the short */ 375 /* Remove the short */
450 val |= (WM8903_OUTPUT_SHORT << shift); 376 val |= (WM8903_OUTPUT_SHORT << shift);
451 wm8903_write(codec, reg, val); 377 snd_soc_write(codec, reg, val);
452 } 378 }
453 379
454 if (event & SND_SOC_DAPM_PRE_PMD) { 380 if (event & SND_SOC_DAPM_PRE_PMD) {
455 val = wm8903_read(codec, reg); 381 val = snd_soc_read(codec, reg);
456 382
457 /* Short the output */ 383 /* Short the output */
458 val &= ~(WM8903_OUTPUT_SHORT << shift); 384 val &= ~(WM8903_OUTPUT_SHORT << shift);
459 wm8903_write(codec, reg, val); 385 snd_soc_write(codec, reg, val);
386
387 /* Disable the DC servo */
388 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
389 dcs_reg &= ~dcs_bit;
390 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
460 391
461 /* Then disable the intermediate and output stages */ 392 /* Then disable the intermediate and output stages */
462 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | 393 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
463 WM8903_OUTPUT_IN) << shift); 394 WM8903_OUTPUT_IN) << shift);
464 wm8903_write(codec, reg, val); 395 snd_soc_write(codec, reg, val);
465 }
466
467 if (event & SND_SOC_DAPM_POST_PMD) {
468 wm8903->charge_pump_users--;
469
470 dev_dbg(&i2c->dev, "Charge pump use count now %d\n",
471 wm8903->charge_pump_users);
472
473 if (wm8903->charge_pump_users == 0) {
474 dev_dbg(&i2c->dev, "Disabling charge pump\n");
475 wm8903_write(codec, WM8903_CHARGE_PUMP_0,
476 cp_reg & ~WM8903_CP_ENA);
477 }
478 } 396 }
479 397
480 return 0; 398 return 0;
@@ -498,13 +416,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
498 u16 reg; 416 u16 reg;
499 int ret; 417 int ret;
500 418
501 reg = wm8903_read(codec, WM8903_CLASS_W_0); 419 reg = snd_soc_read(codec, WM8903_CLASS_W_0);
502 420
503 /* Turn it off if we're about to enable bypass */ 421 /* Turn it off if we're about to enable bypass */
504 if (ucontrol->value.integer.value[0]) { 422 if (ucontrol->value.integer.value[0]) {
505 if (wm8903->class_w_users == 0) { 423 if (wm8903->class_w_users == 0) {
506 dev_dbg(&i2c->dev, "Disabling Class W\n"); 424 dev_dbg(&i2c->dev, "Disabling Class W\n");
507 wm8903_write(codec, WM8903_CLASS_W_0, reg & 425 snd_soc_write(codec, WM8903_CLASS_W_0, reg &
508 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); 426 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
509 } 427 }
510 wm8903->class_w_users++; 428 wm8903->class_w_users++;
@@ -517,7 +435,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
517 if (!ucontrol->value.integer.value[0]) { 435 if (!ucontrol->value.integer.value[0]) {
518 if (wm8903->class_w_users == 1) { 436 if (wm8903->class_w_users == 1) {
519 dev_dbg(&i2c->dev, "Enabling Class W\n"); 437 dev_dbg(&i2c->dev, "Enabling Class W\n");
520 wm8903_write(codec, WM8903_CLASS_W_0, reg | 438 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
521 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 439 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
522 } 440 }
523 wm8903->class_w_users--; 441 wm8903->class_w_users--;
@@ -539,6 +457,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
539/* ALSA can only do steps of .01dB */ 457/* ALSA can only do steps of .01dB */
540static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); 458static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
541 459
460static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0);
542static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); 461static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
543 462
544static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0); 463static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0);
@@ -657,6 +576,16 @@ static const struct soc_enum rinput_inv_enum =
657 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); 576 SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text);
658 577
659 578
579static const char *sidetone_text[] = {
580 "None", "Left", "Right"
581};
582
583static const struct soc_enum lsidetone_enum =
584 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text);
585
586static const struct soc_enum rsidetone_enum =
587 SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
588
660static const struct snd_kcontrol_new wm8903_snd_controls[] = { 589static const struct snd_kcontrol_new wm8903_snd_controls[] = {
661 590
662/* Input PGAs - No TLV since the scale depends on PGA mode */ 591/* Input PGAs - No TLV since the scale depends on PGA mode */
@@ -700,6 +629,9 @@ SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT,
700SOC_ENUM("ADC Companding Mode", adc_companding), 629SOC_ENUM("ADC Companding Mode", adc_companding),
701SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), 630SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0),
702 631
632SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8903_DAC_DIGITAL_0, 4, 8,
633 12, 0, digital_sidetone_tlv),
634
703/* DAC */ 635/* DAC */
704SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT, 636SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT,
705 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), 637 WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv),
@@ -707,8 +639,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
707SOC_ENUM("DAC Mute Mode", mute_mode), 639SOC_ENUM("DAC Mute Mode", mute_mode),
708SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), 640SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
709SOC_ENUM("DAC De-emphasis", dac_deemphasis), 641SOC_ENUM("DAC De-emphasis", dac_deemphasis),
710SOC_SINGLE("DAC Sloping Stopband Filter Switch",
711 WM8903_DAC_DIGITAL_1, 11, 1, 0),
712SOC_ENUM("DAC Companding Mode", dac_companding), 642SOC_ENUM("DAC Companding Mode", dac_companding),
713SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), 643SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
714 644
@@ -762,6 +692,12 @@ static const struct snd_kcontrol_new rinput_mux =
762static const struct snd_kcontrol_new rinput_inv_mux = 692static const struct snd_kcontrol_new rinput_inv_mux =
763 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum); 693 SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum);
764 694
695static const struct snd_kcontrol_new lsidetone_mux =
696 SOC_DAPM_ENUM("DACL Sidetone Mux", lsidetone_enum);
697
698static const struct snd_kcontrol_new rsidetone_mux =
699 SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum);
700
765static const struct snd_kcontrol_new left_output_mixer[] = { 701static const struct snd_kcontrol_new left_output_mixer[] = {
766SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), 702SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
767SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), 703SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
@@ -828,6 +764,9 @@ SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0),
828SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0), 764SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0),
829SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0), 765SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
830 766
767SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux),
768SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux),
769
831SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), 770SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0),
832SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0), 771SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
833 772
@@ -844,26 +783,29 @@ SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
844SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 783SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
845 1, 0, NULL, 0, wm8903_output_event, 784 1, 0, NULL, 0, wm8903_output_event,
846 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 785 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
847 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 786 SND_SOC_DAPM_PRE_PMD),
848SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 787SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
849 0, 0, NULL, 0, wm8903_output_event, 788 0, 0, NULL, 0, wm8903_output_event,
850 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 789 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
851 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 790 SND_SOC_DAPM_PRE_PMD),
852 791
853SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, 792SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
854 NULL, 0, wm8903_output_event, 793 NULL, 0, wm8903_output_event,
855 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 794 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
856 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 795 SND_SOC_DAPM_PRE_PMD),
857SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, 796SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
858 NULL, 0, wm8903_output_event, 797 NULL, 0, wm8903_output_event,
859 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 798 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
860 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 799 SND_SOC_DAPM_PRE_PMD),
861 800
862SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, 801SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
863 NULL, 0), 802 NULL, 0),
864SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, 803SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
865 NULL, 0), 804 NULL, 0),
866 805
806SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0,
807 wm8903_cp_event, SND_SOC_DAPM_POST_PMU),
808SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0),
867}; 809};
868 810
869static const struct snd_soc_dapm_route intercon[] = { 811static const struct snd_soc_dapm_route intercon[] = {
@@ -909,7 +851,19 @@ static const struct snd_soc_dapm_route intercon[] = {
909 { "Right Input PGA", NULL, "Right Input Mode Mux" }, 851 { "Right Input PGA", NULL, "Right Input Mode Mux" },
910 852
911 { "ADCL", NULL, "Left Input PGA" }, 853 { "ADCL", NULL, "Left Input PGA" },
854 { "ADCL", NULL, "CLK_DSP" },
912 { "ADCR", NULL, "Right Input PGA" }, 855 { "ADCR", NULL, "Right Input PGA" },
856 { "ADCR", NULL, "CLK_DSP" },
857
858 { "DACL Sidetone", "Left", "ADCL" },
859 { "DACL Sidetone", "Right", "ADCR" },
860 { "DACR Sidetone", "Left", "ADCL" },
861 { "DACR Sidetone", "Right", "ADCR" },
862
863 { "DACL", NULL, "DACL Sidetone" },
864 { "DACL", NULL, "CLK_DSP" },
865 { "DACR", NULL, "DACR Sidetone" },
866 { "DACR", NULL, "CLK_DSP" },
913 867
914 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" }, 868 { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" },
915 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" }, 869 { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" },
@@ -951,6 +905,11 @@ static const struct snd_soc_dapm_route intercon[] = {
951 905
952 { "ROP", NULL, "Right Speaker PGA" }, 906 { "ROP", NULL, "Right Speaker PGA" },
953 { "RON", NULL, "Right Speaker PGA" }, 907 { "RON", NULL, "Right Speaker PGA" },
908
909 { "Left Headphone Output PGA", NULL, "Charge Pump" },
910 { "Right Headphone Output PGA", NULL, "Charge Pump" },
911 { "Left Line Output PGA", NULL, "Charge Pump" },
912 { "Right Line Output PGA", NULL, "Charge Pump" },
954}; 913};
955 914
956static int wm8903_add_widgets(struct snd_soc_codec *codec) 915static int wm8903_add_widgets(struct snd_soc_codec *codec)
@@ -974,50 +933,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
974 switch (level) { 933 switch (level) {
975 case SND_SOC_BIAS_ON: 934 case SND_SOC_BIAS_ON:
976 case SND_SOC_BIAS_PREPARE: 935 case SND_SOC_BIAS_PREPARE:
977 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); 936 reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
978 reg &= ~(WM8903_VMID_RES_MASK); 937 reg &= ~(WM8903_VMID_RES_MASK);
979 reg |= WM8903_VMID_RES_50K; 938 reg |= WM8903_VMID_RES_50K;
980 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); 939 snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
981 break; 940 break;
982 941
983 case SND_SOC_BIAS_STANDBY: 942 case SND_SOC_BIAS_STANDBY:
984 if (codec->bias_level == SND_SOC_BIAS_OFF) { 943 if (codec->bias_level == SND_SOC_BIAS_OFF) {
985 wm8903_write(codec, WM8903_CLOCK_RATES_2, 944 snd_soc_write(codec, WM8903_CLOCK_RATES_2,
986 WM8903_CLK_SYS_ENA); 945 WM8903_CLK_SYS_ENA);
987 946
947 /* Change DC servo dither level in startup sequence */
948 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
949 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
950 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
951
988 wm8903_run_sequence(codec, 0); 952 wm8903_run_sequence(codec, 0);
989 wm8903_sync_reg_cache(codec, codec->reg_cache); 953 wm8903_sync_reg_cache(codec, codec->reg_cache);
990 954
991 /* Enable low impedence charge pump output */ 955 /* Enable low impedence charge pump output */
992 reg = wm8903_read(codec, 956 reg = snd_soc_read(codec,
993 WM8903_CONTROL_INTERFACE_TEST_1); 957 WM8903_CONTROL_INTERFACE_TEST_1);
994 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, 958 snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
995 reg | WM8903_TEST_KEY); 959 reg | WM8903_TEST_KEY);
996 reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1); 960 reg2 = snd_soc_read(codec, WM8903_CHARGE_PUMP_TEST_1);
997 wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1, 961 snd_soc_write(codec, WM8903_CHARGE_PUMP_TEST_1,
998 reg2 | WM8903_CP_SW_KELVIN_MODE_MASK); 962 reg2 | WM8903_CP_SW_KELVIN_MODE_MASK);
999 wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, 963 snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
1000 reg); 964 reg);
1001 965
1002 /* By default no bypass paths are enabled so 966 /* By default no bypass paths are enabled so
1003 * enable Class W support. 967 * enable Class W support.
1004 */ 968 */
1005 dev_dbg(&i2c->dev, "Enabling Class W\n"); 969 dev_dbg(&i2c->dev, "Enabling Class W\n");
1006 wm8903_write(codec, WM8903_CLASS_W_0, reg | 970 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
1007 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 971 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
1008 } 972 }
1009 973
1010 reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); 974 reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
1011 reg &= ~(WM8903_VMID_RES_MASK); 975 reg &= ~(WM8903_VMID_RES_MASK);
1012 reg |= WM8903_VMID_RES_250K; 976 reg |= WM8903_VMID_RES_250K;
1013 wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); 977 snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
1014 break; 978 break;
1015 979
1016 case SND_SOC_BIAS_OFF: 980 case SND_SOC_BIAS_OFF:
1017 wm8903_run_sequence(codec, 32); 981 wm8903_run_sequence(codec, 32);
1018 reg = wm8903_read(codec, WM8903_CLOCK_RATES_2); 982 reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2);
1019 reg &= ~WM8903_CLK_SYS_ENA; 983 reg &= ~WM8903_CLK_SYS_ENA;
1020 wm8903_write(codec, WM8903_CLOCK_RATES_2, reg); 984 snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg);
1021 break; 985 break;
1022 } 986 }
1023 987
@@ -1041,7 +1005,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
1041 unsigned int fmt) 1005 unsigned int fmt)
1042{ 1006{
1043 struct snd_soc_codec *codec = codec_dai->codec; 1007 struct snd_soc_codec *codec = codec_dai->codec;
1044 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); 1008 u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
1045 1009
1046 aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | 1010 aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK |
1047 WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); 1011 WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV);
@@ -1119,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
1119 return -EINVAL; 1083 return -EINVAL;
1120 } 1084 }
1121 1085
1122 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); 1086 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1123 1087
1124 return 0; 1088 return 0;
1125} 1089}
@@ -1129,14 +1093,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1129 struct snd_soc_codec *codec = codec_dai->codec; 1093 struct snd_soc_codec *codec = codec_dai->codec;
1130 u16 reg; 1094 u16 reg;
1131 1095
1132 reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1); 1096 reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1133 1097
1134 if (mute) 1098 if (mute)
1135 reg |= WM8903_DAC_MUTE; 1099 reg |= WM8903_DAC_MUTE;
1136 else 1100 else
1137 reg &= ~WM8903_DAC_MUTE; 1101 reg &= ~WM8903_DAC_MUTE;
1138 1102
1139 wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg); 1103 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg);
1140 1104
1141 return 0; 1105 return 0;
1142} 1106}
@@ -1215,22 +1179,18 @@ static struct {
1215 int div; 1179 int div;
1216} bclk_divs[] = { 1180} bclk_divs[] = {
1217 { 10, 0 }, 1181 { 10, 0 },
1218 { 15, 1 },
1219 { 20, 2 }, 1182 { 20, 2 },
1220 { 30, 3 }, 1183 { 30, 3 },
1221 { 40, 4 }, 1184 { 40, 4 },
1222 { 50, 5 }, 1185 { 50, 5 },
1223 { 55, 6 },
1224 { 60, 7 }, 1186 { 60, 7 },
1225 { 80, 8 }, 1187 { 80, 8 },
1226 { 100, 9 }, 1188 { 100, 9 },
1227 { 110, 10 },
1228 { 120, 11 }, 1189 { 120, 11 },
1229 { 160, 12 }, 1190 { 160, 12 },
1230 { 200, 13 }, 1191 { 200, 13 },
1231 { 220, 14 }, 1192 { 220, 14 },
1232 { 240, 15 }, 1193 { 240, 15 },
1233 { 250, 16 },
1234 { 300, 17 }, 1194 { 300, 17 },
1235 { 320, 18 }, 1195 { 320, 18 },
1236 { 440, 19 }, 1196 { 440, 19 },
@@ -1277,14 +1237,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
1277 if (wm8903->master_substream) { 1237 if (wm8903->master_substream) {
1278 master_runtime = wm8903->master_substream->runtime; 1238 master_runtime = wm8903->master_substream->runtime;
1279 1239
1280 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 1240 dev_dbg(&i2c->dev, "Constraining to %d bits\n",
1281 master_runtime->sample_bits, 1241 master_runtime->sample_bits);
1282 master_runtime->rate);
1283
1284 snd_pcm_hw_constraint_minmax(substream->runtime,
1285 SNDRV_PCM_HW_PARAM_RATE,
1286 master_runtime->rate,
1287 master_runtime->rate);
1288 1242
1289 snd_pcm_hw_constraint_minmax(substream->runtime, 1243 snd_pcm_hw_constraint_minmax(substream->runtime,
1290 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 1244 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
@@ -1336,17 +1290,24 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1336 int cur_val; 1290 int cur_val;
1337 int clk_sys; 1291 int clk_sys;
1338 1292
1339 u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); 1293 u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
1340 u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2); 1294 u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2);
1341 u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); 1295 u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3);
1342 u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); 1296 u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0);
1343 u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); 1297 u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1);
1298 u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1344 1299
1345 if (substream == wm8903->slave_substream) { 1300 if (substream == wm8903->slave_substream) {
1346 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 1301 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
1347 return 0; 1302 return 0;
1348 } 1303 }
1349 1304
1305 /* Enable sloping stopband filter for low sample rates */
1306 if (fs <= 24000)
1307 dac_digital1 |= WM8903_DAC_SB_FILT;
1308 else
1309 dac_digital1 &= ~WM8903_DAC_SB_FILT;
1310
1350 /* Configure sample rate logic for DSP - choose nearest rate */ 1311 /* Configure sample rate logic for DSP - choose nearest rate */
1351 dsp_config = 0; 1312 dsp_config = 0;
1352 best_val = abs(sample_rates[dsp_config].rate - fs); 1313 best_val = abs(sample_rates[dsp_config].rate - fs);
@@ -1466,11 +1427,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1466 aif2 |= bclk_divs[bclk_div].div; 1427 aif2 |= bclk_divs[bclk_div].div;
1467 aif3 |= bclk / fs; 1428 aif3 |= bclk / fs;
1468 1429
1469 wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0); 1430 snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0);
1470 wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1); 1431 snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1);
1471 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); 1432 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1472 wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); 1433 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
1473 wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); 1434 snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
1435 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
1474 1436
1475 return 0; 1437 return 0;
1476} 1438}
@@ -1523,6 +1485,7 @@ struct snd_soc_dai wm8903_dai = {
1523 .formats = WM8903_FORMATS, 1485 .formats = WM8903_FORMATS,
1524 }, 1486 },
1525 .ops = &wm8903_dai_ops, 1487 .ops = &wm8903_dai_ops,
1488 .symmetric_rates = 1,
1526}; 1489};
1527EXPORT_SYMBOL_GPL(wm8903_dai); 1490EXPORT_SYMBOL_GPL(wm8903_dai);
1528 1491
@@ -1554,7 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev)
1554 if (tmp_cache) { 1517 if (tmp_cache) {
1555 for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) 1518 for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
1556 if (tmp_cache[i] != reg_cache[i]) 1519 if (tmp_cache[i] != reg_cache[i])
1557 wm8903_write(codec, i, tmp_cache[i]); 1520 snd_soc_write(codec, i, tmp_cache[i]);
1558 } else { 1521 } else {
1559 dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); 1522 dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
1560 } 1523 }
@@ -1585,9 +1548,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1585 codec->dev = &i2c->dev; 1548 codec->dev = &i2c->dev;
1586 codec->name = "WM8903"; 1549 codec->name = "WM8903";
1587 codec->owner = THIS_MODULE; 1550 codec->owner = THIS_MODULE;
1588 codec->read = wm8903_read;
1589 codec->write = wm8903_write;
1590 codec->hw_write = (hw_write_t)i2c_master_send;
1591 codec->bias_level = SND_SOC_BIAS_OFF; 1551 codec->bias_level = SND_SOC_BIAS_OFF;
1592 codec->set_bias_level = wm8903_set_bias_level; 1552 codec->set_bias_level = wm8903_set_bias_level;
1593 codec->dai = &wm8903_dai; 1553 codec->dai = &wm8903_dai;
@@ -1595,18 +1555,25 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1595 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); 1555 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
1596 codec->reg_cache = &wm8903->reg_cache[0]; 1556 codec->reg_cache = &wm8903->reg_cache[0];
1597 codec->private_data = wm8903; 1557 codec->private_data = wm8903;
1558 codec->volatile_register = wm8903_volatile_register;
1598 1559
1599 i2c_set_clientdata(i2c, codec); 1560 i2c_set_clientdata(i2c, codec);
1600 codec->control_data = i2c; 1561 codec->control_data = i2c;
1601 1562
1602 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); 1563 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1564 if (ret != 0) {
1565 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
1566 goto err;
1567 }
1568
1569 val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
1603 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { 1570 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1604 dev_err(&i2c->dev, 1571 dev_err(&i2c->dev,
1605 "Device with ID register %x is not a WM8903\n", val); 1572 "Device with ID register %x is not a WM8903\n", val);
1606 return -ENODEV; 1573 return -ENODEV;
1607 } 1574 }
1608 1575
1609 val = wm8903_read(codec, WM8903_REVISION_NUMBER); 1576 val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
1610 dev_info(&i2c->dev, "WM8903 revision %d\n", 1577 dev_info(&i2c->dev, "WM8903 revision %d\n",
1611 val & WM8903_CHIP_REV_MASK); 1578 val & WM8903_CHIP_REV_MASK);
1612 1579
@@ -1616,35 +1583,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1616 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1583 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1617 1584
1618 /* Latch volume update bits */ 1585 /* Latch volume update bits */
1619 val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); 1586 val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
1620 val |= WM8903_ADCVU; 1587 val |= WM8903_ADCVU;
1621 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); 1588 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
1622 wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); 1589 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
1623 1590
1624 val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); 1591 val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
1625 val |= WM8903_DACVU; 1592 val |= WM8903_DACVU;
1626 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); 1593 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
1627 wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); 1594 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
1628 1595
1629 val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT); 1596 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
1630 val |= WM8903_HPOUTVU; 1597 val |= WM8903_HPOUTVU;
1631 wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); 1598 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
1632 wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); 1599 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
1633 1600
1634 val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT); 1601 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
1635 val |= WM8903_LINEOUTVU; 1602 val |= WM8903_LINEOUTVU;
1636 wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); 1603 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
1637 wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); 1604 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
1638 1605
1639 val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT); 1606 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
1640 val |= WM8903_SPKVU; 1607 val |= WM8903_SPKVU;
1641 wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); 1608 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
1642 wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); 1609 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
1643 1610
1644 /* Enable DAC soft mute by default */ 1611 /* Enable DAC soft mute by default */
1645 val = wm8903_read(codec, WM8903_DAC_DIGITAL_1); 1612 val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1646 val |= WM8903_DAC_MUTEMODE; 1613 val |= WM8903_DAC_MUTEMODE;
1647 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); 1614 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
1648 1615
1649 wm8903_dai.dev = &i2c->dev; 1616 wm8903_dai.dev = &i2c->dev;
1650 wm8903_codec = codec; 1617 wm8903_codec = codec;
@@ -1688,6 +1655,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1688 return 0; 1655 return 0;
1689} 1656}
1690 1657
1658#ifdef CONFIG_PM
1659static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1660{
1661 return snd_soc_suspend_device(&client->dev);
1662}
1663
1664static 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
1691/* i2c codec control layer */ 1673/* i2c codec control layer */
1692static const struct i2c_device_id wm8903_i2c_id[] = { 1674static const struct i2c_device_id wm8903_i2c_id[] = {
1693 { "wm8903", 0 }, 1675 { "wm8903", 0 },
@@ -1702,6 +1684,8 @@ static struct i2c_driver wm8903_i2c_driver = {
1702 }, 1684 },
1703 .probe = wm8903_i2c_probe, 1685 .probe = wm8903_i2c_probe,
1704 .remove = __devexit_p(wm8903_i2c_remove), 1686 .remove = __devexit_p(wm8903_i2c_remove),
1687 .suspend = wm8903_i2c_suspend,
1688 .resume = wm8903_i2c_resume,
1705 .id_table = wm8903_i2c_id, 1689 .id_table = wm8903_i2c_id,
1706}; 1690};
1707 1691
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
new file mode 100644
index 000000000000..da97aae475a2
--- /dev/null
+++ b/sound/soc/codecs/wm8940.c
@@ -0,0 +1,933 @@
1/*
2 * wm8940.c -- WM8940 ALSA Soc Audio driver
3 *
4 * Author: Jonathan Cameron <jic23@cam.ac.uk>
5 *
6 * Based on wm8510.c
7 * Copyright 2006 Wolfson Microelectronics PLC.
8 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
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 * Not currently handled:
15 * Notch filter control
16 * AUXMode (inverting vs mixer)
17 * No means to obtain current gain if alc enabled.
18 * No use made of gpio
19 * Fast VMID discharge for power down
20 * Soft Start
21 * DLR and ALR Swaps not enabled
22 * Digital Sidetone not supported
23 */
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/i2c.h>
31#include <linux/platform_device.h>
32#include <linux/spi/spi.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38#include <sound/initval.h>
39#include <sound/tlv.h>
40
41#include "wm8940.h"
42
43struct wm8940_priv {
44 unsigned int sysclk;
45 u16 reg_cache[WM8940_CACHEREGNUM];
46 struct snd_soc_codec codec;
47};
48
49static u16 wm8940_reg_defaults[] = {
50 0x8940, /* Soft Reset */
51 0x0000, /* Power 1 */
52 0x0000, /* Power 2 */
53 0x0000, /* Power 3 */
54 0x0010, /* Interface Control */
55 0x0000, /* Companding Control */
56 0x0140, /* Clock Control */
57 0x0000, /* Additional Controls */
58 0x0000, /* GPIO Control */
59 0x0002, /* Auto Increment Control */
60 0x0000, /* DAC Control */
61 0x00FF, /* DAC Volume */
62 0,
63 0,
64 0x0100, /* ADC Control */
65 0x00FF, /* ADC Volume */
66 0x0000, /* Notch Filter 1 Control 1 */
67 0x0000, /* Notch Filter 1 Control 2 */
68 0x0000, /* Notch Filter 2 Control 1 */
69 0x0000, /* Notch Filter 2 Control 2 */
70 0x0000, /* Notch Filter 3 Control 1 */
71 0x0000, /* Notch Filter 3 Control 2 */
72 0x0000, /* Notch Filter 4 Control 1 */
73 0x0000, /* Notch Filter 4 Control 2 */
74 0x0032, /* DAC Limit Control 1 */
75 0x0000, /* DAC Limit Control 2 */
76 0,
77 0,
78 0,
79 0,
80 0,
81 0,
82 0x0038, /* ALC Control 1 */
83 0x000B, /* ALC Control 2 */
84 0x0032, /* ALC Control 3 */
85 0x0000, /* Noise Gate */
86 0x0041, /* PLLN */
87 0x000C, /* PLLK1 */
88 0x0093, /* PLLK2 */
89 0x00E9, /* PLLK3 */
90 0,
91 0,
92 0x0030, /* ALC Control 4 */
93 0,
94 0x0002, /* Input Control */
95 0x0050, /* PGA Gain */
96 0,
97 0x0002, /* ADC Boost Control */
98 0,
99 0x0002, /* Output Control */
100 0x0000, /* Speaker Mixer Control */
101 0,
102 0,
103 0,
104 0x0079, /* Speaker Volume */
105 0,
106 0x0000, /* Mono Mixer Control */
107};
108
109static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
110static const struct soc_enum wm8940_adc_companding_enum
111= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
112static const struct soc_enum wm8940_dac_companding_enum
113= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding);
114
115static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"};
116static const struct soc_enum wm8940_alc_mode_enum
117= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text);
118
119static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"};
120static const struct soc_enum wm8940_mic_bias_level_enum
121= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text);
122
123static const char *wm8940_filter_mode_text[] = {"Audio", "Application"};
124static const struct soc_enum wm8940_filter_mode_enum
125= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text);
126
127static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1);
128static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0);
129static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0);
130static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0);
131static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0);
132static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0);
133static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0);
134static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0);
135static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1);
136static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0);
137
138static const struct snd_kcontrol_new wm8940_snd_controls[] = {
139 SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL,
140 6, 1, 0),
141 SOC_ENUM("DAC Companding", wm8940_dac_companding_enum),
142 SOC_ENUM("ADC Companding", wm8940_adc_companding_enum),
143
144 SOC_ENUM("ALC Mode", wm8940_alc_mode_enum),
145 SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0),
146 SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1,
147 3, 7, 1, wm8940_alc_max_tlv),
148 SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1,
149 0, 7, 0, wm8940_alc_min_tlv),
150 SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2,
151 0, 14, 0, wm8940_alc_tar_tlv),
152 SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0),
153 SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0),
154 SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0),
155 SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0),
156 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE,
157 3, 1, 0),
158 SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE,
159 0, 7, 0),
160
161 SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0),
162 SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0),
163 SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0),
164 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2,
165 4, 9, 1, wm8940_lim_thresh_tlv),
166 SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2,
167 0, 12, 0, wm8940_lim_boost_tlv),
168
169 SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0),
170 SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN,
171 0, 63, 0, wm8940_pga_vol_tlv),
172 SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL,
173 0, 255, 0, wm8940_adc_tlv),
174 SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL,
175 0, 255, 0, wm8940_adc_tlv),
176 SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum),
177 SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST,
178 8, 1, 0, wm8940_capture_boost_vol_tlv),
179 SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL,
180 0, 63, 0, wm8940_spk_vol_tlv),
181 SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1),
182
183 SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL,
184 8, 1, 1, wm8940_att_tlv),
185 SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0),
186
187 SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1),
188 SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX,
189 7, 1, 1, wm8940_att_tlv),
190
191 SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0),
192 SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum),
193 SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0),
194 SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0),
195 SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0),
196 SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0),
197 SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0),
198};
199
200static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = {
201 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0),
202 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0),
203 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0),
204};
205
206static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = {
207 SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0),
208 SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0),
209 SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0),
210};
211
212static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1);
213static const struct snd_kcontrol_new wm8940_input_boost_controls[] = {
214 SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1),
215 SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST,
216 0, 7, 0, wm8940_boost_vol_tlv),
217 SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST,
218 4, 7, 0, wm8940_boost_vol_tlv),
219};
220
221static const struct snd_kcontrol_new wm8940_micpga_controls[] = {
222 SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0),
223 SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0),
224 SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0),
225};
226
227static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
228 SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0,
229 &wm8940_speaker_mixer_controls[0],
230 ARRAY_SIZE(wm8940_speaker_mixer_controls)),
231 SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0,
232 &wm8940_mono_mixer_controls[0],
233 ARRAY_SIZE(wm8940_mono_mixer_controls)),
234 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0),
235
236 SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0),
237 SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0),
238 SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0),
239 SND_SOC_DAPM_OUTPUT("MONOOUT"),
240 SND_SOC_DAPM_OUTPUT("SPKOUTP"),
241 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
242
243 SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0),
244 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0),
245 SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0,
246 &wm8940_micpga_controls[0],
247 ARRAY_SIZE(wm8940_micpga_controls)),
248 SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0,
249 &wm8940_input_boost_controls[0],
250 ARRAY_SIZE(wm8940_input_boost_controls)),
251 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0),
252
253 SND_SOC_DAPM_INPUT("MICN"),
254 SND_SOC_DAPM_INPUT("MICP"),
255 SND_SOC_DAPM_INPUT("AUX"),
256};
257
258static const struct snd_soc_dapm_route audio_map[] = {
259 /* Mono output mixer */
260 {"Mono Mixer", "PCM Playback Switch", "DAC"},
261 {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
262 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
263
264 /* Speaker output mixer */
265 {"Speaker Mixer", "PCM Playback Switch", "DAC"},
266 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
267 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
268
269 /* Outputs */
270 {"Mono Out", NULL, "Mono Mixer"},
271 {"MONOOUT", NULL, "Mono Out"},
272 {"SpkN Out", NULL, "Speaker Mixer"},
273 {"SpkP Out", NULL, "Speaker Mixer"},
274 {"SPKOUTN", NULL, "SpkN Out"},
275 {"SPKOUTP", NULL, "SpkP Out"},
276
277 /* Microphone PGA */
278 {"Mic PGA", "MICN Switch", "MICN"},
279 {"Mic PGA", "MICP Switch", "MICP"},
280 {"Mic PGA", "AUX Switch", "AUX"},
281
282 /* Boost Mixer */
283 {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
284 {"Boost Mixer", "Mic Volume", "MICP"},
285 {"Boost Mixer", "Aux Volume", "Aux Input"},
286
287 {"ADC", NULL, "Boost Mixer"},
288};
289
290static int wm8940_add_widgets(struct snd_soc_codec *codec)
291{
292 int ret;
293
294 ret = snd_soc_dapm_new_controls(codec, wm8940_dapm_widgets,
295 ARRAY_SIZE(wm8940_dapm_widgets));
296 if (ret)
297 goto error_ret;
298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
299 if (ret)
300 goto error_ret;
301 ret = snd_soc_dapm_new_widgets(codec);
302
303error_ret:
304 return ret;
305}
306
307#define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0);
308
309static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
310 unsigned int fmt)
311{
312 struct snd_soc_codec *codec = codec_dai->codec;
313 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFE67;
314 u16 clk = snd_soc_read(codec, WM8940_CLOCK) & 0x1fe;
315
316 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
317 case SND_SOC_DAIFMT_CBM_CFM:
318 clk |= 1;
319 break;
320 case SND_SOC_DAIFMT_CBS_CFS:
321 break;
322 default:
323 return -EINVAL;
324 }
325 snd_soc_write(codec, WM8940_CLOCK, clk);
326
327 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
328 case SND_SOC_DAIFMT_I2S:
329 iface |= (2 << 3);
330 break;
331 case SND_SOC_DAIFMT_LEFT_J:
332 iface |= (1 << 3);
333 break;
334 case SND_SOC_DAIFMT_RIGHT_J:
335 break;
336 case SND_SOC_DAIFMT_DSP_A:
337 iface |= (3 << 3);
338 break;
339 case SND_SOC_DAIFMT_DSP_B:
340 iface |= (3 << 3) | (1 << 7);
341 break;
342 }
343
344 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
345 case SND_SOC_DAIFMT_NB_NF:
346 break;
347 case SND_SOC_DAIFMT_NB_IF:
348 iface |= (1 << 7);
349 break;
350 case SND_SOC_DAIFMT_IB_NF:
351 iface |= (1 << 8);
352 break;
353 case SND_SOC_DAIFMT_IB_IF:
354 iface |= (1 << 8) | (1 << 7);
355 break;
356 }
357
358 snd_soc_write(codec, WM8940_IFACE, iface);
359
360 return 0;
361}
362
363static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
364 struct snd_pcm_hw_params *params,
365 struct snd_soc_dai *dai)
366{
367 struct snd_soc_pcm_runtime *rtd = substream->private_data;
368 struct snd_soc_device *socdev = rtd->socdev;
369 struct snd_soc_codec *codec = socdev->card->codec;
370 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
371 u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
372 u16 companding = snd_soc_read(codec,
373 WM8940_COMPANDINGCTL) & 0xFFDF;
374 int ret;
375
376 /* LoutR control */
377 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
378 && params_channels(params) == 2)
379 iface |= (1 << 9);
380
381 switch (params_rate(params)) {
382 case SNDRV_PCM_RATE_8000:
383 addcntrl |= (0x5 << 1);
384 break;
385 case SNDRV_PCM_RATE_11025:
386 addcntrl |= (0x4 << 1);
387 break;
388 case SNDRV_PCM_RATE_16000:
389 addcntrl |= (0x3 << 1);
390 break;
391 case SNDRV_PCM_RATE_22050:
392 addcntrl |= (0x2 << 1);
393 break;
394 case SNDRV_PCM_RATE_32000:
395 addcntrl |= (0x1 << 1);
396 break;
397 case SNDRV_PCM_RATE_44100:
398 case SNDRV_PCM_RATE_48000:
399 break;
400 }
401 ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl);
402 if (ret)
403 goto error_ret;
404
405 switch (params_format(params)) {
406 case SNDRV_PCM_FORMAT_S8:
407 companding = companding | (1 << 5);
408 break;
409 case SNDRV_PCM_FORMAT_S16_LE:
410 break;
411 case SNDRV_PCM_FORMAT_S20_3LE:
412 iface |= (1 << 5);
413 break;
414 case SNDRV_PCM_FORMAT_S24_LE:
415 iface |= (2 << 5);
416 break;
417 case SNDRV_PCM_FORMAT_S32_LE:
418 iface |= (3 << 5);
419 break;
420 }
421 ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding);
422 if (ret)
423 goto error_ret;
424 ret = snd_soc_write(codec, WM8940_IFACE, iface);
425
426error_ret:
427 return ret;
428}
429
430static int wm8940_mute(struct snd_soc_dai *dai, int mute)
431{
432 struct snd_soc_codec *codec = dai->codec;
433 u16 mute_reg = snd_soc_read(codec, WM8940_DAC) & 0xffbf;
434
435 if (mute)
436 mute_reg |= 0x40;
437
438 return snd_soc_write(codec, WM8940_DAC, mute_reg);
439}
440
441static int wm8940_set_bias_level(struct snd_soc_codec *codec,
442 enum snd_soc_bias_level level)
443{
444 u16 val;
445 u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0;
446 int ret = 0;
447
448 switch (level) {
449 case SND_SOC_BIAS_ON:
450 /* ensure bufioen and biasen */
451 pwr_reg |= (1 << 2) | (1 << 3);
452 /* Enable thermal shutdown */
453 val = snd_soc_read(codec, WM8940_OUTPUTCTL);
454 ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2);
455 if (ret)
456 break;
457 /* set vmid to 75k */
458 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
459 break;
460 case SND_SOC_BIAS_PREPARE:
461 /* ensure bufioen and biasen */
462 pwr_reg |= (1 << 2) | (1 << 3);
463 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
464 break;
465 case SND_SOC_BIAS_STANDBY:
466 /* ensure bufioen and biasen */
467 pwr_reg |= (1 << 2) | (1 << 3);
468 /* set vmid to 300k for standby */
469 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2);
470 break;
471 case SND_SOC_BIAS_OFF:
472 ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg);
473 break;
474 }
475
476 return ret;
477}
478
479struct pll_ {
480 unsigned int pre_scale:2;
481 unsigned int n:4;
482 unsigned int k;
483};
484
485static struct pll_ pll_div;
486
487/* The size in bits of the pll divide multiplied by 10
488 * to allow rounding later */
489#define FIXED_PLL_SIZE ((1 << 24) * 10)
490static void pll_factors(unsigned int target, unsigned int source)
491{
492 unsigned long long Kpart;
493 unsigned int K, Ndiv, Nmod;
494 /* The left shift ist to avoid accuracy loss when right shifting */
495 Ndiv = target / source;
496
497 if (Ndiv > 12) {
498 source <<= 1;
499 /* Multiply by 2 */
500 pll_div.pre_scale = 0;
501 Ndiv = target / source;
502 } else if (Ndiv < 3) {
503 source >>= 2;
504 /* Divide by 4 */
505 pll_div.pre_scale = 3;
506 Ndiv = target / source;
507 } else if (Ndiv < 6) {
508 source >>= 1;
509 /* divide by 2 */
510 pll_div.pre_scale = 2;
511 Ndiv = target / source;
512 } else
513 pll_div.pre_scale = 1;
514
515 if ((Ndiv < 6) || (Ndiv > 12))
516 printk(KERN_WARNING
517 "WM8940 N value %d outwith recommended range!d\n",
518 Ndiv);
519
520 pll_div.n = Ndiv;
521 Nmod = target % source;
522 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
523
524 do_div(Kpart, source);
525
526 K = Kpart & 0xFFFFFFFF;
527
528 /* Check if we need to round */
529 if ((K % 10) >= 5)
530 K += 5;
531
532 /* Move down to proper range now rounding is done */
533 K /= 10;
534
535 pll_div.k = K;
536}
537
538/* Untested at the moment */
539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
540 int pll_id, unsigned int freq_in, unsigned int freq_out)
541{
542 struct snd_soc_codec *codec = codec_dai->codec;
543 u16 reg;
544
545 /* Turn off PLL */
546 reg = snd_soc_read(codec, WM8940_POWER1);
547 snd_soc_write(codec, WM8940_POWER1, reg & 0x1df);
548
549 if (freq_in == 0 || freq_out == 0) {
550 /* Clock CODEC directly from MCLK */
551 reg = snd_soc_read(codec, WM8940_CLOCK);
552 snd_soc_write(codec, WM8940_CLOCK, reg & 0x0ff);
553 /* Pll power down */
554 snd_soc_write(codec, WM8940_PLLN, (1 << 7));
555 return 0;
556 }
557
558 /* Pll is followed by a frequency divide by 4 */
559 pll_factors(freq_out*4, freq_in);
560 if (pll_div.k)
561 snd_soc_write(codec, WM8940_PLLN,
562 (pll_div.pre_scale << 4) | pll_div.n | (1 << 6));
563 else /* No factional component */
564 snd_soc_write(codec, WM8940_PLLN,
565 (pll_div.pre_scale << 4) | pll_div.n);
566 snd_soc_write(codec, WM8940_PLLK1, pll_div.k >> 18);
567 snd_soc_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
568 snd_soc_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
569 /* Enable the PLL */
570 reg = snd_soc_read(codec, WM8940_POWER1);
571 snd_soc_write(codec, WM8940_POWER1, reg | 0x020);
572
573 /* Run CODEC from PLL instead of MCLK */
574 reg = snd_soc_read(codec, WM8940_CLOCK);
575 snd_soc_write(codec, WM8940_CLOCK, reg | 0x100);
576
577 return 0;
578}
579
580static int wm8940_set_dai_sysclk(struct snd_soc_dai *codec_dai,
581 int clk_id, unsigned int freq, int dir)
582{
583 struct snd_soc_codec *codec = codec_dai->codec;
584 struct wm8940_priv *wm8940 = codec->private_data;
585
586 switch (freq) {
587 case 11289600:
588 case 12000000:
589 case 12288000:
590 case 16934400:
591 case 18432000:
592 wm8940->sysclk = freq;
593 return 0;
594 }
595 return -EINVAL;
596}
597
598static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
599 int div_id, int div)
600{
601 struct snd_soc_codec *codec = codec_dai->codec;
602 u16 reg;
603 int ret = 0;
604
605 switch (div_id) {
606 case WM8940_BCLKDIV:
607 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
608 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
609 break;
610 case WM8940_MCLKDIV:
611 reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F;
612 ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
613 break;
614 case WM8940_OPCLKDIV:
615 reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
616 ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
617 break;
618 }
619 return ret;
620}
621
622#define WM8940_RATES SNDRV_PCM_RATE_8000_48000
623
624#define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
625 SNDRV_PCM_FMTBIT_S16_LE | \
626 SNDRV_PCM_FMTBIT_S20_3LE | \
627 SNDRV_PCM_FMTBIT_S24_LE | \
628 SNDRV_PCM_FMTBIT_S32_LE)
629
630static struct snd_soc_dai_ops wm8940_dai_ops = {
631 .hw_params = wm8940_i2s_hw_params,
632 .set_sysclk = wm8940_set_dai_sysclk,
633 .digital_mute = wm8940_mute,
634 .set_fmt = wm8940_set_dai_fmt,
635 .set_clkdiv = wm8940_set_dai_clkdiv,
636 .set_pll = wm8940_set_dai_pll,
637};
638
639struct snd_soc_dai wm8940_dai = {
640 .name = "WM8940",
641 .playback = {
642 .stream_name = "Playback",
643 .channels_min = 1,
644 .channels_max = 2,
645 .rates = WM8940_RATES,
646 .formats = WM8940_FORMATS,
647 },
648 .capture = {
649 .stream_name = "Capture",
650 .channels_min = 1,
651 .channels_max = 2,
652 .rates = WM8940_RATES,
653 .formats = WM8940_FORMATS,
654 },
655 .ops = &wm8940_dai_ops,
656 .symmetric_rates = 1,
657};
658EXPORT_SYMBOL_GPL(wm8940_dai);
659
660static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
661{
662 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
663 struct snd_soc_codec *codec = socdev->card->codec;
664
665 return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
666}
667
668static int wm8940_resume(struct platform_device *pdev)
669{
670 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
671 struct snd_soc_codec *codec = socdev->card->codec;
672 int i;
673 int ret;
674 u8 data[3];
675 u16 *cache = codec->reg_cache;
676
677 /* Sync reg_cache with the hardware
678 * Could use auto incremented writes to speed this up
679 */
680 for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
681 data[0] = i;
682 data[1] = (cache[i] & 0xFF00) >> 8;
683 data[2] = cache[i] & 0x00FF;
684 ret = codec->hw_write(codec->control_data, data, 3);
685 if (ret < 0)
686 goto error_ret;
687 else if (ret != 3) {
688 ret = -EIO;
689 goto error_ret;
690 }
691 }
692 ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
693 if (ret)
694 goto error_ret;
695 ret = wm8940_set_bias_level(codec, codec->suspend_bias_level);
696
697error_ret:
698 return ret;
699}
700
701static struct snd_soc_codec *wm8940_codec;
702
703static int wm8940_probe(struct platform_device *pdev)
704{
705 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
706 struct snd_soc_codec *codec;
707
708 int ret = 0;
709
710 if (wm8940_codec == NULL) {
711 dev_err(&pdev->dev, "Codec device not registered\n");
712 return -ENODEV;
713 }
714
715 socdev->card->codec = wm8940_codec;
716 codec = wm8940_codec;
717
718 mutex_init(&codec->mutex);
719 /* register pcms */
720 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
721 if (ret < 0) {
722 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
723 goto pcm_err;
724 }
725
726 ret = snd_soc_add_controls(codec, wm8940_snd_controls,
727 ARRAY_SIZE(wm8940_snd_controls));
728 if (ret)
729 goto error_free_pcms;
730 ret = wm8940_add_widgets(codec);
731 if (ret)
732 goto error_free_pcms;
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;
741
742error_free_pcms:
743 snd_soc_free_pcms(socdev);
744 snd_soc_dapm_free(socdev);
745pcm_err:
746 return ret;
747}
748
749static int wm8940_remove(struct platform_device *pdev)
750{
751 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
752
753 snd_soc_free_pcms(socdev);
754 snd_soc_dapm_free(socdev);
755
756 return 0;
757}
758
759struct snd_soc_codec_device soc_codec_dev_wm8940 = {
760 .probe = wm8940_probe,
761 .remove = wm8940_remove,
762 .suspend = wm8940_suspend,
763 .resume = wm8940_resume,
764};
765EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
766
767static int wm8940_register(struct wm8940_priv *wm8940,
768 enum snd_soc_control_type control)
769{
770 struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
771 struct snd_soc_codec *codec = &wm8940->codec;
772 int ret;
773 u16 reg;
774 if (wm8940_codec) {
775 dev_err(codec->dev, "Another WM8940 is registered\n");
776 return -EINVAL;
777 }
778
779 INIT_LIST_HEAD(&codec->dapm_widgets);
780 INIT_LIST_HEAD(&codec->dapm_paths);
781
782 codec->private_data = wm8940;
783 codec->name = "WM8940";
784 codec->owner = THIS_MODULE;
785 codec->bias_level = SND_SOC_BIAS_OFF;
786 codec->set_bias_level = wm8940_set_bias_level;
787 codec->dai = &wm8940_dai;
788 codec->num_dai = 1;
789 codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
790 codec->reg_cache = &wm8940->reg_cache;
791
792 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
793 if (ret == 0) {
794 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
795 return ret;
796 }
797
798 memcpy(codec->reg_cache, wm8940_reg_defaults,
799 sizeof(wm8940_reg_defaults));
800
801 ret = wm8940_reset(codec);
802 if (ret < 0) {
803 dev_err(codec->dev, "Failed to issue reset\n");
804 return ret;
805 }
806
807 wm8940_dai.dev = codec->dev;
808
809 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
810
811 ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
812 if (ret < 0)
813 return ret;
814
815 if (!pdata)
816 dev_warn(codec->dev, "No platform data supplied\n");
817 else {
818 reg = snd_soc_read(codec, WM8940_OUTPUTCTL);
819 ret = snd_soc_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
820 if (ret < 0)
821 return ret;
822 }
823
824
825 wm8940_codec = codec;
826
827 ret = snd_soc_register_codec(codec);
828 if (ret) {
829 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
830 return ret;
831 }
832
833 ret = snd_soc_register_dai(&wm8940_dai);
834 if (ret) {
835 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
836 snd_soc_unregister_codec(codec);
837 return ret;
838 }
839
840 return 0;
841}
842
843static void wm8940_unregister(struct wm8940_priv *wm8940)
844{
845 wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
846 snd_soc_unregister_dai(&wm8940_dai);
847 snd_soc_unregister_codec(&wm8940->codec);
848 kfree(wm8940);
849 wm8940_codec = NULL;
850}
851
852static int wm8940_i2c_probe(struct i2c_client *i2c,
853 const struct i2c_device_id *id)
854{
855 struct wm8940_priv *wm8940;
856 struct snd_soc_codec *codec;
857
858 wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
859 if (wm8940 == NULL)
860 return -ENOMEM;
861
862 codec = &wm8940->codec;
863 codec->hw_write = (hw_write_t)i2c_master_send;
864 i2c_set_clientdata(i2c, wm8940);
865 codec->control_data = i2c;
866 codec->dev = &i2c->dev;
867
868 return wm8940_register(wm8940, SND_SOC_I2C);
869}
870
871static int __devexit wm8940_i2c_remove(struct i2c_client *client)
872{
873 struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
874
875 wm8940_unregister(wm8940);
876
877 return 0;
878}
879
880#ifdef CONFIG_PM
881static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
882{
883 return snd_soc_suspend_device(&client->dev);
884}
885
886static 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
895static const struct i2c_device_id wm8940_i2c_id[] = {
896 { "wm8940", 0 },
897 { }
898};
899MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
900
901static struct i2c_driver wm8940_i2c_driver = {
902 .driver = {
903 .name = "WM8940 I2C Codec",
904 .owner = THIS_MODULE,
905 },
906 .probe = wm8940_i2c_probe,
907 .remove = __devexit_p(wm8940_i2c_remove),
908 .suspend = wm8940_i2c_suspend,
909 .resume = wm8940_i2c_resume,
910 .id_table = wm8940_i2c_id,
911};
912
913static int __init wm8940_modinit(void)
914{
915 int ret;
916
917 ret = i2c_add_driver(&wm8940_i2c_driver);
918 if (ret)
919 printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
920 ret);
921 return ret;
922}
923module_init(wm8940_modinit);
924
925static void __exit wm8940_exit(void)
926{
927 i2c_del_driver(&wm8940_i2c_driver);
928}
929module_exit(wm8940_exit);
930
931MODULE_DESCRIPTION("ASoC WM8940 driver");
932MODULE_AUTHOR("Jonathan Cameron");
933MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h
new file mode 100644
index 000000000000..8410eed3ef84
--- /dev/null
+++ b/sound/soc/codecs/wm8940.h
@@ -0,0 +1,104 @@
1/*
2 * wm8940.h -- WM8940 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 _WM8940_H
10#define _WM8940_H
11
12struct wm8940_setup_data {
13 /* Vref to analogue output resistance */
14#define WM8940_VROI_1K 0
15#define WM8940_VROI_30K 1
16 unsigned int vroi:1;
17};
18extern struct snd_soc_dai wm8940_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8940;
20
21/* WM8940 register space */
22#define WM8940_SOFTRESET 0x00
23#define WM8940_POWER1 0x01
24#define WM8940_POWER2 0x02
25#define WM8940_POWER3 0x03
26#define WM8940_IFACE 0x04
27#define WM8940_COMPANDINGCTL 0x05
28#define WM8940_CLOCK 0x06
29#define WM8940_ADDCNTRL 0x07
30#define WM8940_GPIO 0x08
31#define WM8940_CTLINT 0x09
32#define WM8940_DAC 0x0A
33#define WM8940_DACVOL 0x0B
34
35#define WM8940_ADC 0x0E
36#define WM8940_ADCVOL 0x0F
37#define WM8940_NOTCH1 0x10
38#define WM8940_NOTCH2 0x11
39#define WM8940_NOTCH3 0x12
40#define WM8940_NOTCH4 0x13
41#define WM8940_NOTCH5 0x14
42#define WM8940_NOTCH6 0x15
43#define WM8940_NOTCH7 0x16
44#define WM8940_NOTCH8 0x17
45#define WM8940_DACLIM1 0x18
46#define WM8940_DACLIM2 0x19
47
48#define WM8940_ALC1 0x20
49#define WM8940_ALC2 0x21
50#define WM8940_ALC3 0x22
51#define WM8940_NOISEGATE 0x23
52#define WM8940_PLLN 0x24
53#define WM8940_PLLK1 0x25
54#define WM8940_PLLK2 0x26
55#define WM8940_PLLK3 0x27
56
57#define WM8940_ALC4 0x2A
58
59#define WM8940_INPUTCTL 0x2C
60#define WM8940_PGAGAIN 0x2D
61
62#define WM8940_ADCBOOST 0x2F
63
64#define WM8940_OUTPUTCTL 0x31
65#define WM8940_SPKMIX 0x32
66
67#define WM8940_SPKVOL 0x36
68
69#define WM8940_MONOMIX 0x38
70
71#define WM8940_CACHEREGNUM 0x57
72
73
74/* Clock divider Id's */
75#define WM8940_BCLKDIV 0
76#define WM8940_MCLKDIV 1
77#define WM8940_OPCLKDIV 2
78
79/* MCLK clock dividers */
80#define WM8940_MCLKDIV_1 0
81#define WM8940_MCLKDIV_1_5 1
82#define WM8940_MCLKDIV_2 2
83#define WM8940_MCLKDIV_3 3
84#define WM8940_MCLKDIV_4 4
85#define WM8940_MCLKDIV_6 5
86#define WM8940_MCLKDIV_8 6
87#define WM8940_MCLKDIV_12 7
88
89/* BCLK clock dividers */
90#define WM8940_BCLKDIV_1 0
91#define WM8940_BCLKDIV_2 1
92#define WM8940_BCLKDIV_4 2
93#define WM8940_BCLKDIV_8 3
94#define WM8940_BCLKDIV_16 4
95#define WM8940_BCLKDIV_32 5
96
97/* PLL Out Dividers */
98#define WM8940_OPCLKDIV_1 0
99#define WM8940_OPCLKDIV_2 1
100#define WM8940_OPCLKDIV_3 2
101#define WM8940_OPCLKDIV_4 3
102
103#endif /* _WM8940_H */
104
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
new file mode 100644
index 000000000000..f59703be61c8
--- /dev/null
+++ b/sound/soc/codecs/wm8960.c
@@ -0,0 +1,942 @@
1/*
2 * wm8960.c -- WM8960 ALSA SoC Audio driver
3 *
4 * Author: Liam Girdwood
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#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/init.h>
14#include <linux/delay.h>
15#include <linux/pm.h>
16#include <linux/i2c.h>
17#include <linux/platform_device.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/initval.h>
24#include <sound/tlv.h>
25
26#include "wm8960.h"
27
28#define AUDIO_NAME "wm8960"
29
30struct snd_soc_codec_device soc_codec_dev_wm8960;
31
32/* R25 - Power 1 */
33#define WM8960_VREF 0x40
34
35/* R28 - Anti-pop 1 */
36#define WM8960_POBCTRL 0x80
37#define WM8960_BUFDCOPEN 0x10
38#define WM8960_BUFIOEN 0x08
39#define WM8960_SOFT_ST 0x04
40#define WM8960_HPSTBY 0x01
41
42/* R29 - Anti-pop 2 */
43#define WM8960_DISOP 0x40
44
45/*
46 * wm8960 register cache
47 * We can't read the WM8960 register space when we are
48 * using 2 wire for device control, so we cache them instead.
49 */
50static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
51 0x0097, 0x0097, 0x0000, 0x0000,
52 0x0000, 0x0008, 0x0000, 0x000a,
53 0x01c0, 0x0000, 0x00ff, 0x00ff,
54 0x0000, 0x0000, 0x0000, 0x0000,
55 0x0000, 0x007b, 0x0100, 0x0032,
56 0x0000, 0x00c3, 0x00c3, 0x01c0,
57 0x0000, 0x0000, 0x0000, 0x0000,
58 0x0000, 0x0000, 0x0000, 0x0000,
59 0x0100, 0x0100, 0x0050, 0x0050,
60 0x0050, 0x0050, 0x0000, 0x0000,
61 0x0000, 0x0000, 0x0040, 0x0000,
62 0x0000, 0x0050, 0x0050, 0x0000,
63 0x0002, 0x0037, 0x004d, 0x0080,
64 0x0008, 0x0031, 0x0026, 0x00e9,
65};
66
67struct wm8960_priv {
68 u16 reg_cache[WM8960_CACHEREGNUM];
69 struct snd_soc_codec codec;
70};
71
72#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
73
74/* enumerated controls */
75static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
76static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
77 "Right Inverted", "Stereo Inversion"};
78static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
79static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
80static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
81static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
82
83static const struct soc_enum wm8960_enum[] = {
84 SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph),
85 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
86 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
87 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
88 SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
89 SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
90 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
91};
92
93static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
94static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
95static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
96static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
97
98static const struct snd_kcontrol_new wm8960_snd_controls[] = {
99SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
100 0, 63, 0, adc_tlv),
101SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
102 6, 1, 0),
103SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
104 7, 1, 0),
105
106SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
107 0, 255, 0, dac_tlv),
108
109SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1,
110 0, 127, 0, out_tlv),
111SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1,
112 7, 1, 0),
113
114SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2,
115 0, 127, 0, out_tlv),
116SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2,
117 7, 1, 0),
118SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),
119SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),
120
121SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
122SOC_ENUM("ADC Polarity", wm8960_enum[1]),
123SOC_ENUM("Playback De-emphasis", wm8960_enum[0]),
124SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
125
126SOC_ENUM("DAC Polarity", wm8960_enum[2]),
127
128SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]),
129SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]),
130SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),
131SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),
132
133SOC_ENUM("ALC Function", wm8960_enum[5]),
134SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),
135SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),
136SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),
137SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),
138SOC_ENUM("ALC Mode", wm8960_enum[6]),
139SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),
140SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
141
142SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),
143SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),
144
145SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH,
146 0, 127, 0),
147
148SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
149 WM8960_BYPASS1, 4, 7, 1, bypass_tlv),
150SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",
151 WM8960_LOUTMIX, 4, 7, 1, bypass_tlv),
152SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
153 WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
154SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
155 WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
156};
157
158static const struct snd_kcontrol_new wm8960_lin_boost[] = {
159SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0),
160SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0),
161SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0),
162};
163
164static const struct snd_kcontrol_new wm8960_lin[] = {
165SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),
166};
167
168static const struct snd_kcontrol_new wm8960_rin_boost[] = {
169SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0),
170SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0),
171SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0),
172};
173
174static const struct snd_kcontrol_new wm8960_rin[] = {
175SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),
176};
177
178static const struct snd_kcontrol_new wm8960_loutput_mixer[] = {
179SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0),
180SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0),
181SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),
182};
183
184static const struct snd_kcontrol_new wm8960_routput_mixer[] = {
185SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0),
186SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0),
187SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),
188};
189
190static const struct snd_kcontrol_new wm8960_mono_out[] = {
191SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0),
192SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0),
193};
194
195static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = {
196SND_SOC_DAPM_INPUT("LINPUT1"),
197SND_SOC_DAPM_INPUT("RINPUT1"),
198SND_SOC_DAPM_INPUT("LINPUT2"),
199SND_SOC_DAPM_INPUT("RINPUT2"),
200SND_SOC_DAPM_INPUT("LINPUT3"),
201SND_SOC_DAPM_INPUT("RINPUT3"),
202
203SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
204
205SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
206 wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
207SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,
208 wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)),
209
210SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,
211 wm8960_lin, ARRAY_SIZE(wm8960_lin)),
212SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,
213 wm8960_rin, ARRAY_SIZE(wm8960_rin)),
214
215SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0),
216SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0),
217
218SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),
219SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),
220
221SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0,
222 &wm8960_loutput_mixer[0],
223 ARRAY_SIZE(wm8960_loutput_mixer)),
224SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
225 &wm8960_routput_mixer[0],
226 ARRAY_SIZE(wm8960_routput_mixer)),
227
228SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
229 &wm8960_mono_out[0],
230 ARRAY_SIZE(wm8960_mono_out)),
231
232SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
233SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
234
235SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0),
236SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0),
237
238SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0),
239SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0),
240
241SND_SOC_DAPM_OUTPUT("SPK_LP"),
242SND_SOC_DAPM_OUTPUT("SPK_LN"),
243SND_SOC_DAPM_OUTPUT("HP_L"),
244SND_SOC_DAPM_OUTPUT("HP_R"),
245SND_SOC_DAPM_OUTPUT("SPK_RP"),
246SND_SOC_DAPM_OUTPUT("SPK_RN"),
247SND_SOC_DAPM_OUTPUT("OUT3"),
248};
249
250static const struct snd_soc_dapm_route audio_paths[] = {
251 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
252 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
253 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
254
255 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
256 { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
257 { "Left Input Mixer", NULL, "LINPUT2" },
258 { "Left Input Mixer", NULL, "LINPUT3" },
259
260 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
261 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
262 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
263
264 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
265 { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
266 { "Right Input Mixer", NULL, "RINPUT2" },
267 { "Right Input Mixer", NULL, "LINPUT3" },
268
269 { "Left ADC", NULL, "Left Input Mixer" },
270 { "Right ADC", NULL, "Right Input Mixer" },
271
272 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
273 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
274 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
275
276 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
277 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
278 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
279
280 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
281 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
282
283 { "LOUT1 PGA", NULL, "Left Output Mixer" },
284 { "ROUT1 PGA", NULL, "Right Output Mixer" },
285
286 { "HP_L", NULL, "LOUT1 PGA" },
287 { "HP_R", NULL, "ROUT1 PGA" },
288
289 { "Left Speaker PGA", NULL, "Left Output Mixer" },
290 { "Right Speaker PGA", NULL, "Right Output Mixer" },
291
292 { "Left Speaker Output", NULL, "Left Speaker PGA" },
293 { "Right Speaker Output", NULL, "Right Speaker PGA" },
294
295 { "SPK_LN", NULL, "Left Speaker Output" },
296 { "SPK_LP", NULL, "Left Speaker Output" },
297 { "SPK_RN", NULL, "Right Speaker Output" },
298 { "SPK_RP", NULL, "Right Speaker Output" },
299
300 { "OUT3", NULL, "Mono Output Mixer", }
301};
302
303static int wm8960_add_widgets(struct snd_soc_codec *codec)
304{
305 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
306 ARRAY_SIZE(wm8960_dapm_widgets));
307
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309
310 snd_soc_dapm_new_widgets(codec);
311 return 0;
312}
313
314static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
315 unsigned int fmt)
316{
317 struct snd_soc_codec *codec = codec_dai->codec;
318 u16 iface = 0;
319
320 /* set master/slave audio interface */
321 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
322 case SND_SOC_DAIFMT_CBM_CFM:
323 iface |= 0x0040;
324 break;
325 case SND_SOC_DAIFMT_CBS_CFS:
326 break;
327 default:
328 return -EINVAL;
329 }
330
331 /* interface format */
332 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
333 case SND_SOC_DAIFMT_I2S:
334 iface |= 0x0002;
335 break;
336 case SND_SOC_DAIFMT_RIGHT_J:
337 break;
338 case SND_SOC_DAIFMT_LEFT_J:
339 iface |= 0x0001;
340 break;
341 case SND_SOC_DAIFMT_DSP_A:
342 iface |= 0x0003;
343 break;
344 case SND_SOC_DAIFMT_DSP_B:
345 iface |= 0x0013;
346 break;
347 default:
348 return -EINVAL;
349 }
350
351 /* clock inversion */
352 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
353 case SND_SOC_DAIFMT_NB_NF:
354 break;
355 case SND_SOC_DAIFMT_IB_IF:
356 iface |= 0x0090;
357 break;
358 case SND_SOC_DAIFMT_IB_NF:
359 iface |= 0x0080;
360 break;
361 case SND_SOC_DAIFMT_NB_IF:
362 iface |= 0x0010;
363 break;
364 default:
365 return -EINVAL;
366 }
367
368 /* set iface */
369 snd_soc_write(codec, WM8960_IFACE1, iface);
370 return 0;
371}
372
373static int wm8960_hw_params(struct snd_pcm_substream *substream,
374 struct snd_pcm_hw_params *params,
375 struct snd_soc_dai *dai)
376{
377 struct snd_soc_pcm_runtime *rtd = substream->private_data;
378 struct snd_soc_device *socdev = rtd->socdev;
379 struct snd_soc_codec *codec = socdev->card->codec;
380 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
381
382 /* bit size */
383 switch (params_format(params)) {
384 case SNDRV_PCM_FORMAT_S16_LE:
385 break;
386 case SNDRV_PCM_FORMAT_S20_3LE:
387 iface |= 0x0004;
388 break;
389 case SNDRV_PCM_FORMAT_S24_LE:
390 iface |= 0x0008;
391 break;
392 }
393
394 /* set iface */
395 snd_soc_write(codec, WM8960_IFACE1, iface);
396 return 0;
397}
398
399static int wm8960_mute(struct snd_soc_dai *dai, int mute)
400{
401 struct snd_soc_codec *codec = dai->codec;
402 u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
403
404 if (mute)
405 snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
406 else
407 snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
408 return 0;
409}
410
411static int wm8960_set_bias_level(struct snd_soc_codec *codec,
412 enum snd_soc_bias_level level)
413{
414 struct wm8960_data *pdata = codec->dev->platform_data;
415 u16 reg;
416
417 switch (level) {
418 case SND_SOC_BIAS_ON:
419 break;
420
421 case SND_SOC_BIAS_PREPARE:
422 /* Set VMID to 2x50k */
423 reg = snd_soc_read(codec, WM8960_POWER1);
424 reg &= ~0x180;
425 reg |= 0x80;
426 snd_soc_write(codec, WM8960_POWER1, reg);
427 break;
428
429 case SND_SOC_BIAS_STANDBY:
430 if (codec->bias_level == SND_SOC_BIAS_OFF) {
431 /* Enable anti-pop features */
432 snd_soc_write(codec, WM8960_APOP1,
433 WM8960_POBCTRL | WM8960_SOFT_ST |
434 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
435
436 /* Discharge HP output */
437 reg = WM8960_DISOP;
438 if (pdata)
439 reg |= pdata->dres << 4;
440 snd_soc_write(codec, WM8960_APOP2, reg);
441
442 msleep(400);
443
444 snd_soc_write(codec, WM8960_APOP2, 0);
445
446 /* Enable & ramp VMID at 2x50k */
447 reg = snd_soc_read(codec, WM8960_POWER1);
448 reg |= 0x80;
449 snd_soc_write(codec, WM8960_POWER1, reg);
450 msleep(100);
451
452 /* Enable VREF */
453 snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
454
455 /* Disable anti-pop features */
456 snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
457 }
458
459 /* Set VMID to 2x250k */
460 reg = snd_soc_read(codec, WM8960_POWER1);
461 reg &= ~0x180;
462 reg |= 0x100;
463 snd_soc_write(codec, WM8960_POWER1, reg);
464 break;
465
466 case SND_SOC_BIAS_OFF:
467 /* Enable anti-pop features */
468 snd_soc_write(codec, WM8960_APOP1,
469 WM8960_POBCTRL | WM8960_SOFT_ST |
470 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
471
472 /* Disable VMID and VREF, let them discharge */
473 snd_soc_write(codec, WM8960_POWER1, 0);
474 msleep(600);
475
476 snd_soc_write(codec, WM8960_APOP1, 0);
477 break;
478 }
479
480 codec->bias_level = level;
481
482 return 0;
483}
484
485/* PLL divisors */
486struct _pll_div {
487 u32 pre_div:1;
488 u32 n:4;
489 u32 k:24;
490};
491
492/* The size in bits of the pll divide multiplied by 10
493 * to allow rounding later */
494#define FIXED_PLL_SIZE ((1 << 24) * 10)
495
496static int pll_factors(unsigned int source, unsigned int target,
497 struct _pll_div *pll_div)
498{
499 unsigned long long Kpart;
500 unsigned int K, Ndiv, Nmod;
501
502 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target);
503
504 /* Scale up target to PLL operating frequency */
505 target *= 4;
506
507 Ndiv = target / source;
508 if (Ndiv < 6) {
509 source >>= 1;
510 pll_div->pre_div = 1;
511 Ndiv = target / source;
512 } else
513 pll_div->pre_div = 0;
514
515 if ((Ndiv < 6) || (Ndiv > 12)) {
516 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv);
517 return -EINVAL;
518 }
519
520 pll_div->n = Ndiv;
521 Nmod = target % source;
522 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
523
524 do_div(Kpart, source);
525
526 K = Kpart & 0xFFFFFFFF;
527
528 /* Check if we need to round */
529 if ((K % 10) >= 5)
530 K += 5;
531
532 /* Move down to proper range now rounding is done */
533 K /= 10;
534
535 pll_div->k = K;
536
537 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",
538 pll_div->n, pll_div->k, pll_div->pre_div);
539
540 return 0;
541}
542
543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
544 int pll_id, unsigned int freq_in, unsigned int freq_out)
545{
546 struct snd_soc_codec *codec = codec_dai->codec;
547 u16 reg;
548 static struct _pll_div pll_div;
549 int ret;
550
551 if (freq_in && freq_out) {
552 ret = pll_factors(freq_in, freq_out, &pll_div);
553 if (ret != 0)
554 return ret;
555 }
556
557 /* Disable the PLL: even if we are changing the frequency the
558 * PLL needs to be disabled while we do so. */
559 snd_soc_write(codec, WM8960_CLOCK1,
560 snd_soc_read(codec, WM8960_CLOCK1) & ~1);
561 snd_soc_write(codec, WM8960_POWER2,
562 snd_soc_read(codec, WM8960_POWER2) & ~1);
563
564 if (!freq_in || !freq_out)
565 return 0;
566
567 reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f;
568 reg |= pll_div.pre_div << 4;
569 reg |= pll_div.n;
570
571 if (pll_div.k) {
572 reg |= 0x20;
573
574 snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
575 snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
576 snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
577 }
578 snd_soc_write(codec, WM8960_PLL1, reg);
579
580 /* Turn it on */
581 snd_soc_write(codec, WM8960_POWER2,
582 snd_soc_read(codec, WM8960_POWER2) | 1);
583 msleep(250);
584 snd_soc_write(codec, WM8960_CLOCK1,
585 snd_soc_read(codec, WM8960_CLOCK1) | 1);
586
587 return 0;
588}
589
590static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
591 int div_id, int div)
592{
593 struct snd_soc_codec *codec = codec_dai->codec;
594 u16 reg;
595
596 switch (div_id) {
597 case WM8960_SYSCLKSEL:
598 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe;
599 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
600 break;
601 case WM8960_SYSCLKDIV:
602 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9;
603 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
604 break;
605 case WM8960_DACDIV:
606 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7;
607 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
608 break;
609 case WM8960_OPCLKDIV:
610 reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f;
611 snd_soc_write(codec, WM8960_PLL1, reg | div);
612 break;
613 case WM8960_DCLKDIV:
614 reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f;
615 snd_soc_write(codec, WM8960_CLOCK2, reg | div);
616 break;
617 case WM8960_TOCLKSEL:
618 reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd;
619 snd_soc_write(codec, WM8960_ADDCTL1, reg | div);
620 break;
621 default:
622 return -EINVAL;
623 }
624
625 return 0;
626}
627
628#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
629
630#define WM8960_FORMATS \
631 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
632 SNDRV_PCM_FMTBIT_S24_LE)
633
634static struct snd_soc_dai_ops wm8960_dai_ops = {
635 .hw_params = wm8960_hw_params,
636 .digital_mute = wm8960_mute,
637 .set_fmt = wm8960_set_dai_fmt,
638 .set_clkdiv = wm8960_set_dai_clkdiv,
639 .set_pll = wm8960_set_dai_pll,
640};
641
642struct snd_soc_dai wm8960_dai = {
643 .name = "WM8960",
644 .playback = {
645 .stream_name = "Playback",
646 .channels_min = 1,
647 .channels_max = 2,
648 .rates = WM8960_RATES,
649 .formats = WM8960_FORMATS,},
650 .capture = {
651 .stream_name = "Capture",
652 .channels_min = 1,
653 .channels_max = 2,
654 .rates = WM8960_RATES,
655 .formats = WM8960_FORMATS,},
656 .ops = &wm8960_dai_ops,
657 .symmetric_rates = 1,
658};
659EXPORT_SYMBOL_GPL(wm8960_dai);
660
661static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
662{
663 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
664 struct snd_soc_codec *codec = socdev->card->codec;
665
666 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF);
667 return 0;
668}
669
670static int wm8960_resume(struct platform_device *pdev)
671{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
673 struct snd_soc_codec *codec = socdev->card->codec;
674 int i;
675 u8 data[2];
676 u16 *cache = codec->reg_cache;
677
678 /* Sync reg_cache with the hardware */
679 for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
680 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
681 data[1] = cache[i] & 0x00ff;
682 codec->hw_write(codec->control_data, data, 2);
683 }
684
685 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
686 wm8960_set_bias_level(codec, codec->suspend_bias_level);
687 return 0;
688}
689
690static struct snd_soc_codec *wm8960_codec;
691
692static int wm8960_probe(struct platform_device *pdev)
693{
694 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
695 struct snd_soc_codec *codec;
696 int ret = 0;
697
698 if (wm8960_codec == NULL) {
699 dev_err(&pdev->dev, "Codec device not registered\n");
700 return -ENODEV;
701 }
702
703 socdev->card->codec = wm8960_codec;
704 codec = wm8960_codec;
705
706 /* register pcms */
707 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
708 if (ret < 0) {
709 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
710 goto pcm_err;
711 }
712
713 snd_soc_add_controls(codec, wm8960_snd_controls,
714 ARRAY_SIZE(wm8960_snd_controls));
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
722 return ret;
723
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err:
728 return ret;
729}
730
731/* power down chip */
732static int wm8960_remove(struct platform_device *pdev)
733{
734 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
735
736 snd_soc_free_pcms(socdev);
737 snd_soc_dapm_free(socdev);
738
739 return 0;
740}
741
742struct snd_soc_codec_device soc_codec_dev_wm8960 = {
743 .probe = wm8960_probe,
744 .remove = wm8960_remove,
745 .suspend = wm8960_suspend,
746 .resume = wm8960_resume,
747};
748EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
749
750static int wm8960_register(struct wm8960_priv *wm8960,
751 enum snd_soc_control_type control)
752{
753 struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
754 struct snd_soc_codec *codec = &wm8960->codec;
755 int ret;
756 u16 reg;
757
758 if (wm8960_codec) {
759 dev_err(codec->dev, "Another WM8960 is registered\n");
760 ret = -EINVAL;
761 goto err;
762 }
763
764 if (!pdata) {
765 dev_warn(codec->dev, "No platform data supplied\n");
766 } else {
767 if (pdata->dres > WM8960_DRES_MAX) {
768 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
769 pdata->dres = 0;
770 }
771 }
772
773 mutex_init(&codec->mutex);
774 INIT_LIST_HEAD(&codec->dapm_widgets);
775 INIT_LIST_HEAD(&codec->dapm_paths);
776
777 codec->private_data = wm8960;
778 codec->name = "WM8960";
779 codec->owner = THIS_MODULE;
780 codec->bias_level = SND_SOC_BIAS_OFF;
781 codec->set_bias_level = wm8960_set_bias_level;
782 codec->dai = &wm8960_dai;
783 codec->num_dai = 1;
784 codec->reg_cache_size = WM8960_CACHEREGNUM;
785 codec->reg_cache = &wm8960->reg_cache;
786
787 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
788
789 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
790 if (ret < 0) {
791 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
792 goto err;
793 }
794
795 ret = wm8960_reset(codec);
796 if (ret < 0) {
797 dev_err(codec->dev, "Failed to issue reset\n");
798 goto err;
799 }
800
801 wm8960_dai.dev = codec->dev;
802
803 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
804
805 /* Latch the update bits */
806 reg = snd_soc_read(codec, WM8960_LINVOL);
807 snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
808 reg = snd_soc_read(codec, WM8960_RINVOL);
809 snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
810 reg = snd_soc_read(codec, WM8960_LADC);
811 snd_soc_write(codec, WM8960_LADC, reg | 0x100);
812 reg = snd_soc_read(codec, WM8960_RADC);
813 snd_soc_write(codec, WM8960_RADC, reg | 0x100);
814 reg = snd_soc_read(codec, WM8960_LDAC);
815 snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
816 reg = snd_soc_read(codec, WM8960_RDAC);
817 snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
818 reg = snd_soc_read(codec, WM8960_LOUT1);
819 snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
820 reg = snd_soc_read(codec, WM8960_ROUT1);
821 snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
822 reg = snd_soc_read(codec, WM8960_LOUT2);
823 snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
824 reg = snd_soc_read(codec, WM8960_ROUT2);
825 snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
826
827 wm8960_codec = codec;
828
829 ret = snd_soc_register_codec(codec);
830 if (ret != 0) {
831 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
832 goto err;
833 }
834
835 ret = snd_soc_register_dai(&wm8960_dai);
836 if (ret != 0) {
837 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
838 goto err_codec;
839 }
840
841 return 0;
842
843err_codec:
844 snd_soc_unregister_codec(codec);
845err:
846 kfree(wm8960);
847 return ret;
848}
849
850static void wm8960_unregister(struct wm8960_priv *wm8960)
851{
852 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
853 snd_soc_unregister_dai(&wm8960_dai);
854 snd_soc_unregister_codec(&wm8960->codec);
855 kfree(wm8960);
856 wm8960_codec = NULL;
857}
858
859static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
860 const struct i2c_device_id *id)
861{
862 struct wm8960_priv *wm8960;
863 struct snd_soc_codec *codec;
864
865 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
866 if (wm8960 == NULL)
867 return -ENOMEM;
868
869 codec = &wm8960->codec;
870
871 i2c_set_clientdata(i2c, wm8960);
872 codec->control_data = i2c;
873
874 codec->dev = &i2c->dev;
875
876 return wm8960_register(wm8960, SND_SOC_I2C);
877}
878
879static __devexit int wm8960_i2c_remove(struct i2c_client *client)
880{
881 struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
882 wm8960_unregister(wm8960);
883 return 0;
884}
885
886#ifdef CONFIG_PM
887static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
888{
889 return snd_soc_suspend_device(&client->dev);
890}
891
892static 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
901static const struct i2c_device_id wm8960_i2c_id[] = {
902 { "wm8960", 0 },
903 { }
904};
905MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
906
907static struct i2c_driver wm8960_i2c_driver = {
908 .driver = {
909 .name = "WM8960 I2C Codec",
910 .owner = THIS_MODULE,
911 },
912 .probe = wm8960_i2c_probe,
913 .remove = __devexit_p(wm8960_i2c_remove),
914 .suspend = wm8960_i2c_suspend,
915 .resume = wm8960_i2c_resume,
916 .id_table = wm8960_i2c_id,
917};
918
919static int __init wm8960_modinit(void)
920{
921 int ret;
922
923 ret = i2c_add_driver(&wm8960_i2c_driver);
924 if (ret != 0) {
925 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
926 ret);
927 }
928
929 return ret;
930}
931module_init(wm8960_modinit);
932
933static void __exit wm8960_exit(void)
934{
935 i2c_del_driver(&wm8960_i2c_driver);
936}
937module_exit(wm8960_exit);
938
939
940MODULE_DESCRIPTION("ASoC WM8960 driver");
941MODULE_AUTHOR("Liam Girdwood");
942MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
new file mode 100644
index 000000000000..c9af56c9d9d4
--- /dev/null
+++ b/sound/soc/codecs/wm8960.h
@@ -0,0 +1,127 @@
1/*
2 * wm8960.h -- WM8960 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 _WM8960_H
10#define _WM8960_H
11
12/* WM8960 register space */
13
14
15#define WM8960_CACHEREGNUM 56
16
17#define WM8960_LINVOL 0x0
18#define WM8960_RINVOL 0x1
19#define WM8960_LOUT1 0x2
20#define WM8960_ROUT1 0x3
21#define WM8960_CLOCK1 0x4
22#define WM8960_DACCTL1 0x5
23#define WM8960_DACCTL2 0x6
24#define WM8960_IFACE1 0x7
25#define WM8960_CLOCK2 0x8
26#define WM8960_IFACE2 0x9
27#define WM8960_LDAC 0xa
28#define WM8960_RDAC 0xb
29
30#define WM8960_RESET 0xf
31#define WM8960_3D 0x10
32#define WM8960_ALC1 0x11
33#define WM8960_ALC2 0x12
34#define WM8960_ALC3 0x13
35#define WM8960_NOISEG 0x14
36#define WM8960_LADC 0x15
37#define WM8960_RADC 0x16
38#define WM8960_ADDCTL1 0x17
39#define WM8960_ADDCTL2 0x18
40#define WM8960_POWER1 0x19
41#define WM8960_POWER2 0x1a
42#define WM8960_ADDCTL3 0x1b
43#define WM8960_APOP1 0x1c
44#define WM8960_APOP2 0x1d
45
46#define WM8960_LINPATH 0x20
47#define WM8960_RINPATH 0x21
48#define WM8960_LOUTMIX 0x22
49
50#define WM8960_ROUTMIX 0x25
51#define WM8960_MONOMIX1 0x26
52#define WM8960_MONOMIX2 0x27
53#define WM8960_LOUT2 0x28
54#define WM8960_ROUT2 0x29
55#define WM8960_MONO 0x2a
56#define WM8960_INBMIX1 0x2b
57#define WM8960_INBMIX2 0x2c
58#define WM8960_BYPASS1 0x2d
59#define WM8960_BYPASS2 0x2e
60#define WM8960_POWER3 0x2f
61#define WM8960_ADDCTL4 0x30
62#define WM8960_CLASSD1 0x31
63
64#define WM8960_CLASSD3 0x33
65#define WM8960_PLL1 0x34
66#define WM8960_PLL2 0x35
67#define WM8960_PLL3 0x36
68#define WM8960_PLL4 0x37
69
70
71/*
72 * WM8960 Clock dividers
73 */
74#define WM8960_SYSCLKDIV 0
75#define WM8960_DACDIV 1
76#define WM8960_OPCLKDIV 2
77#define WM8960_DCLKDIV 3
78#define WM8960_TOCLKSEL 4
79#define WM8960_SYSCLKSEL 5
80
81#define WM8960_SYSCLK_DIV_1 (0 << 1)
82#define WM8960_SYSCLK_DIV_2 (2 << 1)
83
84#define WM8960_SYSCLK_MCLK (0 << 0)
85#define WM8960_SYSCLK_PLL (1 << 0)
86
87#define WM8960_DAC_DIV_1 (0 << 3)
88#define WM8960_DAC_DIV_1_5 (1 << 3)
89#define WM8960_DAC_DIV_2 (2 << 3)
90#define WM8960_DAC_DIV_3 (3 << 3)
91#define WM8960_DAC_DIV_4 (4 << 3)
92#define WM8960_DAC_DIV_5_5 (5 << 3)
93#define WM8960_DAC_DIV_6 (6 << 3)
94
95#define WM8960_DCLK_DIV_1_5 (0 << 6)
96#define WM8960_DCLK_DIV_2 (1 << 6)
97#define WM8960_DCLK_DIV_3 (2 << 6)
98#define WM8960_DCLK_DIV_4 (3 << 6)
99#define WM8960_DCLK_DIV_6 (4 << 6)
100#define WM8960_DCLK_DIV_8 (5 << 6)
101#define WM8960_DCLK_DIV_12 (6 << 6)
102#define WM8960_DCLK_DIV_16 (7 << 6)
103
104#define WM8960_TOCLK_F19 (0 << 1)
105#define WM8960_TOCLK_F21 (1 << 1)
106
107#define WM8960_OPCLK_DIV_1 (0 << 0)
108#define WM8960_OPCLK_DIV_2 (1 << 0)
109#define WM8960_OPCLK_DIV_3 (2 << 0)
110#define WM8960_OPCLK_DIV_4 (3 << 0)
111#define WM8960_OPCLK_DIV_5_5 (4 << 0)
112#define WM8960_OPCLK_DIV_6 (5 << 0)
113
114extern struct snd_soc_dai wm8960_dai;
115extern struct snd_soc_codec_device soc_codec_dev_wm8960;
116
117#define WM8960_DRES_400R 0
118#define WM8960_DRES_200R 1
119#define WM8960_DRES_600R 2
120#define WM8960_DRES_150R 3
121#define WM8960_DRES_MAX 3
122
123struct wm8960_data {
124 int dres;
125};
126
127#endif
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
new file mode 100644
index 000000000000..503032085899
--- /dev/null
+++ b/sound/soc/codecs/wm8961.c
@@ -0,0 +1,1265 @@
1/*
2 * wm8961.c -- WM8961 ALSA SoC Audio driver
3 *
4 * Author: Mark Brown
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 * Currently unimplemented features:
11 * - ALC
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 <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include "wm8961.h"
30
31#define WM8961_MAX_REGISTER 0xFC
32
33static u16 wm8961_reg_defaults[] = {
34 0x009F, /* R0 - Left Input volume */
35 0x009F, /* R1 - Right Input volume */
36 0x0000, /* R2 - LOUT1 volume */
37 0x0000, /* R3 - ROUT1 volume */
38 0x0020, /* R4 - Clocking1 */
39 0x0008, /* R5 - ADC & DAC Control 1 */
40 0x0000, /* R6 - ADC & DAC Control 2 */
41 0x000A, /* R7 - Audio Interface 0 */
42 0x01F4, /* R8 - Clocking2 */
43 0x0000, /* R9 - Audio Interface 1 */
44 0x00FF, /* R10 - Left DAC volume */
45 0x00FF, /* R11 - Right DAC volume */
46 0x0000, /* R12 */
47 0x0000, /* R13 */
48 0x0040, /* R14 - Audio Interface 2 */
49 0x0000, /* R15 - Software Reset */
50 0x0000, /* R16 */
51 0x007B, /* R17 - ALC1 */
52 0x0000, /* R18 - ALC2 */
53 0x0032, /* R19 - ALC3 */
54 0x0000, /* R20 - Noise Gate */
55 0x00C0, /* R21 - Left ADC volume */
56 0x00C0, /* R22 - Right ADC volume */
57 0x0120, /* R23 - Additional control(1) */
58 0x0000, /* R24 - Additional control(2) */
59 0x0000, /* R25 - Pwr Mgmt (1) */
60 0x0000, /* R26 - Pwr Mgmt (2) */
61 0x0000, /* R27 - Additional Control (3) */
62 0x0000, /* R28 - Anti-pop */
63 0x0000, /* R29 */
64 0x005F, /* R30 - Clocking 3 */
65 0x0000, /* R31 */
66 0x0000, /* R32 - ADCL signal path */
67 0x0000, /* R33 - ADCR signal path */
68 0x0000, /* R34 */
69 0x0000, /* R35 */
70 0x0000, /* R36 */
71 0x0000, /* R37 */
72 0x0000, /* R38 */
73 0x0000, /* R39 */
74 0x0000, /* R40 - LOUT2 volume */
75 0x0000, /* R41 - ROUT2 volume */
76 0x0000, /* R42 */
77 0x0000, /* R43 */
78 0x0000, /* R44 */
79 0x0000, /* R45 */
80 0x0000, /* R46 */
81 0x0000, /* R47 - Pwr Mgmt (3) */
82 0x0023, /* R48 - Additional Control (4) */
83 0x0000, /* R49 - Class D Control 1 */
84 0x0000, /* R50 */
85 0x0003, /* R51 - Class D Control 2 */
86 0x0000, /* R52 */
87 0x0000, /* R53 */
88 0x0000, /* R54 */
89 0x0000, /* R55 */
90 0x0106, /* R56 - Clocking 4 */
91 0x0000, /* R57 - DSP Sidetone 0 */
92 0x0000, /* R58 - DSP Sidetone 1 */
93 0x0000, /* R59 */
94 0x0000, /* R60 - DC Servo 0 */
95 0x0000, /* R61 - DC Servo 1 */
96 0x0000, /* R62 */
97 0x015E, /* R63 - DC Servo 3 */
98 0x0010, /* R64 */
99 0x0010, /* R65 - DC Servo 5 */
100 0x0000, /* R66 */
101 0x0001, /* R67 */
102 0x0003, /* R68 - Analogue PGA Bias */
103 0x0000, /* R69 - Analogue HP 0 */
104 0x0060, /* R70 */
105 0x01FB, /* R71 - Analogue HP 2 */
106 0x0000, /* R72 - Charge Pump 1 */
107 0x0065, /* R73 */
108 0x005F, /* R74 */
109 0x0059, /* R75 */
110 0x006B, /* R76 */
111 0x0038, /* R77 */
112 0x000C, /* R78 */
113 0x000A, /* R79 */
114 0x006B, /* R80 */
115 0x0000, /* R81 */
116 0x0000, /* R82 - Charge Pump B */
117 0x0087, /* R83 */
118 0x0000, /* R84 */
119 0x005C, /* R85 */
120 0x0000, /* R86 */
121 0x0000, /* R87 - Write Sequencer 1 */
122 0x0000, /* R88 - Write Sequencer 2 */
123 0x0000, /* R89 - Write Sequencer 3 */
124 0x0000, /* R90 - Write Sequencer 4 */
125 0x0000, /* R91 - Write Sequencer 5 */
126 0x0000, /* R92 - Write Sequencer 6 */
127 0x0000, /* R93 - Write Sequencer 7 */
128 0x0000, /* R94 */
129 0x0000, /* R95 */
130 0x0000, /* R96 */
131 0x0000, /* R97 */
132 0x0000, /* R98 */
133 0x0000, /* R99 */
134 0x0000, /* R100 */
135 0x0000, /* R101 */
136 0x0000, /* R102 */
137 0x0000, /* R103 */
138 0x0000, /* R104 */
139 0x0000, /* R105 */
140 0x0000, /* R106 */
141 0x0000, /* R107 */
142 0x0000, /* R108 */
143 0x0000, /* R109 */
144 0x0000, /* R110 */
145 0x0000, /* R111 */
146 0x0000, /* R112 */
147 0x0000, /* R113 */
148 0x0000, /* R114 */
149 0x0000, /* R115 */
150 0x0000, /* R116 */
151 0x0000, /* R117 */
152 0x0000, /* R118 */
153 0x0000, /* R119 */
154 0x0000, /* R120 */
155 0x0000, /* R121 */
156 0x0000, /* R122 */
157 0x0000, /* R123 */
158 0x0000, /* R124 */
159 0x0000, /* R125 */
160 0x0000, /* R126 */
161 0x0000, /* R127 */
162 0x0000, /* R128 */
163 0x0000, /* R129 */
164 0x0000, /* R130 */
165 0x0000, /* R131 */
166 0x0000, /* R132 */
167 0x0000, /* R133 */
168 0x0000, /* R134 */
169 0x0000, /* R135 */
170 0x0000, /* R136 */
171 0x0000, /* R137 */
172 0x0000, /* R138 */
173 0x0000, /* R139 */
174 0x0000, /* R140 */
175 0x0000, /* R141 */
176 0x0000, /* R142 */
177 0x0000, /* R143 */
178 0x0000, /* R144 */
179 0x0000, /* R145 */
180 0x0000, /* R146 */
181 0x0000, /* R147 */
182 0x0000, /* R148 */
183 0x0000, /* R149 */
184 0x0000, /* R150 */
185 0x0000, /* R151 */
186 0x0000, /* R152 */
187 0x0000, /* R153 */
188 0x0000, /* R154 */
189 0x0000, /* R155 */
190 0x0000, /* R156 */
191 0x0000, /* R157 */
192 0x0000, /* R158 */
193 0x0000, /* R159 */
194 0x0000, /* R160 */
195 0x0000, /* R161 */
196 0x0000, /* R162 */
197 0x0000, /* R163 */
198 0x0000, /* R164 */
199 0x0000, /* R165 */
200 0x0000, /* R166 */
201 0x0000, /* R167 */
202 0x0000, /* R168 */
203 0x0000, /* R169 */
204 0x0000, /* R170 */
205 0x0000, /* R171 */
206 0x0000, /* R172 */
207 0x0000, /* R173 */
208 0x0000, /* R174 */
209 0x0000, /* R175 */
210 0x0000, /* R176 */
211 0x0000, /* R177 */
212 0x0000, /* R178 */
213 0x0000, /* R179 */
214 0x0000, /* R180 */
215 0x0000, /* R181 */
216 0x0000, /* R182 */
217 0x0000, /* R183 */
218 0x0000, /* R184 */
219 0x0000, /* R185 */
220 0x0000, /* R186 */
221 0x0000, /* R187 */
222 0x0000, /* R188 */
223 0x0000, /* R189 */
224 0x0000, /* R190 */
225 0x0000, /* R191 */
226 0x0000, /* R192 */
227 0x0000, /* R193 */
228 0x0000, /* R194 */
229 0x0000, /* R195 */
230 0x0030, /* R196 */
231 0x0006, /* R197 */
232 0x0000, /* R198 */
233 0x0060, /* R199 */
234 0x0000, /* R200 */
235 0x003F, /* R201 */
236 0x0000, /* R202 */
237 0x0000, /* R203 */
238 0x0000, /* R204 */
239 0x0001, /* R205 */
240 0x0000, /* R206 */
241 0x0181, /* R207 */
242 0x0005, /* R208 */
243 0x0008, /* R209 */
244 0x0008, /* R210 */
245 0x0000, /* R211 */
246 0x013B, /* R212 */
247 0x0000, /* R213 */
248 0x0000, /* R214 */
249 0x0000, /* R215 */
250 0x0000, /* R216 */
251 0x0070, /* R217 */
252 0x0000, /* R218 */
253 0x0000, /* R219 */
254 0x0000, /* R220 */
255 0x0000, /* R221 */
256 0x0000, /* R222 */
257 0x0003, /* R223 */
258 0x0000, /* R224 */
259 0x0000, /* R225 */
260 0x0001, /* R226 */
261 0x0008, /* R227 */
262 0x0000, /* R228 */
263 0x0000, /* R229 */
264 0x0000, /* R230 */
265 0x0000, /* R231 */
266 0x0004, /* R232 */
267 0x0000, /* R233 */
268 0x0000, /* R234 */
269 0x0000, /* R235 */
270 0x0000, /* R236 */
271 0x0000, /* R237 */
272 0x0080, /* R238 */
273 0x0000, /* R239 */
274 0x0000, /* R240 */
275 0x0000, /* R241 */
276 0x0000, /* R242 */
277 0x0000, /* R243 */
278 0x0000, /* R244 */
279 0x0052, /* R245 */
280 0x0110, /* R246 */
281 0x0040, /* R247 */
282 0x0000, /* R248 */
283 0x0030, /* R249 */
284 0x0000, /* R250 */
285 0x0000, /* R251 */
286 0x0001, /* R252 - General test 1 */
287};
288
289struct wm8961_priv {
290 struct snd_soc_codec codec;
291 int sysclk;
292 u16 reg_cache[WM8961_MAX_REGISTER];
293};
294
295static int wm8961_volatile_register(unsigned int reg)
296{
297 switch (reg) {
298 case WM8961_SOFTWARE_RESET:
299 case WM8961_WRITE_SEQUENCER_7:
300 case WM8961_DC_SERVO_1:
301 return 1;
302
303 default:
304 return 0;
305 }
306}
307
308static int wm8961_reset(struct snd_soc_codec *codec)
309{
310 return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0);
311}
312
313/*
314 * The headphone output supports special anti-pop sequences giving
315 * silent power up and power down.
316 */
317static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
318 struct snd_kcontrol *kcontrol, int event)
319{
320 struct snd_soc_codec *codec = w->codec;
321 u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0);
322 u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1);
323 u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
324 u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
325 int timeout = 500;
326
327 if (event & SND_SOC_DAPM_POST_PMU) {
328 /* Make sure the output is shorted */
329 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
330 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
331
332 /* Enable the charge pump */
333 cp_reg |= WM8961_CP_ENA;
334 snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg);
335 mdelay(5);
336
337 /* Enable the PGA */
338 pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA;
339 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
340
341 /* Enable the amplifier */
342 hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA;
343 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
344
345 /* Second stage enable */
346 hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY;
347 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
348
349 /* Enable the DC servo & trigger startup */
350 dcs_reg |=
351 WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR |
352 WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL;
353 dev_dbg(codec->dev, "Enabling DC servo\n");
354
355 snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
356 do {
357 msleep(1);
358 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
359 } while (--timeout &&
360 dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
361 WM8961_DCS_TRIG_STARTUP_HPL));
362 if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
363 WM8961_DCS_TRIG_STARTUP_HPL))
364 dev_err(codec->dev, "DC servo timed out\n");
365 else
366 dev_dbg(codec->dev, "DC servo startup complete\n");
367
368 /* Enable the output stage */
369 hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP;
370 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
371
372 /* Remove the short on the output stage */
373 hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT;
374 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
375 }
376
377 if (event & SND_SOC_DAPM_PRE_PMD) {
378 /* Short the output */
379 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
380 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
381
382 /* Disable the output stage */
383 hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP);
384 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
385
386 /* Disable DC offset cancellation */
387 dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR |
388 WM8961_DCS_ENA_CHAN_HPL);
389 snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
390
391 /* Finish up */
392 hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA |
393 WM8961_HPL_ENA_DLY | WM8961_HPL_ENA);
394 snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
395
396 /* Disable the PGA */
397 pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA);
398 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
399
400 /* Disable the charge pump */
401 dev_dbg(codec->dev, "Disabling charge pump\n");
402 snd_soc_write(codec, WM8961_CHARGE_PUMP_1,
403 cp_reg & ~WM8961_CP_ENA);
404 }
405
406 return 0;
407}
408
409static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
410 struct snd_kcontrol *kcontrol, int event)
411{
412 struct snd_soc_codec *codec = w->codec;
413 u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
414 u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1);
415
416 if (event & SND_SOC_DAPM_POST_PMU) {
417 /* Enable the PGA */
418 pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA;
419 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
420
421 /* Enable the amplifier */
422 spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA;
423 snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
424 }
425
426 if (event & SND_SOC_DAPM_PRE_PMD) {
427 /* Enable the amplifier */
428 spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
429 snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
430
431 /* Enable the PGA */
432 pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
433 snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
434 }
435
436 return 0;
437}
438
439static const char *adc_hpf_text[] = {
440 "Hi-fi", "Voice 1", "Voice 2", "Voice 3",
441};
442
443static const struct soc_enum adc_hpf =
444 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text);
445
446static const char *dac_deemph_text[] = {
447 "None", "32kHz", "44.1kHz", "48kHz",
448};
449
450static const struct soc_enum dac_deemph =
451 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text);
452
453static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
454static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
455static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
456static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
457static unsigned int boost_tlv[] = {
458 TLV_DB_RANGE_HEAD(4),
459 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
460 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0),
461 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0),
462 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0),
463};
464static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0);
465
466static const struct snd_kcontrol_new wm8961_snd_controls[] = {
467SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
468 0, 127, 0, out_tlv),
469SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2,
470 6, 3, 7, 0, hp_sec_tlv),
471SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
472 7, 1, 0),
473
474SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
475 0, 127, 0, out_tlv),
476SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
477 7, 1, 0),
478SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0),
479
480SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0),
481SOC_ENUM("DAC Deemphasis", dac_deemph),
482SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0),
483
484SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0,
485 WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv),
486
487SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0),
488SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
489
490SOC_DOUBLE_R_TLV("Capture Volume",
491 WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME,
492 1, 119, 0, adc_tlv),
493SOC_DOUBLE_R_TLV("Capture Boost Volume",
494 WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH,
495 4, 3, 0, boost_tlv),
496SOC_DOUBLE_R_TLV("Capture PGA Volume",
497 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
498 0, 62, 0, pga_tlv),
499SOC_DOUBLE_R("Capture PGA ZC Switch",
500 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
501 6, 1, 1),
502SOC_DOUBLE_R("Capture PGA Switch",
503 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
504 7, 1, 1),
505};
506
507static const char *sidetone_text[] = {
508 "None", "Left", "Right"
509};
510
511static const struct soc_enum dacl_sidetone =
512 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text);
513
514static const struct soc_enum dacr_sidetone =
515 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text);
516
517static const struct snd_kcontrol_new dacl_mux =
518 SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone);
519
520static const struct snd_kcontrol_new dacr_mux =
521 SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone);
522
523static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = {
524SND_SOC_DAPM_INPUT("LINPUT"),
525SND_SOC_DAPM_INPUT("RINPUT"),
526
527SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0),
528
529SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0),
530SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
531
532SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
533SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
534
535SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
536
537SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
538SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
539
540SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0),
541SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0),
542
543/* Handle as a mono path for DCS */
544SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM,
545 4, 0, NULL, 0, wm8961_hp_event,
546 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
547SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM,
548 4, 0, NULL, 0, wm8961_spk_event,
549 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
550
551SND_SOC_DAPM_OUTPUT("HP_L"),
552SND_SOC_DAPM_OUTPUT("HP_R"),
553SND_SOC_DAPM_OUTPUT("SPK_LN"),
554SND_SOC_DAPM_OUTPUT("SPK_LP"),
555SND_SOC_DAPM_OUTPUT("SPK_RN"),
556SND_SOC_DAPM_OUTPUT("SPK_RP"),
557};
558
559
560static const struct snd_soc_dapm_route audio_paths[] = {
561 { "DACL", NULL, "CLK_DSP" },
562 { "DACL", NULL, "DACL Sidetone" },
563 { "DACR", NULL, "CLK_DSP" },
564 { "DACR", NULL, "DACR Sidetone" },
565
566 { "DACL Sidetone", "Left", "ADCL" },
567 { "DACL Sidetone", "Right", "ADCR" },
568
569 { "DACR Sidetone", "Left", "ADCL" },
570 { "DACR Sidetone", "Right", "ADCR" },
571
572 { "HP_L", NULL, "Headphone Output" },
573 { "HP_R", NULL, "Headphone Output" },
574 { "Headphone Output", NULL, "DACL" },
575 { "Headphone Output", NULL, "DACR" },
576
577 { "SPK_LN", NULL, "Speaker Output" },
578 { "SPK_LP", NULL, "Speaker Output" },
579 { "SPK_RN", NULL, "Speaker Output" },
580 { "SPK_RP", NULL, "Speaker Output" },
581
582 { "Speaker Output", NULL, "DACL" },
583 { "Speaker Output", NULL, "DACR" },
584
585 { "ADCL", NULL, "Left Input" },
586 { "ADCL", NULL, "CLK_DSP" },
587 { "ADCR", NULL, "Right Input" },
588 { "ADCR", NULL, "CLK_DSP" },
589
590 { "Left Input", NULL, "LINPUT" },
591 { "Right Input", NULL, "RINPUT" },
592
593};
594
595/* Values for CLK_SYS_RATE */
596static struct {
597 int ratio;
598 u16 val;
599} wm8961_clk_sys_ratio[] = {
600 { 64, 0 },
601 { 128, 1 },
602 { 192, 2 },
603 { 256, 3 },
604 { 384, 4 },
605 { 512, 5 },
606 { 768, 6 },
607 { 1024, 7 },
608 { 1408, 8 },
609 { 1536, 9 },
610};
611
612/* Values for SAMPLE_RATE */
613static struct {
614 int rate;
615 u16 val;
616} wm8961_srate[] = {
617 { 48000, 0 },
618 { 44100, 0 },
619 { 32000, 1 },
620 { 22050, 2 },
621 { 24000, 2 },
622 { 16000, 3 },
623 { 11250, 4 },
624 { 12000, 4 },
625 { 8000, 5 },
626};
627
628static int wm8961_hw_params(struct snd_pcm_substream *substream,
629 struct snd_pcm_hw_params *params,
630 struct snd_soc_dai *dai)
631{
632 struct snd_soc_codec *codec = dai->codec;
633 struct wm8961_priv *wm8961 = codec->private_data;
634 int i, best, target, fs;
635 u16 reg;
636
637 fs = params_rate(params);
638
639 if (!wm8961->sysclk) {
640 dev_err(codec->dev, "MCLK has not been specified\n");
641 return -EINVAL;
642 }
643
644 /* Find the closest sample rate for the filters */
645 best = 0;
646 for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) {
647 if (abs(wm8961_srate[i].rate - fs) <
648 abs(wm8961_srate[best].rate - fs))
649 best = i;
650 }
651 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3);
652 reg &= ~WM8961_SAMPLE_RATE_MASK;
653 reg |= wm8961_srate[best].val;
654 snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg);
655 dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n",
656 wm8961_srate[best].rate, fs);
657
658 /* Select a CLK_SYS/fs ratio equal to or higher than required */
659 target = wm8961->sysclk / fs;
660
661 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) {
662 dev_err(codec->dev,
663 "SYSCLK must be at least 64*fs for DAC\n");
664 return -EINVAL;
665 }
666 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) {
667 dev_err(codec->dev,
668 "SYSCLK must be at least 256*fs for ADC\n");
669 return -EINVAL;
670 }
671
672 for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) {
673 if (wm8961_clk_sys_ratio[i].ratio >= target)
674 break;
675 }
676 if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) {
677 dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n");
678 return -EINVAL;
679 }
680 dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n",
681 wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs,
682 wm8961->sysclk / fs);
683
684 reg = snd_soc_read(codec, WM8961_CLOCKING_4);
685 reg &= ~WM8961_CLK_SYS_RATE_MASK;
686 reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT;
687 snd_soc_write(codec, WM8961_CLOCKING_4, reg);
688
689 reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
690 reg &= ~WM8961_WL_MASK;
691 switch (params_format(params)) {
692 case SNDRV_PCM_FORMAT_S16_LE:
693 break;
694 case SNDRV_PCM_FORMAT_S20_3LE:
695 reg |= 1 << WM8961_WL_SHIFT;
696 break;
697 case SNDRV_PCM_FORMAT_S24_LE:
698 reg |= 2 << WM8961_WL_SHIFT;
699 break;
700 case SNDRV_PCM_FORMAT_S32_LE:
701 reg |= 3 << WM8961_WL_SHIFT;
702 break;
703 default:
704 return -EINVAL;
705 }
706 snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg);
707
708 /* Sloping stop-band filter is recommended for <= 24kHz */
709 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
710 if (fs <= 24000)
711 reg |= WM8961_DACSLOPE;
712 else
713 reg &= WM8961_DACSLOPE;
714 snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
715
716 return 0;
717}
718
719static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
720 unsigned int freq,
721 int dir)
722{
723 struct snd_soc_codec *codec = dai->codec;
724 struct wm8961_priv *wm8961 = codec->private_data;
725 u16 reg = snd_soc_read(codec, WM8961_CLOCKING1);
726
727 if (freq > 33000000) {
728 dev_err(codec->dev, "MCLK must be <33MHz\n");
729 return -EINVAL;
730 }
731
732 if (freq > 16500000) {
733 dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq);
734 reg |= WM8961_MCLKDIV;
735 freq /= 2;
736 } else {
737 dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
738 reg &= WM8961_MCLKDIV;
739 }
740
741 snd_soc_write(codec, WM8961_CLOCKING1, reg);
742
743 wm8961->sysclk = freq;
744
745 return 0;
746}
747
748static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
749{
750 struct snd_soc_codec *codec = dai->codec;
751 u16 aif = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
752
753 aif &= ~(WM8961_BCLKINV | WM8961_LRP |
754 WM8961_MS | WM8961_FORMAT_MASK);
755
756 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
757 case SND_SOC_DAIFMT_CBM_CFM:
758 aif |= WM8961_MS;
759 break;
760 case SND_SOC_DAIFMT_CBS_CFS:
761 break;
762 default:
763 return -EINVAL;
764 }
765
766 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
767 case SND_SOC_DAIFMT_RIGHT_J:
768 break;
769
770 case SND_SOC_DAIFMT_LEFT_J:
771 aif |= 1;
772 break;
773
774 case SND_SOC_DAIFMT_I2S:
775 aif |= 2;
776 break;
777
778 case SND_SOC_DAIFMT_DSP_B:
779 aif |= WM8961_LRP;
780 case SND_SOC_DAIFMT_DSP_A:
781 aif |= 3;
782 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
783 case SND_SOC_DAIFMT_NB_NF:
784 case SND_SOC_DAIFMT_IB_NF:
785 break;
786 default:
787 return -EINVAL;
788 }
789 break;
790
791 default:
792 return -EINVAL;
793 }
794
795 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
796 case SND_SOC_DAIFMT_NB_NF:
797 break;
798 case SND_SOC_DAIFMT_NB_IF:
799 aif |= WM8961_LRP;
800 break;
801 case SND_SOC_DAIFMT_IB_NF:
802 aif |= WM8961_BCLKINV;
803 break;
804 case SND_SOC_DAIFMT_IB_IF:
805 aif |= WM8961_BCLKINV | WM8961_LRP;
806 break;
807 default:
808 return -EINVAL;
809 }
810
811 return snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, aif);
812}
813
814static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate)
815{
816 struct snd_soc_codec *codec = dai->codec;
817 u16 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_2);
818
819 if (tristate)
820 reg |= WM8961_TRIS;
821 else
822 reg &= ~WM8961_TRIS;
823
824 return snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg);
825}
826
827static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute)
828{
829 struct snd_soc_codec *codec = dai->codec;
830 u16 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_1);
831
832 if (mute)
833 reg |= WM8961_DACMU;
834 else
835 reg &= ~WM8961_DACMU;
836
837 msleep(17);
838
839 return snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_1, reg);
840}
841
842static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
843{
844 struct snd_soc_codec *codec = dai->codec;
845 u16 reg;
846
847 switch (div_id) {
848 case WM8961_BCLK:
849 reg = snd_soc_read(codec, WM8961_CLOCKING2);
850 reg &= ~WM8961_BCLKDIV_MASK;
851 reg |= div;
852 snd_soc_write(codec, WM8961_CLOCKING2, reg);
853 break;
854
855 case WM8961_LRCLK:
856 reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_2);
857 reg &= ~WM8961_LRCLK_RATE_MASK;
858 reg |= div;
859 snd_soc_write(codec, WM8961_AUDIO_INTERFACE_2, reg);
860 break;
861
862 default:
863 return -EINVAL;
864 }
865
866 return 0;
867}
868
869static int wm8961_set_bias_level(struct snd_soc_codec *codec,
870 enum snd_soc_bias_level level)
871{
872 u16 reg;
873
874 /* This is all slightly unusual since we have no bypass paths
875 * and the output amplifier structure means we can just slam
876 * the biases straight up rather than having to ramp them
877 * slowly.
878 */
879 switch (level) {
880 case SND_SOC_BIAS_ON:
881 break;
882
883 case SND_SOC_BIAS_PREPARE:
884 if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
885 /* Enable bias generation */
886 reg = snd_soc_read(codec, WM8961_ANTI_POP);
887 reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN;
888 snd_soc_write(codec, WM8961_ANTI_POP, reg);
889
890 /* VMID=2*50k, VREF */
891 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
892 reg &= ~WM8961_VMIDSEL_MASK;
893 reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF;
894 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
895 }
896 break;
897
898 case SND_SOC_BIAS_STANDBY:
899 if (codec->bias_level == SND_SOC_BIAS_PREPARE) {
900 /* VREF off */
901 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
902 reg &= ~WM8961_VREF;
903 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
904
905 /* Bias generation off */
906 reg = snd_soc_read(codec, WM8961_ANTI_POP);
907 reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN);
908 snd_soc_write(codec, WM8961_ANTI_POP, reg);
909
910 /* VMID off */
911 reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
912 reg &= ~WM8961_VMIDSEL_MASK;
913 snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
914 }
915 break;
916
917 case SND_SOC_BIAS_OFF:
918 break;
919 }
920
921 codec->bias_level = level;
922
923 return 0;
924}
925
926
927#define WM8961_RATES SNDRV_PCM_RATE_8000_48000
928
929#define WM8961_FORMATS \
930 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
931 SNDRV_PCM_FMTBIT_S24_LE)
932
933static struct snd_soc_dai_ops wm8961_dai_ops = {
934 .hw_params = wm8961_hw_params,
935 .set_sysclk = wm8961_set_sysclk,
936 .set_fmt = wm8961_set_fmt,
937 .digital_mute = wm8961_digital_mute,
938 .set_tristate = wm8961_set_tristate,
939 .set_clkdiv = wm8961_set_clkdiv,
940};
941
942struct snd_soc_dai wm8961_dai = {
943 .name = "WM8961",
944 .playback = {
945 .stream_name = "HiFi Playback",
946 .channels_min = 1,
947 .channels_max = 2,
948 .rates = WM8961_RATES,
949 .formats = WM8961_FORMATS,},
950 .capture = {
951 .stream_name = "HiFi Capture",
952 .channels_min = 1,
953 .channels_max = 2,
954 .rates = WM8961_RATES,
955 .formats = WM8961_FORMATS,},
956 .ops = &wm8961_dai_ops,
957};
958EXPORT_SYMBOL_GPL(wm8961_dai);
959
960
961static struct snd_soc_codec *wm8961_codec;
962
963static int wm8961_probe(struct platform_device *pdev)
964{
965 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
966 struct snd_soc_codec *codec;
967 int ret = 0;
968
969 if (wm8961_codec == NULL) {
970 dev_err(&pdev->dev, "Codec device not registered\n");
971 return -ENODEV;
972 }
973
974 socdev->card->codec = wm8961_codec;
975 codec = wm8961_codec;
976
977 /* register pcms */
978 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
979 if (ret < 0) {
980 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
981 goto pcm_err;
982 }
983
984 snd_soc_add_controls(codec, wm8961_snd_controls,
985 ARRAY_SIZE(wm8961_snd_controls));
986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
987 ARRAY_SIZE(wm8961_dapm_widgets));
988 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
997 return ret;
998
999card_err:
1000 snd_soc_free_pcms(socdev);
1001 snd_soc_dapm_free(socdev);
1002pcm_err:
1003 return ret;
1004}
1005
1006static int wm8961_remove(struct platform_device *pdev)
1007{
1008 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1009
1010 snd_soc_free_pcms(socdev);
1011 snd_soc_dapm_free(socdev);
1012
1013 return 0;
1014}
1015
1016#ifdef CONFIG_PM
1017static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
1018{
1019 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1020 struct snd_soc_codec *codec = socdev->card->codec;
1021
1022 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1023
1024 return 0;
1025}
1026
1027static int wm8961_resume(struct platform_device *pdev)
1028{
1029 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1030 struct snd_soc_codec *codec = socdev->card->codec;
1031 u16 *reg_cache = codec->reg_cache;
1032 int i;
1033
1034 for (i = 0; i < codec->reg_cache_size; i++) {
1035 if (i == WM8961_SOFTWARE_RESET)
1036 continue;
1037
1038 snd_soc_write(codec, i, reg_cache[i]);
1039 }
1040
1041 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1042
1043 return 0;
1044}
1045#else
1046#define wm8961_suspend NULL
1047#define wm8961_resume NULL
1048#endif
1049
1050struct snd_soc_codec_device soc_codec_dev_wm8961 = {
1051 .probe = wm8961_probe,
1052 .remove = wm8961_remove,
1053 .suspend = wm8961_suspend,
1054 .resume = wm8961_resume,
1055};
1056EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
1057
1058static int wm8961_register(struct wm8961_priv *wm8961)
1059{
1060 struct snd_soc_codec *codec = &wm8961->codec;
1061 int ret;
1062 u16 reg;
1063
1064 if (wm8961_codec) {
1065 dev_err(codec->dev, "Another WM8961 is registered\n");
1066 ret = -EINVAL;
1067 goto err;
1068 }
1069
1070 mutex_init(&codec->mutex);
1071 INIT_LIST_HEAD(&codec->dapm_widgets);
1072 INIT_LIST_HEAD(&codec->dapm_paths);
1073
1074 codec->private_data = wm8961;
1075 codec->name = "WM8961";
1076 codec->owner = THIS_MODULE;
1077 codec->dai = &wm8961_dai;
1078 codec->num_dai = 1;
1079 codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
1080 codec->reg_cache = &wm8961->reg_cache;
1081 codec->bias_level = SND_SOC_BIAS_OFF;
1082 codec->set_bias_level = wm8961_set_bias_level;
1083 codec->volatile_register = wm8961_volatile_register;
1084
1085 memcpy(codec->reg_cache, wm8961_reg_defaults,
1086 sizeof(wm8961_reg_defaults));
1087
1088 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1089 if (ret != 0) {
1090 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1091 goto err;
1092 }
1093
1094 reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
1095 if (reg != 0x1801) {
1096 dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
1097 ret = -EINVAL;
1098 goto err;
1099 }
1100
1101 /* This isn't volatile - readback doesn't correspond to write */
1102 reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
1103 dev_info(codec->dev, "WM8961 family %d revision %c\n",
1104 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
1105 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
1106 + 'A');
1107
1108 ret = wm8961_reset(codec);
1109 if (ret < 0) {
1110 dev_err(codec->dev, "Failed to issue reset\n");
1111 return ret;
1112 }
1113
1114 /* Enable class W */
1115 reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
1116 reg |= WM8961_CP_DYN_PWR_MASK;
1117 snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg);
1118
1119 /* Latch volume update bits (right channel only, we always
1120 * write both out) and default ZC on. */
1121 reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME);
1122 snd_soc_write(codec, WM8961_ROUT1_VOLUME,
1123 reg | WM8961_LO1ZC | WM8961_OUT1VU);
1124 snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
1125 reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME);
1126 snd_soc_write(codec, WM8961_ROUT2_VOLUME,
1127 reg | WM8961_SPKRZC | WM8961_SPKVU);
1128 snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);
1129
1130 reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME);
1131 snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
1132 reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
1133 snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);
1134
1135 /* Use soft mute by default */
1136 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
1137 reg |= WM8961_DACSMM;
1138 snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
1139
1140 /* Use automatic clocking mode by default; for now this is all
1141 * we support.
1142 */
1143 reg = snd_soc_read(codec, WM8961_CLOCKING_3);
1144 reg &= ~WM8961_MANUAL_MODE;
1145 snd_soc_write(codec, WM8961_CLOCKING_3, reg);
1146
1147 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1148
1149 wm8961_dai.dev = codec->dev;
1150
1151 wm8961_codec = codec;
1152
1153 ret = snd_soc_register_codec(codec);
1154 if (ret != 0) {
1155 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1156 return ret;
1157 }
1158
1159 ret = snd_soc_register_dai(&wm8961_dai);
1160 if (ret != 0) {
1161 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1162 snd_soc_unregister_codec(codec);
1163 return ret;
1164 }
1165
1166 return 0;
1167
1168err:
1169 kfree(wm8961);
1170 return ret;
1171}
1172
1173static void wm8961_unregister(struct wm8961_priv *wm8961)
1174{
1175 wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF);
1176 snd_soc_unregister_dai(&wm8961_dai);
1177 snd_soc_unregister_codec(&wm8961->codec);
1178 kfree(wm8961);
1179 wm8961_codec = NULL;
1180}
1181
1182static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
1183 const struct i2c_device_id *id)
1184{
1185 struct wm8961_priv *wm8961;
1186 struct snd_soc_codec *codec;
1187
1188 wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
1189 if (wm8961 == NULL)
1190 return -ENOMEM;
1191
1192 codec = &wm8961->codec;
1193
1194 i2c_set_clientdata(i2c, wm8961);
1195 codec->control_data = i2c;
1196
1197 codec->dev = &i2c->dev;
1198
1199 return wm8961_register(wm8961);
1200}
1201
1202static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1203{
1204 struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
1205 wm8961_unregister(wm8961);
1206 return 0;
1207}
1208
1209#ifdef CONFIG_PM
1210static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
1211{
1212 return snd_soc_suspend_device(&client->dev);
1213}
1214
1215static 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
1224static const struct i2c_device_id wm8961_i2c_id[] = {
1225 { "wm8961", 0 },
1226 { }
1227};
1228MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
1229
1230static struct i2c_driver wm8961_i2c_driver = {
1231 .driver = {
1232 .name = "wm8961",
1233 .owner = THIS_MODULE,
1234 },
1235 .probe = wm8961_i2c_probe,
1236 .remove = __devexit_p(wm8961_i2c_remove),
1237 .suspend = wm8961_i2c_suspend,
1238 .resume = wm8961_i2c_resume,
1239 .id_table = wm8961_i2c_id,
1240};
1241
1242static int __init wm8961_modinit(void)
1243{
1244 int ret;
1245
1246 ret = i2c_add_driver(&wm8961_i2c_driver);
1247 if (ret != 0) {
1248 printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
1249 ret);
1250 }
1251
1252 return ret;
1253}
1254module_init(wm8961_modinit);
1255
1256static void __exit wm8961_exit(void)
1257{
1258 i2c_del_driver(&wm8961_i2c_driver);
1259}
1260module_exit(wm8961_exit);
1261
1262
1263MODULE_DESCRIPTION("ASoC WM8961 driver");
1264MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1265MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h
new file mode 100644
index 000000000000..5513bfd720d6
--- /dev/null
+++ b/sound/soc/codecs/wm8961.h
@@ -0,0 +1,866 @@
1/*
2 * wm8961.h -- WM8961 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 _WM8961_H
10#define _WM8961_H
11
12#include <sound/soc.h>
13
14extern struct snd_soc_codec_device soc_codec_dev_wm8961;
15extern struct snd_soc_dai wm8961_dai;
16
17#define WM8961_BCLK 1
18#define WM8961_LRCLK 2
19
20#define WM8961_BCLK_DIV_1 0
21#define WM8961_BCLK_DIV_1_5 1
22#define WM8961_BCLK_DIV_2 2
23#define WM8961_BCLK_DIV_3 3
24#define WM8961_BCLK_DIV_4 4
25#define WM8961_BCLK_DIV_5_5 5
26#define WM8961_BCLK_DIV_6 6
27#define WM8961_BCLK_DIV_8 7
28#define WM8961_BCLK_DIV_11 8
29#define WM8961_BCLK_DIV_12 9
30#define WM8961_BCLK_DIV_16 10
31#define WM8961_BCLK_DIV_24 11
32#define WM8961_BCLK_DIV_32 13
33
34
35/*
36 * Register values.
37 */
38#define WM8961_LEFT_INPUT_VOLUME 0x00
39#define WM8961_RIGHT_INPUT_VOLUME 0x01
40#define WM8961_LOUT1_VOLUME 0x02
41#define WM8961_ROUT1_VOLUME 0x03
42#define WM8961_CLOCKING1 0x04
43#define WM8961_ADC_DAC_CONTROL_1 0x05
44#define WM8961_ADC_DAC_CONTROL_2 0x06
45#define WM8961_AUDIO_INTERFACE_0 0x07
46#define WM8961_CLOCKING2 0x08
47#define WM8961_AUDIO_INTERFACE_1 0x09
48#define WM8961_LEFT_DAC_VOLUME 0x0A
49#define WM8961_RIGHT_DAC_VOLUME 0x0B
50#define WM8961_AUDIO_INTERFACE_2 0x0E
51#define WM8961_SOFTWARE_RESET 0x0F
52#define WM8961_ALC1 0x11
53#define WM8961_ALC2 0x12
54#define WM8961_ALC3 0x13
55#define WM8961_NOISE_GATE 0x14
56#define WM8961_LEFT_ADC_VOLUME 0x15
57#define WM8961_RIGHT_ADC_VOLUME 0x16
58#define WM8961_ADDITIONAL_CONTROL_1 0x17
59#define WM8961_ADDITIONAL_CONTROL_2 0x18
60#define WM8961_PWR_MGMT_1 0x19
61#define WM8961_PWR_MGMT_2 0x1A
62#define WM8961_ADDITIONAL_CONTROL_3 0x1B
63#define WM8961_ANTI_POP 0x1C
64#define WM8961_CLOCKING_3 0x1E
65#define WM8961_ADCL_SIGNAL_PATH 0x20
66#define WM8961_ADCR_SIGNAL_PATH 0x21
67#define WM8961_LOUT2_VOLUME 0x28
68#define WM8961_ROUT2_VOLUME 0x29
69#define WM8961_PWR_MGMT_3 0x2F
70#define WM8961_ADDITIONAL_CONTROL_4 0x30
71#define WM8961_CLASS_D_CONTROL_1 0x31
72#define WM8961_CLASS_D_CONTROL_2 0x33
73#define WM8961_CLOCKING_4 0x38
74#define WM8961_DSP_SIDETONE_0 0x39
75#define WM8961_DSP_SIDETONE_1 0x3A
76#define WM8961_DC_SERVO_0 0x3C
77#define WM8961_DC_SERVO_1 0x3D
78#define WM8961_DC_SERVO_3 0x3F
79#define WM8961_DC_SERVO_5 0x41
80#define WM8961_ANALOGUE_PGA_BIAS 0x44
81#define WM8961_ANALOGUE_HP_0 0x45
82#define WM8961_ANALOGUE_HP_2 0x47
83#define WM8961_CHARGE_PUMP_1 0x48
84#define WM8961_CHARGE_PUMP_B 0x52
85#define WM8961_WRITE_SEQUENCER_1 0x57
86#define WM8961_WRITE_SEQUENCER_2 0x58
87#define WM8961_WRITE_SEQUENCER_3 0x59
88#define WM8961_WRITE_SEQUENCER_4 0x5A
89#define WM8961_WRITE_SEQUENCER_5 0x5B
90#define WM8961_WRITE_SEQUENCER_6 0x5C
91#define WM8961_WRITE_SEQUENCER_7 0x5D
92#define WM8961_GENERAL_TEST_1 0xFC
93
94
95/*
96 * Field Definitions.
97 */
98
99/*
100 * R0 (0x00) - Left Input volume
101 */
102#define WM8961_IPVU 0x0100 /* IPVU */
103#define WM8961_IPVU_MASK 0x0100 /* IPVU */
104#define WM8961_IPVU_SHIFT 8 /* IPVU */
105#define WM8961_IPVU_WIDTH 1 /* IPVU */
106#define WM8961_LINMUTE 0x0080 /* LINMUTE */
107#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */
108#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */
109#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */
110#define WM8961_LIZC 0x0040 /* LIZC */
111#define WM8961_LIZC_MASK 0x0040 /* LIZC */
112#define WM8961_LIZC_SHIFT 6 /* LIZC */
113#define WM8961_LIZC_WIDTH 1 /* LIZC */
114#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */
115#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */
116#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */
117
118/*
119 * R1 (0x01) - Right Input volume
120 */
121#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */
122#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */
123#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */
124#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */
125#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */
126#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */
127#define WM8961_IPVU 0x0100 /* IPVU */
128#define WM8961_IPVU_MASK 0x0100 /* IPVU */
129#define WM8961_IPVU_SHIFT 8 /* IPVU */
130#define WM8961_IPVU_WIDTH 1 /* IPVU */
131#define WM8961_RINMUTE 0x0080 /* RINMUTE */
132#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */
133#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */
134#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */
135#define WM8961_RIZC 0x0040 /* RIZC */
136#define WM8961_RIZC_MASK 0x0040 /* RIZC */
137#define WM8961_RIZC_SHIFT 6 /* RIZC */
138#define WM8961_RIZC_WIDTH 1 /* RIZC */
139#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */
140#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */
141#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */
142
143/*
144 * R2 (0x02) - LOUT1 volume
145 */
146#define WM8961_OUT1VU 0x0100 /* OUT1VU */
147#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
148#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
149#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
150#define WM8961_LO1ZC 0x0080 /* LO1ZC */
151#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */
152#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */
153#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */
154#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */
155#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */
156#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */
157
158/*
159 * R3 (0x03) - ROUT1 volume
160 */
161#define WM8961_OUT1VU 0x0100 /* OUT1VU */
162#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */
163#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */
164#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */
165#define WM8961_RO1ZC 0x0080 /* RO1ZC */
166#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */
167#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */
168#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */
169#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */
170#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */
171#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */
172
173/*
174 * R4 (0x04) - Clocking1
175 */
176#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */
177#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */
178#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */
179#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */
180#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */
181#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */
182#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */
183#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */
184#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */
185#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */
186
187/*
188 * R5 (0x05) - ADC & DAC Control 1
189 */
190#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */
191#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */
192#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */
193#define WM8961_DACMU 0x0008 /* DACMU */
194#define WM8961_DACMU_MASK 0x0008 /* DACMU */
195#define WM8961_DACMU_SHIFT 3 /* DACMU */
196#define WM8961_DACMU_WIDTH 1 /* DACMU */
197#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
198#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
199#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
200#define WM8961_ADCHPD 0x0001 /* ADCHPD */
201#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */
202#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */
203#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */
204
205/*
206 * R6 (0x06) - ADC & DAC Control 2
207 */
208#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */
209#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */
210#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */
211#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */
212#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */
213#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */
214#define WM8961_DACSMM 0x0008 /* DACSMM */
215#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */
216#define WM8961_DACSMM_SHIFT 3 /* DACSMM */
217#define WM8961_DACSMM_WIDTH 1 /* DACSMM */
218#define WM8961_DACMR 0x0004 /* DACMR */
219#define WM8961_DACMR_MASK 0x0004 /* DACMR */
220#define WM8961_DACMR_SHIFT 2 /* DACMR */
221#define WM8961_DACMR_WIDTH 1 /* DACMR */
222#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */
223#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */
224#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */
225#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */
226#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */
227#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */
228#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */
229#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
230
231/*
232 * R7 (0x07) - Audio Interface 0
233 */
234#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */
235#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */
236#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */
237#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */
238#define WM8961_BCLKINV 0x0080 /* BCLKINV */
239#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */
240#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */
241#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */
242#define WM8961_MS 0x0040 /* MS */
243#define WM8961_MS_MASK 0x0040 /* MS */
244#define WM8961_MS_SHIFT 6 /* MS */
245#define WM8961_MS_WIDTH 1 /* MS */
246#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */
247#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */
248#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */
249#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */
250#define WM8961_LRP 0x0010 /* LRP */
251#define WM8961_LRP_MASK 0x0010 /* LRP */
252#define WM8961_LRP_SHIFT 4 /* LRP */
253#define WM8961_LRP_WIDTH 1 /* LRP */
254#define WM8961_WL_MASK 0x000C /* WL - [3:2] */
255#define WM8961_WL_SHIFT 2 /* WL - [3:2] */
256#define WM8961_WL_WIDTH 2 /* WL - [3:2] */
257#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */
258#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */
259#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */
260
261/*
262 * R8 (0x08) - Clocking2
263 */
264#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */
265#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */
266#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */
267#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */
268#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */
269#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */
270#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
271#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */
272#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */
273#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */
274#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
275#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */
276#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */
277#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */
278
279/*
280 * R9 (0x09) - Audio Interface 1
281 */
282#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */
283#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */
284#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */
285#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */
286#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */
287#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */
288#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */
289#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */
290#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */
291#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */
292
293/*
294 * R10 (0x0A) - Left DAC volume
295 */
296#define WM8961_DACVU 0x0100 /* DACVU */
297#define WM8961_DACVU_MASK 0x0100 /* DACVU */
298#define WM8961_DACVU_SHIFT 8 /* DACVU */
299#define WM8961_DACVU_WIDTH 1 /* DACVU */
300#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */
301#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */
302#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */
303
304/*
305 * R11 (0x0B) - Right DAC volume
306 */
307#define WM8961_DACVU 0x0100 /* DACVU */
308#define WM8961_DACVU_MASK 0x0100 /* DACVU */
309#define WM8961_DACVU_SHIFT 8 /* DACVU */
310#define WM8961_DACVU_WIDTH 1 /* DACVU */
311#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */
312#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */
313#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */
314
315/*
316 * R14 (0x0E) - Audio Interface 2
317 */
318#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */
319#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */
320#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */
321
322/*
323 * R15 (0x0F) - Software Reset
324 */
325#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
326#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
327#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
328
329/*
330 * R17 (0x11) - ALC1
331 */
332#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
333#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
334#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
335#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */
336#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */
337#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */
338#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */
339#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */
340#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */
341
342/*
343 * R18 (0x12) - ALC2
344 */
345#define WM8961_ALCZC 0x0080 /* ALCZC */
346#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */
347#define WM8961_ALCZC_SHIFT 7 /* ALCZC */
348#define WM8961_ALCZC_WIDTH 1 /* ALCZC */
349#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */
350#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */
351#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */
352#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */
353#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */
354#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */
355
356/*
357 * R19 (0x13) - ALC3
358 */
359#define WM8961_ALCMODE 0x0100 /* ALCMODE */
360#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */
361#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */
362#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */
363#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */
364#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */
365#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */
366#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */
367#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */
368#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */
369
370/*
371 * R20 (0x14) - Noise Gate
372 */
373#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */
374#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */
375#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */
376#define WM8961_NGG 0x0002 /* NGG */
377#define WM8961_NGG_MASK 0x0002 /* NGG */
378#define WM8961_NGG_SHIFT 1 /* NGG */
379#define WM8961_NGG_WIDTH 1 /* NGG */
380#define WM8961_NGAT 0x0001 /* NGAT */
381#define WM8961_NGAT_MASK 0x0001 /* NGAT */
382#define WM8961_NGAT_SHIFT 0 /* NGAT */
383#define WM8961_NGAT_WIDTH 1 /* NGAT */
384
385/*
386 * R21 (0x15) - Left ADC volume
387 */
388#define WM8961_ADCVU 0x0100 /* ADCVU */
389#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
390#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
391#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
392#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */
393#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */
394#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */
395
396/*
397 * R22 (0x16) - Right ADC volume
398 */
399#define WM8961_ADCVU 0x0100 /* ADCVU */
400#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */
401#define WM8961_ADCVU_SHIFT 8 /* ADCVU */
402#define WM8961_ADCVU_WIDTH 1 /* ADCVU */
403#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */
404#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */
405#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */
406
407/*
408 * R23 (0x17) - Additional control(1)
409 */
410#define WM8961_TSDEN 0x0100 /* TSDEN */
411#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */
412#define WM8961_TSDEN_SHIFT 8 /* TSDEN */
413#define WM8961_TSDEN_WIDTH 1 /* TSDEN */
414#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */
415#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */
416#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */
417#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */
418#define WM8961_TOEN 0x0001 /* TOEN */
419#define WM8961_TOEN_MASK 0x0001 /* TOEN */
420#define WM8961_TOEN_SHIFT 0 /* TOEN */
421#define WM8961_TOEN_WIDTH 1 /* TOEN */
422
423/*
424 * R24 (0x18) - Additional control(2)
425 */
426#define WM8961_TRIS 0x0008 /* TRIS */
427#define WM8961_TRIS_MASK 0x0008 /* TRIS */
428#define WM8961_TRIS_SHIFT 3 /* TRIS */
429#define WM8961_TRIS_WIDTH 1 /* TRIS */
430
431/*
432 * R25 (0x19) - Pwr Mgmt (1)
433 */
434#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */
435#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */
436#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */
437#define WM8961_VREF 0x0040 /* VREF */
438#define WM8961_VREF_MASK 0x0040 /* VREF */
439#define WM8961_VREF_SHIFT 6 /* VREF */
440#define WM8961_VREF_WIDTH 1 /* VREF */
441#define WM8961_AINL 0x0020 /* AINL */
442#define WM8961_AINL_MASK 0x0020 /* AINL */
443#define WM8961_AINL_SHIFT 5 /* AINL */
444#define WM8961_AINL_WIDTH 1 /* AINL */
445#define WM8961_AINR 0x0010 /* AINR */
446#define WM8961_AINR_MASK 0x0010 /* AINR */
447#define WM8961_AINR_SHIFT 4 /* AINR */
448#define WM8961_AINR_WIDTH 1 /* AINR */
449#define WM8961_ADCL 0x0008 /* ADCL */
450#define WM8961_ADCL_MASK 0x0008 /* ADCL */
451#define WM8961_ADCL_SHIFT 3 /* ADCL */
452#define WM8961_ADCL_WIDTH 1 /* ADCL */
453#define WM8961_ADCR 0x0004 /* ADCR */
454#define WM8961_ADCR_MASK 0x0004 /* ADCR */
455#define WM8961_ADCR_SHIFT 2 /* ADCR */
456#define WM8961_ADCR_WIDTH 1 /* ADCR */
457#define WM8961_MICB 0x0002 /* MICB */
458#define WM8961_MICB_MASK 0x0002 /* MICB */
459#define WM8961_MICB_SHIFT 1 /* MICB */
460#define WM8961_MICB_WIDTH 1 /* MICB */
461
462/*
463 * R26 (0x1A) - Pwr Mgmt (2)
464 */
465#define WM8961_DACL 0x0100 /* DACL */
466#define WM8961_DACL_MASK 0x0100 /* DACL */
467#define WM8961_DACL_SHIFT 8 /* DACL */
468#define WM8961_DACL_WIDTH 1 /* DACL */
469#define WM8961_DACR 0x0080 /* DACR */
470#define WM8961_DACR_MASK 0x0080 /* DACR */
471#define WM8961_DACR_SHIFT 7 /* DACR */
472#define WM8961_DACR_WIDTH 1 /* DACR */
473#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */
474#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */
475#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */
476#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */
477#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */
478#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */
479#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */
480#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */
481#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */
482#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */
483#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */
484#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */
485#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */
486#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */
487#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */
488#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */
489
490/*
491 * R27 (0x1B) - Additional Control (3)
492 */
493#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */
494#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */
495#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */
496
497/*
498 * R28 (0x1C) - Anti-pop
499 */
500#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */
501#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */
502#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */
503#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */
504#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */
505#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */
506#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */
507#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */
508#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */
509#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */
510#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */
511#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */
512
513/*
514 * R30 (0x1E) - Clocking 3
515 */
516#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */
517#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */
518#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */
519#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */
520#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */
521#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */
522#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */
523#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */
524#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */
525#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */
526
527/*
528 * R32 (0x20) - ADCL signal path
529 */
530#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */
531#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */
532#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */
533
534/*
535 * R33 (0x21) - ADCR signal path
536 */
537#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */
538#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */
539#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */
540
541/*
542 * R40 (0x28) - LOUT2 volume
543 */
544#define WM8961_SPKVU 0x0100 /* SPKVU */
545#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
546#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
547#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
548#define WM8961_SPKLZC 0x0080 /* SPKLZC */
549#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */
550#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */
551#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */
552#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */
553#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */
554#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */
555
556/*
557 * R41 (0x29) - ROUT2 volume
558 */
559#define WM8961_SPKVU 0x0100 /* SPKVU */
560#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */
561#define WM8961_SPKVU_SHIFT 8 /* SPKVU */
562#define WM8961_SPKVU_WIDTH 1 /* SPKVU */
563#define WM8961_SPKRZC 0x0080 /* SPKRZC */
564#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */
565#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */
566#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */
567#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */
568#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */
569#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */
570
571/*
572 * R47 (0x2F) - Pwr Mgmt (3)
573 */
574#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */
575#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */
576#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */
577#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
578#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */
579#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */
580#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */
581#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */
582
583/*
584 * R48 (0x30) - Additional Control (4)
585 */
586#define WM8961_TSENSEN 0x0002 /* TSENSEN */
587#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */
588#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */
589#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */
590#define WM8961_MBSEL 0x0001 /* MBSEL */
591#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */
592#define WM8961_MBSEL_SHIFT 0 /* MBSEL */
593#define WM8961_MBSEL_WIDTH 1 /* MBSEL */
594
595/*
596 * R49 (0x31) - Class D Control 1
597 */
598#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */
599#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */
600#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */
601#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */
602#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */
603#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */
604#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */
605#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */
606
607/*
608 * R51 (0x33) - Class D Control 2
609 */
610#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */
611#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */
612#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */
613
614/*
615 * R56 (0x38) - Clocking 4
616 */
617#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */
618#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */
619#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */
620#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */
621#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */
622#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */
623
624/*
625 * R57 (0x39) - DSP Sidetone 0
626 */
627#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
628#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
629#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
630#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */
631#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */
632#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */
633
634/*
635 * R58 (0x3A) - DSP Sidetone 1
636 */
637#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */
638#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */
639#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */
640#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
641#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
642#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
643
644/*
645 * R60 (0x3C) - DC Servo 0
646 */
647#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */
648#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */
649#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */
650#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */
651#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */
652#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */
653#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */
654#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */
655#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */
656#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */
657#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */
658#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */
659#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */
660#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */
661#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */
662#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */
663#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */
664#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */
665#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */
666#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */
667#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */
668#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */
669#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */
670#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */
671
672/*
673 * R61 (0x3D) - DC Servo 1
674 */
675#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */
676#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */
677#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */
678#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */
679#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */
680#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */
681#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */
682#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */
683#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */
684#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */
685#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */
686#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */
687#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */
688#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */
689#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */
690#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */
691#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */
692#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */
693#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */
694#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */
695#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */
696#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */
697#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */
698#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */
699
700/*
701 * R63 (0x3F) - DC Servo 3
702 */
703#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */
704#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */
705#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */
706
707/*
708 * R65 (0x41) - DC Servo 5
709 */
710#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */
711#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */
712#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */
713
714/*
715 * R68 (0x44) - Analogue PGA Bias
716 */
717#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */
718#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */
719#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */
720
721/*
722 * R69 (0x45) - Analogue HP 0
723 */
724#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */
725#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */
726#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */
727#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */
728#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */
729#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */
730#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */
731#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */
732#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */
733#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */
734#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */
735#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */
736#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */
737#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */
738#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */
739#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */
740#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */
741#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */
742#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */
743#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */
744#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */
745#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */
746#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */
747#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */
748#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */
749#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */
750#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */
751#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */
752#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */
753#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */
754#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */
755#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */
756
757/*
758 * R71 (0x47) - Analogue HP 2
759 */
760#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */
761#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */
762#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */
763#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */
764#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */
765#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */
766#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */
767#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */
768#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */
769
770/*
771 * R72 (0x48) - Charge Pump 1
772 */
773#define WM8961_CP_ENA 0x0001 /* CP_ENA */
774#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */
775#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */
776#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */
777
778/*
779 * R82 (0x52) - Charge Pump B
780 */
781#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */
782#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */
783#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */
784
785/*
786 * R87 (0x57) - Write Sequencer 1
787 */
788#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */
789#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */
790#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */
791#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
792#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
793#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
794#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
795
796/*
797 * R88 (0x58) - Write Sequencer 2
798 */
799#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */
800#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */
801#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */
802#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
803#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
804#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
805#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
806
807/*
808 * R89 (0x59) - Write Sequencer 3
809 */
810#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
811#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
812#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
813
814/*
815 * R90 (0x5A) - Write Sequencer 4
816 */
817#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */
818#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */
819#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */
820#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
821#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */
822#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */
823#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */
824#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */
825#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
826#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
827#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
828
829/*
830 * R91 (0x5B) - Write Sequencer 5
831 */
832#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */
833#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */
834#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */
835#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */
836#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */
837#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */
838
839/*
840 * R92 (0x5C) - Write Sequencer 6
841 */
842#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */
843#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */
844#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */
845
846/*
847 * R93 (0x5D) - Write Sequencer 7
848 */
849#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
850#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
851#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
852#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
853
854/*
855 * R252 (0xFC) - General test 1
856 */
857#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */
858#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */
859#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */
860#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */
861#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */
862#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */
863#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */
864#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */
865
866#endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 032dca22dbd3..d66efb0546ea 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
59 0x0079, 0x0079, 0x0079, /* 40 */ 59 0x0079, 0x0079, 0x0079, /* 40 */
60}; 60};
61 61
62static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, 62#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
63 unsigned int reg)
64{
65 u16 *cache = codec->reg_cache;
66 if (reg < WM8971_REG_COUNT)
67 return cache[reg];
68
69 return -1;
70}
71
72static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
73 unsigned int reg, unsigned int value)
74{
75 u16 *cache = codec->reg_cache;
76 if (reg < WM8971_REG_COUNT)
77 cache[reg] = value;
78}
79
80static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 data[2];
84
85 /* data is
86 * D15..D9 WM8753 register offset
87 * D8...D0 register data
88 */
89 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
90 data[1] = value & 0x00ff;
91
92 wm8971_write_reg_cache (codec, reg, value);
93 if (codec->hw_write(codec->control_data, data, 2) == 2)
94 return 0;
95 else
96 return -EIO;
97}
98
99#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
100 63
101/* WM8971 Controls */ 64/* WM8971 Controls */
102static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; 65static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
521 return -EINVAL; 484 return -EINVAL;
522 } 485 }
523 486
524 wm8971_write(codec, WM8971_IFACE, iface); 487 snd_soc_write(codec, WM8971_IFACE, iface);
525 return 0; 488 return 0;
526} 489}
527 490
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
533 struct snd_soc_device *socdev = rtd->socdev; 496 struct snd_soc_device *socdev = rtd->socdev;
534 struct snd_soc_codec *codec = socdev->card->codec; 497 struct snd_soc_codec *codec = socdev->card->codec;
535 struct wm8971_priv *wm8971 = codec->private_data; 498 struct wm8971_priv *wm8971 = codec->private_data;
536 u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; 499 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
537 u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; 500 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
538 int coeff = get_coeff(wm8971->sysclk, params_rate(params)); 501 int coeff = get_coeff(wm8971->sysclk, params_rate(params));
539 502
540 /* bit size */ 503 /* bit size */
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
553 } 516 }
554 517
555 /* set iface & srate */ 518 /* set iface & srate */
556 wm8971_write(codec, WM8971_IFACE, iface); 519 snd_soc_write(codec, WM8971_IFACE, iface);
557 if (coeff >= 0) 520 if (coeff >= 0)
558 wm8971_write(codec, WM8971_SRATE, srate | 521 snd_soc_write(codec, WM8971_SRATE, srate |
559 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 522 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
560 523
561 return 0; 524 return 0;
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
564static int wm8971_mute(struct snd_soc_dai *dai, int mute) 527static int wm8971_mute(struct snd_soc_dai *dai, int mute)
565{ 528{
566 struct snd_soc_codec *codec = dai->codec; 529 struct snd_soc_codec *codec = dai->codec;
567 u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; 530 u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
568 531
569 if (mute) 532 if (mute)
570 wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); 533 snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
571 else 534 else
572 wm8971_write(codec, WM8971_ADCDAC, mute_reg); 535 snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
573 return 0; 536 return 0;
574} 537}
575 538
576static int wm8971_set_bias_level(struct snd_soc_codec *codec, 539static int wm8971_set_bias_level(struct snd_soc_codec *codec,
577 enum snd_soc_bias_level level) 540 enum snd_soc_bias_level level)
578{ 541{
579 u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 542 u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
580 543
581 switch (level) { 544 switch (level) {
582 case SND_SOC_BIAS_ON: 545 case SND_SOC_BIAS_ON:
583 /* set vmid to 50k and unmute dac */ 546 /* set vmid to 50k and unmute dac */
584 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); 547 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
585 break; 548 break;
586 case SND_SOC_BIAS_PREPARE: 549 case SND_SOC_BIAS_PREPARE:
587 break; 550 break;
588 case SND_SOC_BIAS_STANDBY: 551 case SND_SOC_BIAS_STANDBY:
589 /* mute dac and set vmid to 500k, enable VREF */ 552 /* mute dac and set vmid to 500k, enable VREF */
590 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); 553 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
591 break; 554 break;
592 case SND_SOC_BIAS_OFF: 555 case SND_SOC_BIAS_OFF:
593 wm8971_write(codec, WM8971_PWR1, 0x0001); 556 snd_soc_write(codec, WM8971_PWR1, 0x0001);
594 break; 557 break;
595 } 558 }
596 codec->bias_level = level; 559 codec->bias_level = level;
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
667 630
668 /* charge wm8971 caps */ 631 /* charge wm8971 caps */
669 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { 632 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
670 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 633 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
671 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 634 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
672 codec->bias_level = SND_SOC_BIAS_ON; 635 codec->bias_level = SND_SOC_BIAS_ON;
673 queue_delayed_work(wm8971_workq, &codec->delayed_work, 636 queue_delayed_work(wm8971_workq, &codec->delayed_work,
674 msecs_to_jiffies(1000)); 637 msecs_to_jiffies(1000));
@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev)
677 return 0; 640 return 0;
678} 641}
679 642
680static int wm8971_init(struct snd_soc_device *socdev) 643static int wm8971_init(struct snd_soc_device *socdev,
644 enum snd_soc_control_type control)
681{ 645{
682 struct snd_soc_codec *codec = socdev->card->codec; 646 struct snd_soc_codec *codec = socdev->card->codec;
683 int reg, ret = 0; 647 int reg, ret = 0;
684 648
685 codec->name = "WM8971"; 649 codec->name = "WM8971";
686 codec->owner = THIS_MODULE; 650 codec->owner = THIS_MODULE;
687 codec->read = wm8971_read_reg_cache;
688 codec->write = wm8971_write;
689 codec->set_bias_level = wm8971_set_bias_level; 651 codec->set_bias_level = wm8971_set_bias_level;
690 codec->dai = &wm8971_dai; 652 codec->dai = &wm8971_dai;
691 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); 653 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
695 if (codec->reg_cache == NULL) 657 if (codec->reg_cache == NULL)
696 return -ENOMEM; 658 return -ENOMEM;
697 659
660 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
661 if (ret < 0) {
662 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
663 goto err;
664 }
665
698 wm8971_reset(codec); 666 wm8971_reset(codec);
699 667
700 /* register pcms */ 668 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 669 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 670 if (ret < 0) {
703 printk(KERN_ERR "wm8971: failed to create pcms\n"); 671 printk(KERN_ERR "wm8971: failed to create pcms\n");
704 goto pcm_err; 672 goto err;
705 } 673 }
706 674
707 /* charge output caps - set vmid to 5k for quick power up */ 675 /* charge output caps - set vmid to 5k for quick power up */
708 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 676 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
709 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 677 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
710 codec->bias_level = SND_SOC_BIAS_STANDBY; 678 codec->bias_level = SND_SOC_BIAS_STANDBY;
711 queue_delayed_work(wm8971_workq, &codec->delayed_work, 679 queue_delayed_work(wm8971_workq, &codec->delayed_work,
712 msecs_to_jiffies(1000)); 680 msecs_to_jiffies(1000));
713 681
714 /* set the update bits */ 682 /* set the update bits */
715 reg = wm8971_read_reg_cache(codec, WM8971_LDAC); 683 reg = snd_soc_read(codec, WM8971_LDAC);
716 wm8971_write(codec, WM8971_LDAC, reg | 0x0100); 684 snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
717 reg = wm8971_read_reg_cache(codec, WM8971_RDAC); 685 reg = snd_soc_read(codec, WM8971_RDAC);
718 wm8971_write(codec, WM8971_RDAC, reg | 0x0100); 686 snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
719 687
720 reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); 688 reg = snd_soc_read(codec, WM8971_LOUT1V);
721 wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); 689 snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
722 reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); 690 reg = snd_soc_read(codec, WM8971_ROUT1V);
723 wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); 691 snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
724 692
725 reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); 693 reg = snd_soc_read(codec, WM8971_LOUT2V);
726 wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); 694 snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
727 reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); 695 reg = snd_soc_read(codec, WM8971_ROUT2V);
728 wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); 696 snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
729 697
730 reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); 698 reg = snd_soc_read(codec, WM8971_LINVOL);
731 wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); 699 snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
732 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); 700 reg = snd_soc_read(codec, WM8971_RINVOL);
733 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); 701 snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
734 702
735 snd_soc_add_controls(codec, wm8971_snd_controls, 703 snd_soc_add_controls(codec, wm8971_snd_controls,
736 ARRAY_SIZE(wm8971_snd_controls)); 704 ARRAY_SIZE(wm8971_snd_controls));
@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
745card_err: 713card_err:
746 snd_soc_free_pcms(socdev); 714 snd_soc_free_pcms(socdev);
747 snd_soc_dapm_free(socdev); 715 snd_soc_dapm_free(socdev);
748pcm_err: 716err:
749 kfree(codec->reg_cache); 717 kfree(codec->reg_cache);
750 return ret; 718 return ret;
751} 719}
@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
767 735
768 codec->control_data = i2c; 736 codec->control_data = i2c;
769 737
770 ret = wm8971_init(socdev); 738 ret = wm8971_init(socdev, SND_SOC_I2C);
771 if (ret < 0) 739 if (ret < 0)
772 pr_err("failed to initialise WM8971\n"); 740 pr_err("failed to initialise WM8971\n");
773 741
@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev)
877 845
878#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) 846#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
879 if (setup->i2c_address) { 847 if (setup->i2c_address) {
880 codec->hw_write = (hw_write_t)i2c_master_send;
881 ret = wm8971_add_i2c_device(pdev, setup); 848 ret = wm8971_add_i2c_device(pdev, setup);
882 } 849 }
883#endif 850#endif
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
new file mode 100644
index 000000000000..d8a013ab3177
--- /dev/null
+++ b/sound/soc/codecs/wm8974.c
@@ -0,0 +1,808 @@
1/*
2 * wm8974.c -- WM8974 ALSA Soc Audio driver
3 *
4 * Copyright 2006-2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Liam Girdwood <linux@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/version.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 <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
30#include "wm8974.h"
31
32static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
33 0x0000, 0x0000, 0x0000, 0x0000,
34 0x0050, 0x0000, 0x0140, 0x0000,
35 0x0000, 0x0000, 0x0000, 0x00ff,
36 0x0000, 0x0000, 0x0100, 0x00ff,
37 0x0000, 0x0000, 0x012c, 0x002c,
38 0x002c, 0x002c, 0x002c, 0x0000,
39 0x0032, 0x0000, 0x0000, 0x0000,
40 0x0000, 0x0000, 0x0000, 0x0000,
41 0x0038, 0x000b, 0x0032, 0x0000,
42 0x0008, 0x000c, 0x0093, 0x00e9,
43 0x0000, 0x0000, 0x0000, 0x0000,
44 0x0003, 0x0010, 0x0000, 0x0000,
45 0x0000, 0x0002, 0x0000, 0x0000,
46 0x0000, 0x0000, 0x0039, 0x0000,
47 0x0000,
48};
49
50#define WM8974_POWER1_BIASEN 0x08
51#define WM8974_POWER1_BUFIOEN 0x10
52
53struct wm8974_priv {
54 struct snd_soc_codec codec;
55 u16 reg_cache[WM8974_CACHEREGNUM];
56};
57
58static struct snd_soc_codec *wm8974_codec;
59
60#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
61
62static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
63static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
64static const char *wm8974_eqmode[] = {"Capture", "Playback" };
65static const char *wm8974_bw[] = {"Narrow", "Wide" };
66static const char *wm8974_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" };
67static const char *wm8974_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" };
68static const char *wm8974_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" };
69static const char *wm8974_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" };
70static const char *wm8974_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" };
71static const char *wm8974_alc[] = {"ALC", "Limiter" };
72
73static const struct soc_enum wm8974_enum[] = {
74 SOC_ENUM_SINGLE(WM8974_COMP, 1, 4, wm8974_companding), /* adc */
75 SOC_ENUM_SINGLE(WM8974_COMP, 3, 4, wm8974_companding), /* dac */
76 SOC_ENUM_SINGLE(WM8974_DAC, 4, 4, wm8974_deemp),
77 SOC_ENUM_SINGLE(WM8974_EQ1, 8, 2, wm8974_eqmode),
78
79 SOC_ENUM_SINGLE(WM8974_EQ1, 5, 4, wm8974_eq1),
80 SOC_ENUM_SINGLE(WM8974_EQ2, 8, 2, wm8974_bw),
81 SOC_ENUM_SINGLE(WM8974_EQ2, 5, 4, wm8974_eq2),
82 SOC_ENUM_SINGLE(WM8974_EQ3, 8, 2, wm8974_bw),
83
84 SOC_ENUM_SINGLE(WM8974_EQ3, 5, 4, wm8974_eq3),
85 SOC_ENUM_SINGLE(WM8974_EQ4, 8, 2, wm8974_bw),
86 SOC_ENUM_SINGLE(WM8974_EQ4, 5, 4, wm8974_eq4),
87 SOC_ENUM_SINGLE(WM8974_EQ5, 8, 2, wm8974_bw),
88
89 SOC_ENUM_SINGLE(WM8974_EQ5, 5, 4, wm8974_eq5),
90 SOC_ENUM_SINGLE(WM8974_ALC3, 8, 2, wm8974_alc),
91};
92
93static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" };
94
95static const struct soc_enum wm8974_auxmode =
96 SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text);
97
98static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
99static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
100static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0);
101static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0);
102
103static const struct snd_kcontrol_new wm8974_snd_controls[] = {
104
105SOC_SINGLE("Digital Loopback Switch", WM8974_COMP, 0, 1, 0),
106
107SOC_ENUM("DAC Companding", wm8974_enum[1]),
108SOC_ENUM("ADC Companding", wm8974_enum[0]),
109
110SOC_ENUM("Playback De-emphasis", wm8974_enum[2]),
111SOC_SINGLE("DAC Inversion Switch", WM8974_DAC, 0, 1, 0),
112
113SOC_SINGLE_TLV("PCM Volume", WM8974_DACVOL, 0, 255, 0, digital_tlv),
114
115SOC_SINGLE("High Pass Filter Switch", WM8974_ADC, 8, 1, 0),
116SOC_SINGLE("High Pass Cut Off", WM8974_ADC, 4, 7, 0),
117SOC_SINGLE("ADC Inversion Switch", WM8974_ADC, 0, 1, 0),
118
119SOC_SINGLE_TLV("Capture Volume", WM8974_ADCVOL, 0, 255, 0, digital_tlv),
120
121SOC_ENUM("Equaliser Function", wm8974_enum[3]),
122SOC_ENUM("EQ1 Cut Off", wm8974_enum[4]),
123SOC_SINGLE_TLV("EQ1 Volume", WM8974_EQ1, 0, 24, 1, eq_tlv),
124
125SOC_ENUM("Equaliser EQ2 Bandwith", wm8974_enum[5]),
126SOC_ENUM("EQ2 Cut Off", wm8974_enum[6]),
127SOC_SINGLE_TLV("EQ2 Volume", WM8974_EQ2, 0, 24, 1, eq_tlv),
128
129SOC_ENUM("Equaliser EQ3 Bandwith", wm8974_enum[7]),
130SOC_ENUM("EQ3 Cut Off", wm8974_enum[8]),
131SOC_SINGLE_TLV("EQ3 Volume", WM8974_EQ3, 0, 24, 1, eq_tlv),
132
133SOC_ENUM("Equaliser EQ4 Bandwith", wm8974_enum[9]),
134SOC_ENUM("EQ4 Cut Off", wm8974_enum[10]),
135SOC_SINGLE_TLV("EQ4 Volume", WM8974_EQ4, 0, 24, 1, eq_tlv),
136
137SOC_ENUM("Equaliser EQ5 Bandwith", wm8974_enum[11]),
138SOC_ENUM("EQ5 Cut Off", wm8974_enum[12]),
139SOC_SINGLE_TLV("EQ5 Volume", WM8974_EQ5, 0, 24, 1, eq_tlv),
140
141SOC_SINGLE("DAC Playback Limiter Switch", WM8974_DACLIM1, 8, 1, 0),
142SOC_SINGLE("DAC Playback Limiter Decay", WM8974_DACLIM1, 4, 15, 0),
143SOC_SINGLE("DAC Playback Limiter Attack", WM8974_DACLIM1, 0, 15, 0),
144
145SOC_SINGLE("DAC Playback Limiter Threshold", WM8974_DACLIM2, 4, 7, 0),
146SOC_SINGLE("DAC Playback Limiter Boost", WM8974_DACLIM2, 0, 15, 0),
147
148SOC_SINGLE("ALC Enable Switch", WM8974_ALC1, 8, 1, 0),
149SOC_SINGLE("ALC Capture Max Gain", WM8974_ALC1, 3, 7, 0),
150SOC_SINGLE("ALC Capture Min Gain", WM8974_ALC1, 0, 7, 0),
151
152SOC_SINGLE("ALC Capture ZC Switch", WM8974_ALC2, 8, 1, 0),
153SOC_SINGLE("ALC Capture Hold", WM8974_ALC2, 4, 7, 0),
154SOC_SINGLE("ALC Capture Target", WM8974_ALC2, 0, 15, 0),
155
156SOC_ENUM("ALC Capture Mode", wm8974_enum[13]),
157SOC_SINGLE("ALC Capture Decay", WM8974_ALC3, 4, 15, 0),
158SOC_SINGLE("ALC Capture Attack", WM8974_ALC3, 0, 15, 0),
159
160SOC_SINGLE("ALC Capture Noise Gate Switch", WM8974_NGATE, 3, 1, 0),
161SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8974_NGATE, 0, 7, 0),
162
163SOC_SINGLE("Capture PGA ZC Switch", WM8974_INPPGA, 7, 1, 0),
164SOC_SINGLE_TLV("Capture PGA Volume", WM8974_INPPGA, 0, 63, 0, inpga_tlv),
165
166SOC_SINGLE("Speaker Playback ZC Switch", WM8974_SPKVOL, 7, 1, 0),
167SOC_SINGLE("Speaker Playback Switch", WM8974_SPKVOL, 6, 1, 1),
168SOC_SINGLE_TLV("Speaker Playback Volume", WM8974_SPKVOL, 0, 63, 0, spk_tlv),
169
170SOC_ENUM("Aux Mode", wm8974_auxmode),
171
172SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0),
173SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1),
174};
175
176/* Speaker Output Mixer */
177static const struct snd_kcontrol_new wm8974_speaker_mixer_controls[] = {
178SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_SPKMIX, 1, 1, 0),
179SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_SPKMIX, 5, 1, 0),
180SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_SPKMIX, 0, 1, 1),
181};
182
183/* Mono Output Mixer */
184static const struct snd_kcontrol_new wm8974_mono_mixer_controls[] = {
185SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_MONOMIX, 1, 1, 0),
186SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_MONOMIX, 2, 1, 0),
187SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0),
188};
189
190/* Boost mixer */
191static const struct snd_kcontrol_new wm8974_boost_mixer[] = {
192SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0),
193};
194
195/* Input PGA */
196static const struct snd_kcontrol_new wm8974_inpga[] = {
197SOC_DAPM_SINGLE("Aux Switch", WM8974_INPUT, 2, 1, 0),
198SOC_DAPM_SINGLE("MicN Switch", WM8974_INPUT, 1, 1, 0),
199SOC_DAPM_SINGLE("MicP Switch", WM8974_INPUT, 0, 1, 0),
200};
201
202/* AUX Input boost vol */
203static const struct snd_kcontrol_new wm8974_aux_boost_controls =
204SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0);
205
206/* Mic Input boost vol */
207static const struct snd_kcontrol_new wm8974_mic_boost_controls =
208SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0);
209
210static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = {
211SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0,
212 &wm8974_speaker_mixer_controls[0],
213 ARRAY_SIZE(wm8974_speaker_mixer_controls)),
214SND_SOC_DAPM_MIXER("Mono Mixer", WM8974_POWER3, 3, 0,
215 &wm8974_mono_mixer_controls[0],
216 ARRAY_SIZE(wm8974_mono_mixer_controls)),
217SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8974_POWER3, 0, 0),
218SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8974_POWER2, 0, 0),
219SND_SOC_DAPM_PGA("Aux Input", WM8974_POWER1, 6, 0, NULL, 0),
220SND_SOC_DAPM_PGA("SpkN Out", WM8974_POWER3, 5, 0, NULL, 0),
221SND_SOC_DAPM_PGA("SpkP Out", WM8974_POWER3, 6, 0, NULL, 0),
222SND_SOC_DAPM_PGA("Mono Out", WM8974_POWER3, 7, 0, NULL, 0),
223
224SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga,
225 ARRAY_SIZE(wm8974_inpga)),
226SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0,
227 wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)),
228
229SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
230
231SND_SOC_DAPM_INPUT("MICN"),
232SND_SOC_DAPM_INPUT("MICP"),
233SND_SOC_DAPM_INPUT("AUX"),
234SND_SOC_DAPM_OUTPUT("MONOOUT"),
235SND_SOC_DAPM_OUTPUT("SPKOUTP"),
236SND_SOC_DAPM_OUTPUT("SPKOUTN"),
237};
238
239static const struct snd_soc_dapm_route audio_map[] = {
240 /* Mono output mixer */
241 {"Mono Mixer", "PCM Playback Switch", "DAC"},
242 {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
243 {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
244
245 /* Speaker output mixer */
246 {"Speaker Mixer", "PCM Playback Switch", "DAC"},
247 {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
248 {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
249
250 /* Outputs */
251 {"Mono Out", NULL, "Mono Mixer"},
252 {"MONOOUT", NULL, "Mono Out"},
253 {"SpkN Out", NULL, "Speaker Mixer"},
254 {"SpkP Out", NULL, "Speaker Mixer"},
255 {"SPKOUTN", NULL, "SpkN Out"},
256 {"SPKOUTP", NULL, "SpkP Out"},
257
258 /* Boost Mixer */
259 {"ADC", NULL, "Boost Mixer"},
260 {"Boost Mixer", "Aux Switch", "Aux Input"},
261 {"Boost Mixer", NULL, "Input PGA"},
262 {"Boost Mixer", NULL, "MICP"},
263
264 /* Input PGA */
265 {"Input PGA", "Aux Switch", "Aux Input"},
266 {"Input PGA", "MicN Switch", "MICN"},
267 {"Input PGA", "MicP Switch", "MICP"},
268
269 /* Inputs */
270 {"Aux Input", NULL, "AUX"},
271};
272
273static int wm8974_add_widgets(struct snd_soc_codec *codec)
274{
275 snd_soc_dapm_new_controls(codec, wm8974_dapm_widgets,
276 ARRAY_SIZE(wm8974_dapm_widgets));
277
278 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
279
280 snd_soc_dapm_new_widgets(codec);
281 return 0;
282}
283
284struct pll_ {
285 unsigned int pre_div:4; /* prescale - 1 */
286 unsigned int n:4;
287 unsigned int k;
288};
289
290static struct pll_ pll_div;
291
292/* The size in bits of the pll divide multiplied by 10
293 * to allow rounding later */
294#define FIXED_PLL_SIZE ((1 << 24) * 10)
295
296static void pll_factors(unsigned int target, unsigned int source)
297{
298 unsigned long long Kpart;
299 unsigned int K, Ndiv, Nmod;
300
301 Ndiv = target / source;
302 if (Ndiv < 6) {
303 source >>= 1;
304 pll_div.pre_div = 1;
305 Ndiv = target / source;
306 } else
307 pll_div.pre_div = 0;
308
309 if ((Ndiv < 6) || (Ndiv > 12))
310 printk(KERN_WARNING
311 "WM8974 N value %u outwith recommended range!\n",
312 Ndiv);
313
314 pll_div.n = Ndiv;
315 Nmod = target % source;
316 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
317
318 do_div(Kpart, source);
319
320 K = Kpart & 0xFFFFFFFF;
321
322 /* Check if we need to round */
323 if ((K % 10) >= 5)
324 K += 5;
325
326 /* Move down to proper range now rounding is done */
327 K /= 10;
328
329 pll_div.k = K;
330}
331
332static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai,
333 int pll_id, unsigned int freq_in, unsigned int freq_out)
334{
335 struct snd_soc_codec *codec = codec_dai->codec;
336 u16 reg;
337
338 if (freq_in == 0 || freq_out == 0) {
339 /* Clock CODEC directly from MCLK */
340 reg = snd_soc_read(codec, WM8974_CLOCK);
341 snd_soc_write(codec, WM8974_CLOCK, reg & 0x0ff);
342
343 /* Turn off PLL */
344 reg = snd_soc_read(codec, WM8974_POWER1);
345 snd_soc_write(codec, WM8974_POWER1, reg & 0x1df);
346 return 0;
347 }
348
349 pll_factors(freq_out*4, freq_in);
350
351 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n);
352 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);
353 snd_soc_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff);
354 snd_soc_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff);
355 reg = snd_soc_read(codec, WM8974_POWER1);
356 snd_soc_write(codec, WM8974_POWER1, reg | 0x020);
357
358 /* Run CODEC from PLL instead of MCLK */
359 reg = snd_soc_read(codec, WM8974_CLOCK);
360 snd_soc_write(codec, WM8974_CLOCK, reg | 0x100);
361
362 return 0;
363}
364
365/*
366 * Configure WM8974 clock dividers.
367 */
368static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
369 int div_id, int div)
370{
371 struct snd_soc_codec *codec = codec_dai->codec;
372 u16 reg;
373
374 switch (div_id) {
375 case WM8974_OPCLKDIV:
376 reg = snd_soc_read(codec, WM8974_GPIO) & 0x1cf;
377 snd_soc_write(codec, WM8974_GPIO, reg | div);
378 break;
379 case WM8974_MCLKDIV:
380 reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f;
381 snd_soc_write(codec, WM8974_CLOCK, reg | div);
382 break;
383 case WM8974_ADCCLK:
384 reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7;
385 snd_soc_write(codec, WM8974_ADC, reg | div);
386 break;
387 case WM8974_DACCLK:
388 reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7;
389 snd_soc_write(codec, WM8974_DAC, reg | div);
390 break;
391 case WM8974_BCLKDIV:
392 reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3;
393 snd_soc_write(codec, WM8974_CLOCK, reg | div);
394 break;
395 default:
396 return -EINVAL;
397 }
398
399 return 0;
400}
401
402static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai,
403 unsigned int fmt)
404{
405 struct snd_soc_codec *codec = codec_dai->codec;
406 u16 iface = 0;
407 u16 clk = snd_soc_read(codec, WM8974_CLOCK) & 0x1fe;
408
409 /* set master/slave audio interface */
410 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
411 case SND_SOC_DAIFMT_CBM_CFM:
412 clk |= 0x0001;
413 break;
414 case SND_SOC_DAIFMT_CBS_CFS:
415 break;
416 default:
417 return -EINVAL;
418 }
419
420 /* interface format */
421 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
422 case SND_SOC_DAIFMT_I2S:
423 iface |= 0x0010;
424 break;
425 case SND_SOC_DAIFMT_RIGHT_J:
426 break;
427 case SND_SOC_DAIFMT_LEFT_J:
428 iface |= 0x0008;
429 break;
430 case SND_SOC_DAIFMT_DSP_A:
431 iface |= 0x00018;
432 break;
433 default:
434 return -EINVAL;
435 }
436
437 /* clock inversion */
438 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
439 case SND_SOC_DAIFMT_NB_NF:
440 break;
441 case SND_SOC_DAIFMT_IB_IF:
442 iface |= 0x0180;
443 break;
444 case SND_SOC_DAIFMT_IB_NF:
445 iface |= 0x0100;
446 break;
447 case SND_SOC_DAIFMT_NB_IF:
448 iface |= 0x0080;
449 break;
450 default:
451 return -EINVAL;
452 }
453
454 snd_soc_write(codec, WM8974_IFACE, iface);
455 snd_soc_write(codec, WM8974_CLOCK, clk);
456 return 0;
457}
458
459static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream,
460 struct snd_pcm_hw_params *params,
461 struct snd_soc_dai *dai)
462{
463 struct snd_soc_codec *codec = dai->codec;
464 u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f;
465 u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1;
466
467 /* bit size */
468 switch (params_format(params)) {
469 case SNDRV_PCM_FORMAT_S16_LE:
470 break;
471 case SNDRV_PCM_FORMAT_S20_3LE:
472 iface |= 0x0020;
473 break;
474 case SNDRV_PCM_FORMAT_S24_LE:
475 iface |= 0x0040;
476 break;
477 case SNDRV_PCM_FORMAT_S32_LE:
478 iface |= 0x0060;
479 break;
480 }
481
482 /* filter coefficient */
483 switch (params_rate(params)) {
484 case SNDRV_PCM_RATE_8000:
485 adn |= 0x5 << 1;
486 break;
487 case SNDRV_PCM_RATE_11025:
488 adn |= 0x4 << 1;
489 break;
490 case SNDRV_PCM_RATE_16000:
491 adn |= 0x3 << 1;
492 break;
493 case SNDRV_PCM_RATE_22050:
494 adn |= 0x2 << 1;
495 break;
496 case SNDRV_PCM_RATE_32000:
497 adn |= 0x1 << 1;
498 break;
499 case SNDRV_PCM_RATE_44100:
500 case SNDRV_PCM_RATE_48000:
501 break;
502 }
503
504 snd_soc_write(codec, WM8974_IFACE, iface);
505 snd_soc_write(codec, WM8974_ADD, adn);
506 return 0;
507}
508
509static int wm8974_mute(struct snd_soc_dai *dai, int mute)
510{
511 struct snd_soc_codec *codec = dai->codec;
512 u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
513
514 if (mute)
515 snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
516 else
517 snd_soc_write(codec, WM8974_DAC, mute_reg);
518 return 0;
519}
520
521/* liam need to make this lower power with dapm */
522static int wm8974_set_bias_level(struct snd_soc_codec *codec,
523 enum snd_soc_bias_level level)
524{
525 u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3;
526
527 switch (level) {
528 case SND_SOC_BIAS_ON:
529 case SND_SOC_BIAS_PREPARE:
530 power1 |= 0x1; /* VMID 50k */
531 snd_soc_write(codec, WM8974_POWER1, power1);
532 break;
533
534 case SND_SOC_BIAS_STANDBY:
535 power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
536
537 if (codec->bias_level == SND_SOC_BIAS_OFF) {
538 /* Initial cap charge at VMID 5k */
539 snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
540 mdelay(100);
541 }
542
543 power1 |= 0x2; /* VMID 500k */
544 snd_soc_write(codec, WM8974_POWER1, power1);
545 break;
546
547 case SND_SOC_BIAS_OFF:
548 snd_soc_write(codec, WM8974_POWER1, 0);
549 snd_soc_write(codec, WM8974_POWER2, 0);
550 snd_soc_write(codec, WM8974_POWER3, 0);
551 break;
552 }
553
554 codec->bias_level = level;
555 return 0;
556}
557
558#define WM8974_RATES (SNDRV_PCM_RATE_8000_48000)
559
560#define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
561 SNDRV_PCM_FMTBIT_S24_LE)
562
563static struct snd_soc_dai_ops wm8974_ops = {
564 .hw_params = wm8974_pcm_hw_params,
565 .digital_mute = wm8974_mute,
566 .set_fmt = wm8974_set_dai_fmt,
567 .set_clkdiv = wm8974_set_dai_clkdiv,
568 .set_pll = wm8974_set_dai_pll,
569};
570
571struct snd_soc_dai wm8974_dai = {
572 .name = "WM8974 HiFi",
573 .playback = {
574 .stream_name = "Playback",
575 .channels_min = 1,
576 .channels_max = 2, /* Only 1 channel of data */
577 .rates = WM8974_RATES,
578 .formats = WM8974_FORMATS,},
579 .capture = {
580 .stream_name = "Capture",
581 .channels_min = 1,
582 .channels_max = 2, /* Only 1 channel of data */
583 .rates = WM8974_RATES,
584 .formats = WM8974_FORMATS,},
585 .ops = &wm8974_ops,
586 .symmetric_rates = 1,
587};
588EXPORT_SYMBOL_GPL(wm8974_dai);
589
590static int wm8974_suspend(struct platform_device *pdev, pm_message_t state)
591{
592 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
593 struct snd_soc_codec *codec = socdev->card->codec;
594
595 wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
596 return 0;
597}
598
599static int wm8974_resume(struct platform_device *pdev)
600{
601 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
602 struct snd_soc_codec *codec = socdev->card->codec;
603 int i;
604 u8 data[2];
605 u16 *cache = codec->reg_cache;
606
607 /* Sync reg_cache with the hardware */
608 for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
609 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
610 data[1] = cache[i] & 0x00ff;
611 codec->hw_write(codec->control_data, data, 2);
612 }
613 wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
614 wm8974_set_bias_level(codec, codec->suspend_bias_level);
615 return 0;
616}
617
618static int wm8974_probe(struct platform_device *pdev)
619{
620 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
621 struct snd_soc_codec *codec;
622 int ret = 0;
623
624 if (wm8974_codec == NULL) {
625 dev_err(&pdev->dev, "Codec device not registered\n");
626 return -ENODEV;
627 }
628
629 socdev->card->codec = wm8974_codec;
630 codec = wm8974_codec;
631
632 /* register pcms */
633 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
634 if (ret < 0) {
635 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
636 goto pcm_err;
637 }
638
639 snd_soc_add_controls(codec, wm8974_snd_controls,
640 ARRAY_SIZE(wm8974_snd_controls));
641 wm8974_add_widgets(codec);
642 ret = snd_soc_init_card(socdev);
643 if (ret < 0) {
644 dev_err(codec->dev, "failed to register card: %d\n", ret);
645 goto card_err;
646 }
647
648 return ret;
649
650card_err:
651 snd_soc_free_pcms(socdev);
652 snd_soc_dapm_free(socdev);
653pcm_err:
654 return ret;
655}
656
657/* power down chip */
658static int wm8974_remove(struct platform_device *pdev)
659{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661
662 snd_soc_free_pcms(socdev);
663 snd_soc_dapm_free(socdev);
664
665 return 0;
666}
667
668struct snd_soc_codec_device soc_codec_dev_wm8974 = {
669 .probe = wm8974_probe,
670 .remove = wm8974_remove,
671 .suspend = wm8974_suspend,
672 .resume = wm8974_resume,
673};
674EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974);
675
676static __devinit int wm8974_register(struct wm8974_priv *wm8974)
677{
678 int ret;
679 struct snd_soc_codec *codec = &wm8974->codec;
680
681 if (wm8974_codec) {
682 dev_err(codec->dev, "Another WM8974 is registered\n");
683 return -EINVAL;
684 }
685
686 mutex_init(&codec->mutex);
687 INIT_LIST_HEAD(&codec->dapm_widgets);
688 INIT_LIST_HEAD(&codec->dapm_paths);
689
690 codec->private_data = wm8974;
691 codec->name = "WM8974";
692 codec->owner = THIS_MODULE;
693 codec->bias_level = SND_SOC_BIAS_OFF;
694 codec->set_bias_level = wm8974_set_bias_level;
695 codec->dai = &wm8974_dai;
696 codec->num_dai = 1;
697 codec->reg_cache_size = WM8974_CACHEREGNUM;
698 codec->reg_cache = &wm8974->reg_cache;
699
700 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
701 if (ret < 0) {
702 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
703 goto err;
704 }
705
706 memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg));
707
708 ret = wm8974_reset(codec);
709 if (ret < 0) {
710 dev_err(codec->dev, "Failed to issue reset\n");
711 goto err;
712 }
713
714 wm8974_dai.dev = codec->dev;
715
716 wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
717
718 wm8974_codec = codec;
719
720 ret = snd_soc_register_codec(codec);
721 if (ret != 0) {
722 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
723 goto err;
724 }
725
726 ret = snd_soc_register_dai(&wm8974_dai);
727 if (ret != 0) {
728 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
729 goto err_codec;
730 }
731
732 return 0;
733
734err_codec:
735 snd_soc_unregister_codec(codec);
736err:
737 kfree(wm8974);
738 return ret;
739}
740
741static __devexit void wm8974_unregister(struct wm8974_priv *wm8974)
742{
743 wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF);
744 snd_soc_unregister_dai(&wm8974_dai);
745 snd_soc_unregister_codec(&wm8974->codec);
746 kfree(wm8974);
747 wm8974_codec = NULL;
748}
749
750static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
751 const struct i2c_device_id *id)
752{
753 struct wm8974_priv *wm8974;
754 struct snd_soc_codec *codec;
755
756 wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
757 if (wm8974 == NULL)
758 return -ENOMEM;
759
760 codec = &wm8974->codec;
761 codec->hw_write = (hw_write_t)i2c_master_send;
762
763 i2c_set_clientdata(i2c, wm8974);
764 codec->control_data = i2c;
765
766 codec->dev = &i2c->dev;
767
768 return wm8974_register(wm8974);
769}
770
771static __devexit int wm8974_i2c_remove(struct i2c_client *client)
772{
773 struct wm8974_priv *wm8974 = i2c_get_clientdata(client);
774 wm8974_unregister(wm8974);
775 return 0;
776}
777
778static const struct i2c_device_id wm8974_i2c_id[] = {
779 { "wm8974", 0 },
780 { }
781};
782MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
783
784static struct i2c_driver wm8974_i2c_driver = {
785 .driver = {
786 .name = "WM8974",
787 .owner = THIS_MODULE,
788 },
789 .probe = wm8974_i2c_probe,
790 .remove = __devexit_p(wm8974_i2c_remove),
791 .id_table = wm8974_i2c_id,
792};
793
794static int __init wm8974_modinit(void)
795{
796 return i2c_add_driver(&wm8974_i2c_driver);
797}
798module_init(wm8974_modinit);
799
800static void __exit wm8974_exit(void)
801{
802 i2c_del_driver(&wm8974_i2c_driver);
803}
804module_exit(wm8974_exit);
805
806MODULE_DESCRIPTION("ASoC WM8974 driver");
807MODULE_AUTHOR("Liam Girdwood");
808MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h
new file mode 100644
index 000000000000..98de9562d4d2
--- /dev/null
+++ b/sound/soc/codecs/wm8974.h
@@ -0,0 +1,99 @@
1/*
2 * wm8974.h -- WM8974 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 _WM8974_H
10#define _WM8974_H
11
12/* WM8974 register space */
13
14#define WM8974_RESET 0x0
15#define WM8974_POWER1 0x1
16#define WM8974_POWER2 0x2
17#define WM8974_POWER3 0x3
18#define WM8974_IFACE 0x4
19#define WM8974_COMP 0x5
20#define WM8974_CLOCK 0x6
21#define WM8974_ADD 0x7
22#define WM8974_GPIO 0x8
23#define WM8974_DAC 0xa
24#define WM8974_DACVOL 0xb
25#define WM8974_ADC 0xe
26#define WM8974_ADCVOL 0xf
27#define WM8974_EQ1 0x12
28#define WM8974_EQ2 0x13
29#define WM8974_EQ3 0x14
30#define WM8974_EQ4 0x15
31#define WM8974_EQ5 0x16
32#define WM8974_DACLIM1 0x18
33#define WM8974_DACLIM2 0x19
34#define WM8974_NOTCH1 0x1b
35#define WM8974_NOTCH2 0x1c
36#define WM8974_NOTCH3 0x1d
37#define WM8974_NOTCH4 0x1e
38#define WM8974_ALC1 0x20
39#define WM8974_ALC2 0x21
40#define WM8974_ALC3 0x22
41#define WM8974_NGATE 0x23
42#define WM8974_PLLN 0x24
43#define WM8974_PLLK1 0x25
44#define WM8974_PLLK2 0x26
45#define WM8974_PLLK3 0x27
46#define WM8974_ATTEN 0x28
47#define WM8974_INPUT 0x2c
48#define WM8974_INPPGA 0x2d
49#define WM8974_ADCBOOST 0x2f
50#define WM8974_OUTPUT 0x31
51#define WM8974_SPKMIX 0x32
52#define WM8974_SPKVOL 0x36
53#define WM8974_MONOMIX 0x38
54
55#define WM8974_CACHEREGNUM 57
56
57/* Clock divider Id's */
58#define WM8974_OPCLKDIV 0
59#define WM8974_MCLKDIV 1
60#define WM8974_ADCCLK 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
72/* PLL Out dividers */
73#define WM8974_OPCLKDIV_1 (0 << 4)
74#define WM8974_OPCLKDIV_2 (1 << 4)
75#define WM8974_OPCLKDIV_3 (2 << 4)
76#define WM8974_OPCLKDIV_4 (3 << 4)
77
78/* BCLK clock dividers */
79#define WM8974_BCLKDIV_1 (0 << 2)
80#define WM8974_BCLKDIV_2 (1 << 2)
81#define WM8974_BCLKDIV_4 (2 << 2)
82#define WM8974_BCLKDIV_8 (3 << 2)
83#define WM8974_BCLKDIV_16 (4 << 2)
84#define WM8974_BCLKDIV_32 (5 << 2)
85
86/* MCLK clock dividers */
87#define WM8974_MCLKDIV_1 (0 << 5)
88#define WM8974_MCLKDIV_1_5 (1 << 5)
89#define WM8974_MCLKDIV_2 (2 << 5)
90#define WM8974_MCLKDIV_3 (3 << 5)
91#define WM8974_MCLKDIV_4 (4 << 5)
92#define WM8974_MCLKDIV_6 (5 << 5)
93#define WM8974_MCLKDIV_8 (6 << 5)
94#define WM8974_MCLKDIV_12 (7 << 5)
95
96extern struct snd_soc_dai wm8974_dai;
97extern struct snd_soc_codec_device soc_codec_dev_wm8974;
98
99#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
new file mode 100644
index 000000000000..1c8653523c8c
--- /dev/null
+++ b/sound/soc/codecs/wm8988.c
@@ -0,0 +1,1069 @@
1/*
2 * wm8988.c -- WM8988 ALSA SoC audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License 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/spi/spi.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/tlv.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29
30#include "wm8988.h"
31
32/*
33 * wm8988 register cache
34 * We can't read the WM8988 register space when we
35 * are using 2 wire for device control, so we cache them instead.
36 */
37static const u16 wm8988_reg[] = {
38 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
39 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
40 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
41 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
42 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
43 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
44 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
45 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
46 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
47 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
48 0x0079, 0x0079, 0x0079, /* 40 */
49};
50
51/* codec private data */
52struct wm8988_priv {
53 unsigned int sysclk;
54 struct snd_soc_codec codec;
55 struct snd_pcm_hw_constraint_list *sysclk_constraints;
56 u16 reg_cache[WM8988_NUM_REG];
57};
58
59
60#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
61
62/*
63 * WM8988 Controls
64 */
65
66static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
67static const struct soc_enum bass_boost =
68 SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt);
69
70static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
71static const struct soc_enum bass_filter =
72 SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt);
73
74static const char *treble_txt[] = {"8kHz", "4kHz"};
75static const struct soc_enum treble =
76 SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt);
77
78static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
79static const struct soc_enum stereo_3d_lc =
80 SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt);
81
82static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
83static const struct soc_enum stereo_3d_uc =
84 SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt);
85
86static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
87static const struct soc_enum stereo_3d_func =
88 SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt);
89
90static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
91static const struct soc_enum alc_func =
92 SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt);
93
94static const char *ng_type_txt[] = {"Constant PGA Gain",
95 "Mute ADC Output"};
96static const struct soc_enum ng_type =
97 SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt);
98
99static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
100static const struct soc_enum deemph =
101 SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt);
102
103static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
104 "L + R Invert"};
105static const struct soc_enum adcpol =
106 SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt);
107
108static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
109static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
110static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
111static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
112static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
113
114static const struct snd_kcontrol_new wm8988_snd_controls[] = {
115
116SOC_ENUM("Bass Boost", bass_boost),
117SOC_ENUM("Bass Filter", bass_filter),
118SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1),
119
120SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0),
121SOC_ENUM("Treble Cut-off", treble),
122
123SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0),
124SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0),
125SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),
126SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),
127SOC_ENUM("3D Mode", stereo_3d_func),
128
129SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0),
130SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0),
131SOC_ENUM("ALC Capture Function", alc_func),
132SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0),
133SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0),
134SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0),
135SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0),
136SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0),
137SOC_ENUM("ALC Capture NG Type", ng_type),
138SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0),
139
140SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0),
141
142SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC,
143 0, 255, 0, adc_tlv),
144SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL,
145 0, 63, 0, pga_tlv),
146SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0),
147SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1),
148
149SOC_ENUM("Playback De-emphasis", deemph),
150
151SOC_ENUM("Capture Polarity", adcpol),
152SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0),
153SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0),
154
155SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv),
156
157SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1,
158 bypass_tlv),
159SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1,
160 bypass_tlv),
161SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1,
162 bypass_tlv),
163SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1,
164 bypass_tlv),
165
166SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V,
167 WM8988_ROUT1V, 7, 1, 0),
168SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V,
169 0, 127, 0, out_tlv),
170
171SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V,
172 WM8988_ROUT2V, 7, 1, 0),
173SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,
174 0, 127, 0, out_tlv),
175
176};
177
178/*
179 * DAPM Controls
180 */
181
182static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
183 struct snd_kcontrol *kcontrol, int event)
184{
185 struct snd_soc_codec *codec = w->codec;
186 u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
187
188 /* Use the DAC to gate LRC if active, otherwise use ADC */
189 if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
190 adctl2 &= ~0x4;
191 else
192 adctl2 |= 0x4;
193
194 return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
195}
196
197static const char *wm8988_line_texts[] = {
198 "Line 1", "Line 2", "PGA", "Differential"};
199
200static const unsigned int wm8988_line_values[] = {
201 0, 1, 3, 4};
202
203static const struct soc_enum wm8988_lline_enum =
204 SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7,
205 ARRAY_SIZE(wm8988_line_texts),
206 wm8988_line_texts,
207 wm8988_line_values);
208static const struct snd_kcontrol_new wm8988_left_line_controls =
209 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
210
211static const struct soc_enum wm8988_rline_enum =
212 SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,
213 ARRAY_SIZE(wm8988_line_texts),
214 wm8988_line_texts,
215 wm8988_line_values);
216static const struct snd_kcontrol_new wm8988_right_line_controls =
217 SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum);
218
219/* Left Mixer */
220static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {
221 SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0),
222 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0),
223 SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0),
224 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0),
225};
226
227/* Right Mixer */
228static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = {
229 SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0),
230 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0),
231 SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0),
232 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0),
233};
234
235static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"};
236static const unsigned int wm8988_pga_val[] = { 0, 1, 3 };
237
238/* Left PGA Mux */
239static const struct soc_enum wm8988_lpga_enum =
240 SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3,
241 ARRAY_SIZE(wm8988_pga_sel),
242 wm8988_pga_sel,
243 wm8988_pga_val);
244static const struct snd_kcontrol_new wm8988_left_pga_controls =
245 SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum);
246
247/* Right PGA Mux */
248static const struct soc_enum wm8988_rpga_enum =
249 SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3,
250 ARRAY_SIZE(wm8988_pga_sel),
251 wm8988_pga_sel,
252 wm8988_pga_val);
253static const struct snd_kcontrol_new wm8988_right_pga_controls =
254 SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum);
255
256/* Differential Mux */
257static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};
258static const struct soc_enum diffmux =
259 SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel);
260static const struct snd_kcontrol_new wm8988_diffmux_controls =
261 SOC_DAPM_ENUM("Route", diffmux);
262
263/* Mono ADC Mux */
264static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",
265 "Mono (Right)", "Digital Mono"};
266static const struct soc_enum monomux =
267 SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux);
268static const struct snd_kcontrol_new wm8988_monomux_controls =
269 SOC_DAPM_ENUM("Route", monomux);
270
271static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
272 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
273
274 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
275 &wm8988_diffmux_controls),
276 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
277 &wm8988_monomux_controls),
278 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
279 &wm8988_monomux_controls),
280
281 SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0,
282 &wm8988_left_pga_controls),
283 SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0,
284 &wm8988_right_pga_controls),
285
286 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
287 &wm8988_left_line_controls),
288 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
289 &wm8988_right_line_controls),
290
291 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0),
292 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0),
293
294 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0),
295 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0),
296
297 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
298 &wm8988_left_mixer_controls[0],
299 ARRAY_SIZE(wm8988_left_mixer_controls)),
300 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
301 &wm8988_right_mixer_controls[0],
302 ARRAY_SIZE(wm8988_right_mixer_controls)),
303
304 SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0),
305 SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0),
306 SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0),
307 SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0),
308
309 SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control),
310
311 SND_SOC_DAPM_OUTPUT("LOUT1"),
312 SND_SOC_DAPM_OUTPUT("ROUT1"),
313 SND_SOC_DAPM_OUTPUT("LOUT2"),
314 SND_SOC_DAPM_OUTPUT("ROUT2"),
315 SND_SOC_DAPM_OUTPUT("VREF"),
316
317 SND_SOC_DAPM_INPUT("LINPUT1"),
318 SND_SOC_DAPM_INPUT("LINPUT2"),
319 SND_SOC_DAPM_INPUT("RINPUT1"),
320 SND_SOC_DAPM_INPUT("RINPUT2"),
321};
322
323static const struct snd_soc_dapm_route audio_map[] = {
324
325 { "Left Line Mux", "Line 1", "LINPUT1" },
326 { "Left Line Mux", "Line 2", "LINPUT2" },
327 { "Left Line Mux", "PGA", "Left PGA Mux" },
328 { "Left Line Mux", "Differential", "Differential Mux" },
329
330 { "Right Line Mux", "Line 1", "RINPUT1" },
331 { "Right Line Mux", "Line 2", "RINPUT2" },
332 { "Right Line Mux", "PGA", "Right PGA Mux" },
333 { "Right Line Mux", "Differential", "Differential Mux" },
334
335 { "Left PGA Mux", "Line 1", "LINPUT1" },
336 { "Left PGA Mux", "Line 2", "LINPUT2" },
337 { "Left PGA Mux", "Differential", "Differential Mux" },
338
339 { "Right PGA Mux", "Line 1", "RINPUT1" },
340 { "Right PGA Mux", "Line 2", "RINPUT2" },
341 { "Right PGA Mux", "Differential", "Differential Mux" },
342
343 { "Differential Mux", "Line 1", "LINPUT1" },
344 { "Differential Mux", "Line 1", "RINPUT1" },
345 { "Differential Mux", "Line 2", "LINPUT2" },
346 { "Differential Mux", "Line 2", "RINPUT2" },
347
348 { "Left ADC Mux", "Stereo", "Left PGA Mux" },
349 { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
350 { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },
351
352 { "Right ADC Mux", "Stereo", "Right PGA Mux" },
353 { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },
354 { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },
355
356 { "Left ADC", NULL, "Left ADC Mux" },
357 { "Right ADC", NULL, "Right ADC Mux" },
358
359 { "Left Line Mux", "Line 1", "LINPUT1" },
360 { "Left Line Mux", "Line 2", "LINPUT2" },
361 { "Left Line Mux", "PGA", "Left PGA Mux" },
362 { "Left Line Mux", "Differential", "Differential Mux" },
363
364 { "Right Line Mux", "Line 1", "RINPUT1" },
365 { "Right Line Mux", "Line 2", "RINPUT2" },
366 { "Right Line Mux", "PGA", "Right PGA Mux" },
367 { "Right Line Mux", "Differential", "Differential Mux" },
368
369 { "Left Mixer", "Playback Switch", "Left DAC" },
370 { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
371 { "Left Mixer", "Right Playback Switch", "Right DAC" },
372 { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
373
374 { "Right Mixer", "Left Playback Switch", "Left DAC" },
375 { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
376 { "Right Mixer", "Playback Switch", "Right DAC" },
377 { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
378
379 { "Left Out 1", NULL, "Left Mixer" },
380 { "LOUT1", NULL, "Left Out 1" },
381 { "Right Out 1", NULL, "Right Mixer" },
382 { "ROUT1", NULL, "Right Out 1" },
383
384 { "Left Out 2", NULL, "Left Mixer" },
385 { "LOUT2", NULL, "Left Out 2" },
386 { "Right Out 2", NULL, "Right Mixer" },
387 { "ROUT2", NULL, "Right Out 2" },
388};
389
390struct _coeff_div {
391 u32 mclk;
392 u32 rate;
393 u16 fs;
394 u8 sr:5;
395 u8 usb:1;
396};
397
398/* codec hifi mclk clock divider coefficients */
399static const struct _coeff_div coeff_div[] = {
400 /* 8k */
401 {12288000, 8000, 1536, 0x6, 0x0},
402 {11289600, 8000, 1408, 0x16, 0x0},
403 {18432000, 8000, 2304, 0x7, 0x0},
404 {16934400, 8000, 2112, 0x17, 0x0},
405 {12000000, 8000, 1500, 0x6, 0x1},
406
407 /* 11.025k */
408 {11289600, 11025, 1024, 0x18, 0x0},
409 {16934400, 11025, 1536, 0x19, 0x0},
410 {12000000, 11025, 1088, 0x19, 0x1},
411
412 /* 16k */
413 {12288000, 16000, 768, 0xa, 0x0},
414 {18432000, 16000, 1152, 0xb, 0x0},
415 {12000000, 16000, 750, 0xa, 0x1},
416
417 /* 22.05k */
418 {11289600, 22050, 512, 0x1a, 0x0},
419 {16934400, 22050, 768, 0x1b, 0x0},
420 {12000000, 22050, 544, 0x1b, 0x1},
421
422 /* 32k */
423 {12288000, 32000, 384, 0xc, 0x0},
424 {18432000, 32000, 576, 0xd, 0x0},
425 {12000000, 32000, 375, 0xa, 0x1},
426
427 /* 44.1k */
428 {11289600, 44100, 256, 0x10, 0x0},
429 {16934400, 44100, 384, 0x11, 0x0},
430 {12000000, 44100, 272, 0x11, 0x1},
431
432 /* 48k */
433 {12288000, 48000, 256, 0x0, 0x0},
434 {18432000, 48000, 384, 0x1, 0x0},
435 {12000000, 48000, 250, 0x0, 0x1},
436
437 /* 88.2k */
438 {11289600, 88200, 128, 0x1e, 0x0},
439 {16934400, 88200, 192, 0x1f, 0x0},
440 {12000000, 88200, 136, 0x1f, 0x1},
441
442 /* 96k */
443 {12288000, 96000, 128, 0xe, 0x0},
444 {18432000, 96000, 192, 0xf, 0x0},
445 {12000000, 96000, 125, 0xe, 0x1},
446};
447
448static inline int get_coeff(int mclk, int rate)
449{
450 int i;
451
452 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
453 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
454 return i;
455 }
456
457 return -EINVAL;
458}
459
460/* The set of rates we can generate from the above for each SYSCLK */
461
462static unsigned int rates_12288[] = {
463 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
464};
465
466static struct snd_pcm_hw_constraint_list constraints_12288 = {
467 .count = ARRAY_SIZE(rates_12288),
468 .list = rates_12288,
469};
470
471static unsigned int rates_112896[] = {
472 8000, 11025, 22050, 44100,
473};
474
475static struct snd_pcm_hw_constraint_list constraints_112896 = {
476 .count = ARRAY_SIZE(rates_112896),
477 .list = rates_112896,
478};
479
480static unsigned int rates_12[] = {
481 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
482 48000, 88235, 96000,
483};
484
485static struct snd_pcm_hw_constraint_list constraints_12 = {
486 .count = ARRAY_SIZE(rates_12),
487 .list = rates_12,
488};
489
490/*
491 * Note that this should be called from init rather than from hw_params.
492 */
493static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
494 int clk_id, unsigned int freq, int dir)
495{
496 struct snd_soc_codec *codec = codec_dai->codec;
497 struct wm8988_priv *wm8988 = codec->private_data;
498
499 switch (freq) {
500 case 11289600:
501 case 18432000:
502 case 22579200:
503 case 36864000:
504 wm8988->sysclk_constraints = &constraints_112896;
505 wm8988->sysclk = freq;
506 return 0;
507
508 case 12288000:
509 case 16934400:
510 case 24576000:
511 case 33868800:
512 wm8988->sysclk_constraints = &constraints_12288;
513 wm8988->sysclk = freq;
514 return 0;
515
516 case 12000000:
517 case 24000000:
518 wm8988->sysclk_constraints = &constraints_12;
519 wm8988->sysclk = freq;
520 return 0;
521 }
522 return -EINVAL;
523}
524
525static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
526 unsigned int fmt)
527{
528 struct snd_soc_codec *codec = codec_dai->codec;
529 u16 iface = 0;
530
531 /* set master/slave audio interface */
532 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
533 case SND_SOC_DAIFMT_CBM_CFM:
534 iface = 0x0040;
535 break;
536 case SND_SOC_DAIFMT_CBS_CFS:
537 break;
538 default:
539 return -EINVAL;
540 }
541
542 /* interface format */
543 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
544 case SND_SOC_DAIFMT_I2S:
545 iface |= 0x0002;
546 break;
547 case SND_SOC_DAIFMT_RIGHT_J:
548 break;
549 case SND_SOC_DAIFMT_LEFT_J:
550 iface |= 0x0001;
551 break;
552 case SND_SOC_DAIFMT_DSP_A:
553 iface |= 0x0003;
554 break;
555 case SND_SOC_DAIFMT_DSP_B:
556 iface |= 0x0013;
557 break;
558 default:
559 return -EINVAL;
560 }
561
562 /* clock inversion */
563 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
564 case SND_SOC_DAIFMT_NB_NF:
565 break;
566 case SND_SOC_DAIFMT_IB_IF:
567 iface |= 0x0090;
568 break;
569 case SND_SOC_DAIFMT_IB_NF:
570 iface |= 0x0080;
571 break;
572 case SND_SOC_DAIFMT_NB_IF:
573 iface |= 0x0010;
574 break;
575 default:
576 return -EINVAL;
577 }
578
579 snd_soc_write(codec, WM8988_IFACE, iface);
580 return 0;
581}
582
583static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
584 struct snd_soc_dai *dai)
585{
586 struct snd_soc_codec *codec = dai->codec;
587 struct wm8988_priv *wm8988 = codec->private_data;
588
589 /* The set of sample rates that can be supported depends on the
590 * MCLK supplied to the CODEC - enforce this.
591 */
592 if (!wm8988->sysclk) {
593 dev_err(codec->dev,
594 "No MCLK configured, call set_sysclk() on init\n");
595 return -EINVAL;
596 }
597
598 snd_pcm_hw_constraint_list(substream->runtime, 0,
599 SNDRV_PCM_HW_PARAM_RATE,
600 wm8988->sysclk_constraints);
601
602 return 0;
603}
604
605static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
606 struct snd_pcm_hw_params *params,
607 struct snd_soc_dai *dai)
608{
609 struct snd_soc_pcm_runtime *rtd = substream->private_data;
610 struct snd_soc_device *socdev = rtd->socdev;
611 struct snd_soc_codec *codec = socdev->card->codec;
612 struct wm8988_priv *wm8988 = codec->private_data;
613 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
614 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
615 int coeff;
616
617 coeff = get_coeff(wm8988->sysclk, params_rate(params));
618 if (coeff < 0) {
619 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
620 srate |= 0x40;
621 }
622 if (coeff < 0) {
623 dev_err(codec->dev,
624 "Unable to configure sample rate %dHz with %dHz MCLK\n",
625 params_rate(params), wm8988->sysclk);
626 return coeff;
627 }
628
629 /* bit size */
630 switch (params_format(params)) {
631 case SNDRV_PCM_FORMAT_S16_LE:
632 break;
633 case SNDRV_PCM_FORMAT_S20_3LE:
634 iface |= 0x0004;
635 break;
636 case SNDRV_PCM_FORMAT_S24_LE:
637 iface |= 0x0008;
638 break;
639 case SNDRV_PCM_FORMAT_S32_LE:
640 iface |= 0x000c;
641 break;
642 }
643
644 /* set iface & srate */
645 snd_soc_write(codec, WM8988_IFACE, iface);
646 if (coeff >= 0)
647 snd_soc_write(codec, WM8988_SRATE, srate |
648 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
649
650 return 0;
651}
652
653static int wm8988_mute(struct snd_soc_dai *dai, int mute)
654{
655 struct snd_soc_codec *codec = dai->codec;
656 u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
657
658 if (mute)
659 snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
660 else
661 snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
662 return 0;
663}
664
665static int wm8988_set_bias_level(struct snd_soc_codec *codec,
666 enum snd_soc_bias_level level)
667{
668 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
669
670 switch (level) {
671 case SND_SOC_BIAS_ON:
672 break;
673
674 case SND_SOC_BIAS_PREPARE:
675 /* VREF, VMID=2x50k, digital enabled */
676 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
677 break;
678
679 case SND_SOC_BIAS_STANDBY:
680 if (codec->bias_level == SND_SOC_BIAS_OFF) {
681 /* VREF, VMID=2x5k */
682 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
683
684 /* Charge caps */
685 msleep(100);
686 }
687
688 /* VREF, VMID=2*500k, digital stopped */
689 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
690 break;
691
692 case SND_SOC_BIAS_OFF:
693 snd_soc_write(codec, WM8988_PWR1, 0x0000);
694 break;
695 }
696 codec->bias_level = level;
697 return 0;
698}
699
700#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
701
702#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
703 SNDRV_PCM_FMTBIT_S24_LE)
704
705static struct snd_soc_dai_ops wm8988_ops = {
706 .startup = wm8988_pcm_startup,
707 .hw_params = wm8988_pcm_hw_params,
708 .set_fmt = wm8988_set_dai_fmt,
709 .set_sysclk = wm8988_set_dai_sysclk,
710 .digital_mute = wm8988_mute,
711};
712
713struct snd_soc_dai wm8988_dai = {
714 .name = "WM8988",
715 .playback = {
716 .stream_name = "Playback",
717 .channels_min = 1,
718 .channels_max = 2,
719 .rates = WM8988_RATES,
720 .formats = WM8988_FORMATS,
721 },
722 .capture = {
723 .stream_name = "Capture",
724 .channels_min = 1,
725 .channels_max = 2,
726 .rates = WM8988_RATES,
727 .formats = WM8988_FORMATS,
728 },
729 .ops = &wm8988_ops,
730 .symmetric_rates = 1,
731};
732EXPORT_SYMBOL_GPL(wm8988_dai);
733
734static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
735{
736 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
737 struct snd_soc_codec *codec = socdev->card->codec;
738
739 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
740 return 0;
741}
742
743static int wm8988_resume(struct platform_device *pdev)
744{
745 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
746 struct snd_soc_codec *codec = socdev->card->codec;
747 int i;
748 u8 data[2];
749 u16 *cache = codec->reg_cache;
750
751 /* Sync reg_cache with the hardware */
752 for (i = 0; i < WM8988_NUM_REG; i++) {
753 if (i == WM8988_RESET)
754 continue;
755 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
756 data[1] = cache[i] & 0x00ff;
757 codec->hw_write(codec->control_data, data, 2);
758 }
759
760 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
761
762 return 0;
763}
764
765static struct snd_soc_codec *wm8988_codec;
766
767static int wm8988_probe(struct platform_device *pdev)
768{
769 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
770 struct snd_soc_codec *codec;
771 int ret = 0;
772
773 if (wm8988_codec == NULL) {
774 dev_err(&pdev->dev, "Codec device not registered\n");
775 return -ENODEV;
776 }
777
778 socdev->card->codec = wm8988_codec;
779 codec = wm8988_codec;
780
781 /* register pcms */
782 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
783 if (ret < 0) {
784 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
785 goto pcm_err;
786 }
787
788 snd_soc_add_controls(codec, wm8988_snd_controls,
789 ARRAY_SIZE(wm8988_snd_controls));
790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
791 ARRAY_SIZE(wm8988_dapm_widgets));
792 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
801 return ret;
802
803card_err:
804 snd_soc_free_pcms(socdev);
805 snd_soc_dapm_free(socdev);
806pcm_err:
807 return ret;
808}
809
810static int wm8988_remove(struct platform_device *pdev)
811{
812 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
813
814 snd_soc_free_pcms(socdev);
815 snd_soc_dapm_free(socdev);
816
817 return 0;
818}
819
820struct snd_soc_codec_device soc_codec_dev_wm8988 = {
821 .probe = wm8988_probe,
822 .remove = wm8988_remove,
823 .suspend = wm8988_suspend,
824 .resume = wm8988_resume,
825};
826EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
827
828static int wm8988_register(struct wm8988_priv *wm8988,
829 enum snd_soc_control_type control)
830{
831 struct snd_soc_codec *codec = &wm8988->codec;
832 int ret;
833 u16 reg;
834
835 if (wm8988_codec) {
836 dev_err(codec->dev, "Another WM8988 is registered\n");
837 ret = -EINVAL;
838 goto err;
839 }
840
841 mutex_init(&codec->mutex);
842 INIT_LIST_HEAD(&codec->dapm_widgets);
843 INIT_LIST_HEAD(&codec->dapm_paths);
844
845 codec->private_data = wm8988;
846 codec->name = "WM8988";
847 codec->owner = THIS_MODULE;
848 codec->dai = &wm8988_dai;
849 codec->num_dai = 1;
850 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
851 codec->reg_cache = &wm8988->reg_cache;
852 codec->bias_level = SND_SOC_BIAS_OFF;
853 codec->set_bias_level = wm8988_set_bias_level;
854
855 memcpy(codec->reg_cache, wm8988_reg,
856 sizeof(wm8988_reg));
857
858 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
859 if (ret < 0) {
860 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
861 goto err;
862 }
863
864 ret = wm8988_reset(codec);
865 if (ret < 0) {
866 dev_err(codec->dev, "Failed to issue reset\n");
867 goto err;
868 }
869
870 /* set the update bits (we always update left then right) */
871 reg = snd_soc_read(codec, WM8988_RADC);
872 snd_soc_write(codec, WM8988_RADC, reg | 0x100);
873 reg = snd_soc_read(codec, WM8988_RDAC);
874 snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
875 reg = snd_soc_read(codec, WM8988_ROUT1V);
876 snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
877 reg = snd_soc_read(codec, WM8988_ROUT2V);
878 snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
879 reg = snd_soc_read(codec, WM8988_RINVOL);
880 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
881
882 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
883
884 wm8988_dai.dev = codec->dev;
885
886 wm8988_codec = codec;
887
888 ret = snd_soc_register_codec(codec);
889 if (ret != 0) {
890 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
891 goto err;
892 }
893
894 ret = snd_soc_register_dai(&wm8988_dai);
895 if (ret != 0) {
896 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
897 snd_soc_unregister_codec(codec);
898 goto err_codec;
899 }
900
901 return 0;
902
903err_codec:
904 snd_soc_unregister_codec(codec);
905err:
906 kfree(wm8988);
907 return ret;
908}
909
910static void wm8988_unregister(struct wm8988_priv *wm8988)
911{
912 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
913 snd_soc_unregister_dai(&wm8988_dai);
914 snd_soc_unregister_codec(&wm8988->codec);
915 kfree(wm8988);
916 wm8988_codec = NULL;
917}
918
919#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
920static int wm8988_i2c_probe(struct i2c_client *i2c,
921 const struct i2c_device_id *id)
922{
923 struct wm8988_priv *wm8988;
924 struct snd_soc_codec *codec;
925
926 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
927 if (wm8988 == NULL)
928 return -ENOMEM;
929
930 codec = &wm8988->codec;
931
932 i2c_set_clientdata(i2c, wm8988);
933 codec->control_data = i2c;
934
935 codec->dev = &i2c->dev;
936
937 return wm8988_register(wm8988, SND_SOC_I2C);
938}
939
940static int wm8988_i2c_remove(struct i2c_client *client)
941{
942 struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
943 wm8988_unregister(wm8988);
944 return 0;
945}
946
947#ifdef CONFIG_PM
948static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
949{
950 return snd_soc_suspend_device(&client->dev);
951}
952
953static 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
962static const struct i2c_device_id wm8988_i2c_id[] = {
963 { "wm8988", 0 },
964 { }
965};
966MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
967
968static struct i2c_driver wm8988_i2c_driver = {
969 .driver = {
970 .name = "WM8988",
971 .owner = THIS_MODULE,
972 },
973 .probe = wm8988_i2c_probe,
974 .remove = wm8988_i2c_remove,
975 .suspend = wm8988_i2c_suspend,
976 .resume = wm8988_i2c_resume,
977 .id_table = wm8988_i2c_id,
978};
979#endif
980
981#if defined(CONFIG_SPI_MASTER)
982static int __devinit wm8988_spi_probe(struct spi_device *spi)
983{
984 struct wm8988_priv *wm8988;
985 struct snd_soc_codec *codec;
986
987 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
988 if (wm8988 == NULL)
989 return -ENOMEM;
990
991 codec = &wm8988->codec;
992 codec->control_data = spi;
993 codec->dev = &spi->dev;
994
995 spi->dev.driver_data = wm8988;
996
997 return wm8988_register(wm8988, SND_SOC_SPI);
998}
999
1000static int __devexit wm8988_spi_remove(struct spi_device *spi)
1001{
1002 struct wm8988_priv *wm8988 = spi->dev.driver_data;
1003
1004 wm8988_unregister(wm8988);
1005
1006 return 0;
1007}
1008
1009#ifdef CONFIG_PM
1010static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1011{
1012 return snd_soc_suspend_device(&spi->dev);
1013}
1014
1015static 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
1024static struct spi_driver wm8988_spi_driver = {
1025 .driver = {
1026 .name = "wm8988",
1027 .bus = &spi_bus_type,
1028 .owner = THIS_MODULE,
1029 },
1030 .probe = wm8988_spi_probe,
1031 .remove = __devexit_p(wm8988_spi_remove),
1032 .suspend = wm8988_spi_suspend,
1033 .resume = wm8988_spi_resume,
1034};
1035#endif
1036
1037static int __init wm8988_modinit(void)
1038{
1039 int ret;
1040
1041#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1042 ret = i2c_add_driver(&wm8988_i2c_driver);
1043 if (ret != 0)
1044 pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
1045#endif
1046#if defined(CONFIG_SPI_MASTER)
1047 ret = spi_register_driver(&wm8988_spi_driver);
1048 if (ret != 0)
1049 pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
1050#endif
1051 return ret;
1052}
1053module_init(wm8988_modinit);
1054
1055static void __exit wm8988_exit(void)
1056{
1057#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1058 i2c_del_driver(&wm8988_i2c_driver);
1059#endif
1060#if defined(CONFIG_SPI_MASTER)
1061 spi_unregister_driver(&wm8988_spi_driver);
1062#endif
1063}
1064module_exit(wm8988_exit);
1065
1066
1067MODULE_DESCRIPTION("ASoC WM8988 driver");
1068MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1069MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h
new file mode 100644
index 000000000000..4552d37fdd41
--- /dev/null
+++ b/sound/soc/codecs/wm8988.h
@@ -0,0 +1,60 @@
1/*
2 * Copyright 2005 Openedhand Ltd.
3 *
4 * Author: Richard Purdie <richard@openedhand.com>
5 *
6 * Based on WM8753.h
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
14#ifndef _WM8988_H
15#define _WM8988_H
16
17/* WM8988 register space */
18
19#define WM8988_LINVOL 0x00
20#define WM8988_RINVOL 0x01
21#define WM8988_LOUT1V 0x02
22#define WM8988_ROUT1V 0x03
23#define WM8988_ADCDAC 0x05
24#define WM8988_IFACE 0x07
25#define WM8988_SRATE 0x08
26#define WM8988_LDAC 0x0a
27#define WM8988_RDAC 0x0b
28#define WM8988_BASS 0x0c
29#define WM8988_TREBLE 0x0d
30#define WM8988_RESET 0x0f
31#define WM8988_3D 0x10
32#define WM8988_ALC1 0x11
33#define WM8988_ALC2 0x12
34#define WM8988_ALC3 0x13
35#define WM8988_NGATE 0x14
36#define WM8988_LADC 0x15
37#define WM8988_RADC 0x16
38#define WM8988_ADCTL1 0x17
39#define WM8988_ADCTL2 0x18
40#define WM8988_PWR1 0x19
41#define WM8988_PWR2 0x1a
42#define WM8988_ADCTL3 0x1b
43#define WM8988_ADCIN 0x1f
44#define WM8988_LADCIN 0x20
45#define WM8988_RADCIN 0x21
46#define WM8988_LOUTM1 0x22
47#define WM8988_LOUTM2 0x23
48#define WM8988_ROUTM1 0x24
49#define WM8988_ROUTM2 0x25
50#define WM8988_LOUT2V 0x28
51#define WM8988_ROUT2V 0x29
52#define WM8988_LPPB 0x43
53#define WM8988_NUM_REG 0x44
54
55#define WM8988_SYSCLK 0
56
57extern struct snd_soc_dai wm8988_dai;
58extern struct snd_soc_codec_device soc_codec_dev_wm8988;
59
60#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 40cd274eb1ef..2d702db4131d 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -108,53 +108,7 @@ static const u16 wm8990_reg[] = {
108 0x0000, /* R63 - Driver internal */ 108 0x0000, /* R63 - Driver internal */
109}; 109};
110 110
111/* 111#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
112 * read wm8990 register cache
113 */
114static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
115 unsigned int reg)
116{
117 u16 *cache = codec->reg_cache;
118 BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
119 return cache[reg];
120}
121
122/*
123 * write wm8990 register cache
124 */
125static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
126 unsigned int reg, unsigned int value)
127{
128 u16 *cache = codec->reg_cache;
129
130 /* Reset register and reserved registers are uncached */
131 if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
132 return;
133
134 cache[reg] = value;
135}
136
137/*
138 * write to the wm8990 register space
139 */
140static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
141 unsigned int value)
142{
143 u8 data[3];
144
145 data[0] = reg & 0xFF;
146 data[1] = (value >> 8) & 0xFF;
147 data[2] = value & 0xFF;
148
149 wm8990_write_reg_cache(codec, reg, value);
150
151 if (codec->hw_write(codec->control_data, data, 3) == 2)
152 return 0;
153 else
154 return -EIO;
155}
156
157#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
158 112
159static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); 113static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
160 114
@@ -187,8 +141,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
187 return ret; 141 return ret;
188 142
189 /* now hit the volume update bits (always bit 8) */ 143 /* now hit the volume update bits (always bit 8) */
190 val = wm8990_read_reg_cache(codec, reg); 144 val = snd_soc_read(codec, reg);
191 return wm8990_write(codec, reg, val | 0x0100); 145 return snd_soc_write(codec, reg, val | 0x0100);
192} 146}
193 147
194#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ 148#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
@@ -427,8 +381,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
427{ 381{
428 u16 reg, fakepower; 382 u16 reg, fakepower;
429 383
430 reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2); 384 reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2);
431 fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS); 385 fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
432 386
433 if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | 387 if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
434 (1 << WM8990_AINLMUX_PWR_BIT))) { 388 (1 << WM8990_AINLMUX_PWR_BIT))) {
@@ -443,7 +397,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
443 } else { 397 } else {
444 reg &= ~WM8990_AINL_ENA; 398 reg &= ~WM8990_AINL_ENA;
445 } 399 }
446 wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); 400 snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
447 401
448 return 0; 402 return 0;
449} 403}
@@ -457,7 +411,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
457 411
458 switch (reg_shift) { 412 switch (reg_shift) {
459 case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : 413 case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
460 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1); 414 reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1);
461 if (reg & WM8990_LDLO) { 415 if (reg & WM8990_LDLO) {
462 printk(KERN_WARNING 416 printk(KERN_WARNING
463 "Cannot set as Output Mixer 1 LDLO Set\n"); 417 "Cannot set as Output Mixer 1 LDLO Set\n");
@@ -465,7 +419,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
465 } 419 }
466 break; 420 break;
467 case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): 421 case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
468 reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2); 422 reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2);
469 if (reg & WM8990_RDRO) { 423 if (reg & WM8990_RDRO) {
470 printk(KERN_WARNING 424 printk(KERN_WARNING
471 "Cannot set as Output Mixer 2 RDRO Set\n"); 425 "Cannot set as Output Mixer 2 RDRO Set\n");
@@ -473,7 +427,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
473 } 427 }
474 break; 428 break;
475 case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): 429 case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
476 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 430 reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
477 if (reg & WM8990_LDSPK) { 431 if (reg & WM8990_LDSPK) {
478 printk(KERN_WARNING 432 printk(KERN_WARNING
479 "Cannot set as Speaker Mixer LDSPK Set\n"); 433 "Cannot set as Speaker Mixer LDSPK Set\n");
@@ -481,7 +435,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
481 } 435 }
482 break; 436 break;
483 case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): 437 case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
484 reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 438 reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
485 if (reg & WM8990_RDSPK) { 439 if (reg & WM8990_RDSPK) {
486 printk(KERN_WARNING 440 printk(KERN_WARNING
487 "Cannot set as Speaker Mixer RDSPK Set\n"); 441 "Cannot set as Speaker Mixer RDSPK Set\n");
@@ -998,7 +952,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
998 952
999 if ((Ndiv < 6) || (Ndiv > 12)) 953 if ((Ndiv < 6) || (Ndiv > 12))
1000 printk(KERN_WARNING 954 printk(KERN_WARNING
1001 "WM8990 N value outwith recommended range! N = %d\n", Ndiv); 955 "WM8990 N value outwith recommended range! N = %u\n", Ndiv);
1002 956
1003 pll_div->n = Ndiv; 957 pll_div->n = Ndiv;
1004 Nmod = target % source; 958 Nmod = target % source;
@@ -1029,24 +983,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
1029 pll_factors(&pll_div, freq_out * 4, freq_in); 983 pll_factors(&pll_div, freq_out * 4, freq_in);
1030 984
1031 /* Turn on PLL */ 985 /* Turn on PLL */
1032 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 986 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1033 reg |= WM8990_PLL_ENA; 987 reg |= WM8990_PLL_ENA;
1034 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 988 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1035 989
1036 /* sysclk comes from PLL */ 990 /* sysclk comes from PLL */
1037 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2); 991 reg = snd_soc_read(codec, WM8990_CLOCKING_2);
1038 wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); 992 snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
1039 993
1040 /* set up N , fractional mode and pre-divisor if neccessary */ 994 /* set up N , fractional mode and pre-divisor if neccessary */
1041 wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | 995 snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
1042 (pll_div.div2?WM8990_PRESCALE:0)); 996 (pll_div.div2?WM8990_PRESCALE:0));
1043 wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); 997 snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
1044 wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); 998 snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
1045 } else { 999 } else {
1046 /* Turn on PLL */ 1000 /* Turn on PLL */
1047 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1001 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1048 reg &= ~WM8990_PLL_ENA; 1002 reg &= ~WM8990_PLL_ENA;
1049 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 1003 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
1050 } 1004 }
1051 return 0; 1005 return 0;
1052} 1006}
@@ -1073,8 +1027,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
1073 struct snd_soc_codec *codec = codec_dai->codec; 1027 struct snd_soc_codec *codec = codec_dai->codec;
1074 u16 audio1, audio3; 1028 u16 audio1, audio3;
1075 1029
1076 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1030 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
1077 audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3); 1031 audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3);
1078 1032
1079 /* set master/slave audio interface */ 1033 /* set master/slave audio interface */
1080 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1034 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1115,8 +1069,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
1115 return -EINVAL; 1069 return -EINVAL;
1116 } 1070 }
1117 1071
1118 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1072 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1119 wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); 1073 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
1120 return 0; 1074 return 0;
1121} 1075}
1122 1076
@@ -1128,24 +1082,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1128 1082
1129 switch (div_id) { 1083 switch (div_id) {
1130 case WM8990_MCLK_DIV: 1084 case WM8990_MCLK_DIV:
1131 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1085 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1132 ~WM8990_MCLK_DIV_MASK; 1086 ~WM8990_MCLK_DIV_MASK;
1133 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1087 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1134 break; 1088 break;
1135 case WM8990_DACCLK_DIV: 1089 case WM8990_DACCLK_DIV:
1136 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1090 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1137 ~WM8990_DAC_CLKDIV_MASK; 1091 ~WM8990_DAC_CLKDIV_MASK;
1138 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1092 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1139 break; 1093 break;
1140 case WM8990_ADCCLK_DIV: 1094 case WM8990_ADCCLK_DIV:
1141 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1095 reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
1142 ~WM8990_ADC_CLKDIV_MASK; 1096 ~WM8990_ADC_CLKDIV_MASK;
1143 wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1097 snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
1144 break; 1098 break;
1145 case WM8990_BCLK_DIV: 1099 case WM8990_BCLK_DIV:
1146 reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) & 1100 reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
1147 ~WM8990_BCLK_DIV_MASK; 1101 ~WM8990_BCLK_DIV_MASK;
1148 wm8990_write(codec, WM8990_CLOCKING_1, reg | div); 1102 snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
1149 break; 1103 break;
1150 default: 1104 default:
1151 return -EINVAL; 1105 return -EINVAL;
@@ -1164,7 +1118,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
1164 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1165 struct snd_soc_device *socdev = rtd->socdev; 1119 struct snd_soc_device *socdev = rtd->socdev;
1166 struct snd_soc_codec *codec = socdev->card->codec; 1120 struct snd_soc_codec *codec = socdev->card->codec;
1167 u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1121 u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
1168 1122
1169 audio1 &= ~WM8990_AIF_WL_MASK; 1123 audio1 &= ~WM8990_AIF_WL_MASK;
1170 /* bit size */ 1124 /* bit size */
@@ -1182,7 +1136,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
1182 break; 1136 break;
1183 } 1137 }
1184 1138
1185 wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1139 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
1186 return 0; 1140 return 0;
1187} 1141}
1188 1142
@@ -1191,12 +1145,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
1191 struct snd_soc_codec *codec = dai->codec; 1145 struct snd_soc_codec *codec = dai->codec;
1192 u16 val; 1146 u16 val;
1193 1147
1194 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; 1148 val = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
1195 1149
1196 if (mute) 1150 if (mute)
1197 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1151 snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1198 else 1152 else
1199 wm8990_write(codec, WM8990_DAC_CTRL, val); 1153 snd_soc_write(codec, WM8990_DAC_CTRL, val);
1200 1154
1201 return 0; 1155 return 0;
1202} 1156}
@@ -1212,21 +1166,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1212 1166
1213 case SND_SOC_BIAS_PREPARE: 1167 case SND_SOC_BIAS_PREPARE:
1214 /* VMID=2*50k */ 1168 /* VMID=2*50k */
1215 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & 1169 val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
1216 ~WM8990_VMID_MODE_MASK; 1170 ~WM8990_VMID_MODE_MASK;
1217 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); 1171 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
1218 break; 1172 break;
1219 1173
1220 case SND_SOC_BIAS_STANDBY: 1174 case SND_SOC_BIAS_STANDBY:
1221 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1175 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1222 /* Enable all output discharge bits */ 1176 /* Enable all output discharge bits */
1223 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1177 snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1224 WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1178 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1225 WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1179 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1226 WM8990_DIS_ROUT); 1180 WM8990_DIS_ROUT);
1227 1181
1228 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ 1182 /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
1229 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1183 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1230 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1184 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1231 WM8990_VMIDTOG); 1185 WM8990_VMIDTOG);
1232 1186
@@ -1234,83 +1188,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1234 msleep(msecs_to_jiffies(300)); 1188 msleep(msecs_to_jiffies(300));
1235 1189
1236 /* Disable VMIDTOG */ 1190 /* Disable VMIDTOG */
1237 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1191 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1238 WM8990_BUFDCOPEN | WM8990_POBCTRL); 1192 WM8990_BUFDCOPEN | WM8990_POBCTRL);
1239 1193
1240 /* disable all output discharge bits */ 1194 /* disable all output discharge bits */
1241 wm8990_write(codec, WM8990_ANTIPOP1, 0); 1195 snd_soc_write(codec, WM8990_ANTIPOP1, 0);
1242 1196
1243 /* Enable outputs */ 1197 /* Enable outputs */
1244 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); 1198 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
1245 1199
1246 msleep(msecs_to_jiffies(50)); 1200 msleep(msecs_to_jiffies(50));
1247 1201
1248 /* Enable VMID at 2x50k */ 1202 /* Enable VMID at 2x50k */
1249 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); 1203 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
1250 1204
1251 msleep(msecs_to_jiffies(100)); 1205 msleep(msecs_to_jiffies(100));
1252 1206
1253 /* Enable VREF */ 1207 /* Enable VREF */
1254 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1208 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1255 1209
1256 msleep(msecs_to_jiffies(600)); 1210 msleep(msecs_to_jiffies(600));
1257 1211
1258 /* Enable BUFIOEN */ 1212 /* Enable BUFIOEN */
1259 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1213 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1260 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1214 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1261 WM8990_BUFIOEN); 1215 WM8990_BUFIOEN);
1262 1216
1263 /* Disable outputs */ 1217 /* Disable outputs */
1264 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); 1218 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
1265 1219
1266 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1220 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1267 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); 1221 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1268 1222
1269 /* Enable workaround for ADC clocking issue. */ 1223 /* Enable workaround for ADC clocking issue. */
1270 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); 1224 snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
1271 wm8990_write(codec, WM8990_EXT_CTL1, 0xa003); 1225 snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003);
1272 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0); 1226 snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0);
1273 } 1227 }
1274 1228
1275 /* VMID=2*250k */ 1229 /* VMID=2*250k */
1276 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & 1230 val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
1277 ~WM8990_VMID_MODE_MASK; 1231 ~WM8990_VMID_MODE_MASK;
1278 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); 1232 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
1279 break; 1233 break;
1280 1234
1281 case SND_SOC_BIAS_OFF: 1235 case SND_SOC_BIAS_OFF:
1282 /* Enable POBCTRL and SOFT_ST */ 1236 /* Enable POBCTRL and SOFT_ST */
1283 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1237 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1284 WM8990_POBCTRL | WM8990_BUFIOEN); 1238 WM8990_POBCTRL | WM8990_BUFIOEN);
1285 1239
1286 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ 1240 /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
1287 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1241 snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
1288 WM8990_BUFDCOPEN | WM8990_POBCTRL | 1242 WM8990_BUFDCOPEN | WM8990_POBCTRL |
1289 WM8990_BUFIOEN); 1243 WM8990_BUFIOEN);
1290 1244
1291 /* mute DAC */ 1245 /* mute DAC */
1292 val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL); 1246 val = snd_soc_read(codec, WM8990_DAC_CTRL);
1293 wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1247 snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
1294 1248
1295 /* Enable any disabled outputs */ 1249 /* Enable any disabled outputs */
1296 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1250 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
1297 1251
1298 /* Disable VMID */ 1252 /* Disable VMID */
1299 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); 1253 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
1300 1254
1301 msleep(msecs_to_jiffies(300)); 1255 msleep(msecs_to_jiffies(300));
1302 1256
1303 /* Enable all output discharge bits */ 1257 /* Enable all output discharge bits */
1304 wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1258 snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
1305 WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1259 WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
1306 WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1260 WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
1307 WM8990_DIS_ROUT); 1261 WM8990_DIS_ROUT);
1308 1262
1309 /* Disable VREF */ 1263 /* Disable VREF */
1310 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); 1264 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
1311 1265
1312 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1266 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1313 wm8990_write(codec, WM8990_ANTIPOP2, 0x0); 1267 snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
1314 break; 1268 break;
1315 } 1269 }
1316 1270
@@ -1411,8 +1365,6 @@ static int wm8990_init(struct snd_soc_device *socdev)
1411 1365
1412 codec->name = "WM8990"; 1366 codec->name = "WM8990";
1413 codec->owner = THIS_MODULE; 1367 codec->owner = THIS_MODULE;
1414 codec->read = wm8990_read_reg_cache;
1415 codec->write = wm8990_write;
1416 codec->set_bias_level = wm8990_set_bias_level; 1368 codec->set_bias_level = wm8990_set_bias_level;
1417 codec->dai = &wm8990_dai; 1369 codec->dai = &wm8990_dai;
1418 codec->num_dai = 2; 1370 codec->num_dai = 2;
@@ -1422,6 +1374,12 @@ static int wm8990_init(struct snd_soc_device *socdev)
1422 if (codec->reg_cache == NULL) 1374 if (codec->reg_cache == NULL)
1423 return -ENOMEM; 1375 return -ENOMEM;
1424 1376
1377 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1378 if (ret < 0) {
1379 printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
1380 goto pcm_err;
1381 }
1382
1425 wm8990_reset(codec); 1383 wm8990_reset(codec);
1426 1384
1427 /* register pcms */ 1385 /* register pcms */
@@ -1435,18 +1393,18 @@ static int wm8990_init(struct snd_soc_device *socdev)
1435 codec->bias_level = SND_SOC_BIAS_OFF; 1393 codec->bias_level = SND_SOC_BIAS_OFF;
1436 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1394 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1437 1395
1438 reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4); 1396 reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
1439 wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); 1397 snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
1440 1398
1441 reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) & 1399 reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
1442 ~WM8990_GPIO1_SEL_MASK; 1400 ~WM8990_GPIO1_SEL_MASK;
1443 wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1); 1401 snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
1444 1402
1445 reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1403 reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
1446 wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); 1404 snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
1447 1405
1448 wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1406 snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1449 wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1407 snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1450 1408
1451 snd_soc_add_controls(codec, wm8990_snd_controls, 1409 snd_soc_add_controls(codec, wm8990_snd_controls,
1452 ARRAY_SIZE(wm8990_snd_controls)); 1410 ARRAY_SIZE(wm8990_snd_controls));
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
new file mode 100644
index 000000000000..13befa338247
--- /dev/null
+++ b/sound/soc/codecs/wm8993.c
@@ -0,0 +1,1595 @@
1/*
2 * wm8993.c -- WM8993 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/spi/spi.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/tlv.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/wm8993.h>
28
29#include "wm8993.h"
30#include "wm_hubs.h"
31
32static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
33 0x8993, /* R0 - Software Reset */
34 0x0000, /* R1 - Power Management (1) */
35 0x6000, /* R2 - Power Management (2) */
36 0x0000, /* R3 - Power Management (3) */
37 0x4050, /* R4 - Audio Interface (1) */
38 0x4000, /* R5 - Audio Interface (2) */
39 0x01C8, /* R6 - Clocking 1 */
40 0x0000, /* R7 - Clocking 2 */
41 0x0000, /* R8 - Audio Interface (3) */
42 0x0040, /* R9 - Audio Interface (4) */
43 0x0004, /* R10 - DAC CTRL */
44 0x00C0, /* R11 - Left DAC Digital Volume */
45 0x00C0, /* R12 - Right DAC Digital Volume */
46 0x0000, /* R13 - Digital Side Tone */
47 0x0300, /* R14 - ADC CTRL */
48 0x00C0, /* R15 - Left ADC Digital Volume */
49 0x00C0, /* R16 - Right ADC Digital Volume */
50 0x0000, /* R17 */
51 0x0000, /* R18 - GPIO CTRL 1 */
52 0x0010, /* R19 - GPIO1 */
53 0x0000, /* R20 - IRQ_DEBOUNCE */
54 0x0000, /* R21 */
55 0x8000, /* R22 - GPIOCTRL 2 */
56 0x0800, /* R23 - GPIO_POL */
57 0x008B, /* R24 - Left Line Input 1&2 Volume */
58 0x008B, /* R25 - Left Line Input 3&4 Volume */
59 0x008B, /* R26 - Right Line Input 1&2 Volume */
60 0x008B, /* R27 - Right Line Input 3&4 Volume */
61 0x006D, /* R28 - Left Output Volume */
62 0x006D, /* R29 - Right Output Volume */
63 0x0066, /* R30 - Line Outputs Volume */
64 0x0020, /* R31 - HPOUT2 Volume */
65 0x0079, /* R32 - Left OPGA Volume */
66 0x0079, /* R33 - Right OPGA Volume */
67 0x0003, /* R34 - SPKMIXL Attenuation */
68 0x0003, /* R35 - SPKMIXR Attenuation */
69 0x0011, /* R36 - SPKOUT Mixers */
70 0x0100, /* R37 - SPKOUT Boost */
71 0x0079, /* R38 - Speaker Volume Left */
72 0x0079, /* R39 - Speaker Volume Right */
73 0x0000, /* R40 - Input Mixer2 */
74 0x0000, /* R41 - Input Mixer3 */
75 0x0000, /* R42 - Input Mixer4 */
76 0x0000, /* R43 - Input Mixer5 */
77 0x0000, /* R44 - Input Mixer6 */
78 0x0000, /* R45 - Output Mixer1 */
79 0x0000, /* R46 - Output Mixer2 */
80 0x0000, /* R47 - Output Mixer3 */
81 0x0000, /* R48 - Output Mixer4 */
82 0x0000, /* R49 - Output Mixer5 */
83 0x0000, /* R50 - Output Mixer6 */
84 0x0000, /* R51 - HPOUT2 Mixer */
85 0x0000, /* R52 - Line Mixer1 */
86 0x0000, /* R53 - Line Mixer2 */
87 0x0000, /* R54 - Speaker Mixer */
88 0x0000, /* R55 - Additional Control */
89 0x0000, /* R56 - AntiPOP1 */
90 0x0000, /* R57 - AntiPOP2 */
91 0x0000, /* R58 - MICBIAS */
92 0x0000, /* R59 */
93 0x0000, /* R60 - FLL Control 1 */
94 0x0000, /* R61 - FLL Control 2 */
95 0x0000, /* R62 - FLL Control 3 */
96 0x2EE0, /* R63 - FLL Control 4 */
97 0x0002, /* R64 - FLL Control 5 */
98 0x2287, /* R65 - Clocking 3 */
99 0x025F, /* R66 - Clocking 4 */
100 0x0000, /* R67 - MW Slave Control */
101 0x0000, /* R68 */
102 0x0002, /* R69 - Bus Control 1 */
103 0x0000, /* R70 - Write Sequencer 0 */
104 0x0000, /* R71 - Write Sequencer 1 */
105 0x0000, /* R72 - Write Sequencer 2 */
106 0x0000, /* R73 - Write Sequencer 3 */
107 0x0000, /* R74 - Write Sequencer 4 */
108 0x0000, /* R75 - Write Sequencer 5 */
109 0x1F25, /* R76 - Charge Pump 1 */
110 0x0000, /* R77 */
111 0x0000, /* R78 */
112 0x0000, /* R79 */
113 0x0000, /* R80 */
114 0x0000, /* R81 - Class W 0 */
115 0x0000, /* R82 */
116 0x0000, /* R83 */
117 0x0000, /* R84 - DC Servo 0 */
118 0x054A, /* R85 - DC Servo 1 */
119 0x0000, /* R86 */
120 0x0000, /* R87 - DC Servo 3 */
121 0x0000, /* R88 - DC Servo Readback 0 */
122 0x0000, /* R89 - DC Servo Readback 1 */
123 0x0000, /* R90 - DC Servo Readback 2 */
124 0x0000, /* R91 */
125 0x0000, /* R92 */
126 0x0000, /* R93 */
127 0x0000, /* R94 */
128 0x0000, /* R95 */
129 0x0100, /* R96 - Analogue HP 0 */
130 0x0000, /* R97 */
131 0x0000, /* R98 - EQ1 */
132 0x000C, /* R99 - EQ2 */
133 0x000C, /* R100 - EQ3 */
134 0x000C, /* R101 - EQ4 */
135 0x000C, /* R102 - EQ5 */
136 0x000C, /* R103 - EQ6 */
137 0x0FCA, /* R104 - EQ7 */
138 0x0400, /* R105 - EQ8 */
139 0x00D8, /* R106 - EQ9 */
140 0x1EB5, /* R107 - EQ10 */
141 0xF145, /* R108 - EQ11 */
142 0x0B75, /* R109 - EQ12 */
143 0x01C5, /* R110 - EQ13 */
144 0x1C58, /* R111 - EQ14 */
145 0xF373, /* R112 - EQ15 */
146 0x0A54, /* R113 - EQ16 */
147 0x0558, /* R114 - EQ17 */
148 0x168E, /* R115 - EQ18 */
149 0xF829, /* R116 - EQ19 */
150 0x07AD, /* R117 - EQ20 */
151 0x1103, /* R118 - EQ21 */
152 0x0564, /* R119 - EQ22 */
153 0x0559, /* R120 - EQ23 */
154 0x4000, /* R121 - EQ24 */
155 0x0000, /* R122 - Digital Pulls */
156 0x0F08, /* R123 - DRC Control 1 */
157 0x0000, /* R124 - DRC Control 2 */
158 0x0080, /* R125 - DRC Control 3 */
159 0x0000, /* R126 - DRC Control 4 */
160};
161
162static struct {
163 int ratio;
164 int clk_sys_rate;
165} clk_sys_rates[] = {
166 { 64, 0 },
167 { 128, 1 },
168 { 192, 2 },
169 { 256, 3 },
170 { 384, 4 },
171 { 512, 5 },
172 { 768, 6 },
173 { 1024, 7 },
174 { 1408, 8 },
175 { 1536, 9 },
176};
177
178static struct {
179 int rate;
180 int sample_rate;
181} sample_rates[] = {
182 { 8000, 0 },
183 { 11025, 1 },
184 { 12000, 1 },
185 { 16000, 2 },
186 { 22050, 3 },
187 { 24000, 3 },
188 { 32000, 4 },
189 { 44100, 5 },
190 { 48000, 5 },
191};
192
193static struct {
194 int div; /* *10 due to .5s */
195 int bclk_div;
196} bclk_divs[] = {
197 { 10, 0 },
198 { 15, 1 },
199 { 20, 2 },
200 { 30, 3 },
201 { 40, 4 },
202 { 55, 5 },
203 { 60, 6 },
204 { 80, 7 },
205 { 110, 8 },
206 { 120, 9 },
207 { 160, 10 },
208 { 220, 11 },
209 { 240, 12 },
210 { 320, 13 },
211 { 440, 14 },
212 { 480, 15 },
213};
214
215struct wm8993_priv {
216 u16 reg_cache[WM8993_REGISTER_COUNT];
217 struct wm8993_platform_data pdata;
218 struct snd_soc_codec codec;
219 int master;
220 int sysclk_source;
221 int tdm_slots;
222 int tdm_width;
223 unsigned int mclk_rate;
224 unsigned int sysclk_rate;
225 unsigned int fs;
226 unsigned int bclk;
227 int class_w_users;
228 unsigned int fll_fref;
229 unsigned int fll_fout;
230};
231
232static 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 = &reg;
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
260static int wm8993_volatile(unsigned int reg)
261{
262 switch (reg) {
263 case WM8993_SOFTWARE_RESET:
264 case WM8993_DC_SERVO_0:
265 case WM8993_DC_SERVO_READBACK_0:
266 case WM8993_DC_SERVO_READBACK_1:
267 case WM8993_DC_SERVO_READBACK_2:
268 return 1;
269 default:
270 return 0;
271 }
272}
273
274static 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
287static 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
316struct _fll_div {
317 u16 fll_fratio;
318 u16 fll_outdiv;
319 u16 fll_clk_ref_div;
320 u16 n;
321 u16 k;
322};
323
324/* The size in bits of the FLL divide multiplied by 10
325 * to allow rounding later */
326#define FIXED_FLL_SIZE ((1 << 16) * 10)
327
328static struct {
329 unsigned int min;
330 unsigned int max;
331 u16 fll_fratio;
332 int ratio;
333} fll_fratios[] = {
334 { 0, 64000, 4, 16 },
335 { 64000, 128000, 3, 8 },
336 { 128000, 256000, 2, 4 },
337 { 256000, 1000000, 1, 2 },
338 { 1000000, 13500000, 0, 1 },
339};
340
341static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
342 unsigned int Fout)
343{
344 u64 Kpart;
345 unsigned int K, Ndiv, Nmod, target;
346 unsigned int div;
347 int i;
348
349 /* Fref must be <=13.5MHz */
350 div = 1;
351 fll_div->fll_clk_ref_div = 0;
352 while ((Fref / div) > 13500000) {
353 div *= 2;
354 fll_div->fll_clk_ref_div++;
355
356 if (div > 8) {
357 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
358 Fref);
359 return -EINVAL;
360 }
361 }
362
363 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
364
365 /* Apply the division for our remaining calculations */
366 Fref /= div;
367
368 /* Fvco should be 90-100MHz; don't check the upper bound */
369 div = 0;
370 target = Fout * 2;
371 while (target < 90000000) {
372 div++;
373 target *= 2;
374 if (div > 7) {
375 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
376 Fout);
377 return -EINVAL;
378 }
379 }
380 fll_div->fll_outdiv = div;
381
382 pr_debug("Fvco=%dHz\n", target);
383
384 /* Find an appropraite FLL_FRATIO and factor it out of the target */
385 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
386 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
387 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
388 target /= fll_fratios[i].ratio;
389 break;
390 }
391 }
392 if (i == ARRAY_SIZE(fll_fratios)) {
393 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
394 return -EINVAL;
395 }
396
397 /* Now, calculate N.K */
398 Ndiv = target / Fref;
399
400 fll_div->n = Ndiv;
401 Nmod = target % Fref;
402 pr_debug("Nmod=%d\n", Nmod);
403
404 /* Calculate fractional part - scale up so we can round. */
405 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
406
407 do_div(Kpart, Fref);
408
409 K = Kpart & 0xFFFFFFFF;
410
411 if ((K % 10) >= 5)
412 K += 5;
413
414 /* Move down to proper range now rounding is done */
415 fll_div->k = K / 10;
416
417 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
418 fll_div->n, fll_div->k,
419 fll_div->fll_fratio, fll_div->fll_outdiv,
420 fll_div->fll_clk_ref_div);
421
422 return 0;
423}
424
425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id,
426 unsigned int Fref, unsigned int Fout)
427{
428 struct snd_soc_codec *codec = dai->codec;
429 struct wm8993_priv *wm8993 = codec->private_data;
430 u16 reg1, reg4, reg5;
431 struct _fll_div fll_div;
432 int ret;
433
434 /* Any change? */
435 if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout)
436 return 0;
437
438 /* Disable the FLL */
439 if (Fout == 0) {
440 dev_dbg(codec->dev, "FLL disabled\n");
441 wm8993->fll_fref = 0;
442 wm8993->fll_fout = 0;
443
444 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
445 reg1 &= ~WM8993_FLL_ENA;
446 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
447
448 return 0;
449 }
450
451 ret = fll_factors(&fll_div, Fref, Fout);
452 if (ret != 0)
453 return ret;
454
455 reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5);
456 reg5 &= ~WM8993_FLL_CLK_SRC_MASK;
457
458 switch (fll_id) {
459 case WM8993_FLL_MCLK:
460 break;
461
462 case WM8993_FLL_LRCLK:
463 reg5 |= 1;
464 break;
465
466 case WM8993_FLL_BCLK:
467 reg5 |= 2;
468 break;
469
470 default:
471 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
472 return -EINVAL;
473 }
474
475 /* Any FLL configuration change requires that the FLL be
476 * disabled first. */
477 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
478 reg1 &= ~WM8993_FLL_ENA;
479 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
480
481 /* Apply the configuration */
482 if (fll_div.k)
483 reg1 |= WM8993_FLL_FRAC_MASK;
484 else
485 reg1 &= ~WM8993_FLL_FRAC_MASK;
486 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
487
488 wm8993_write(codec, WM8993_FLL_CONTROL_2,
489 (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) |
490 (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT));
491 wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k);
492
493 reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4);
494 reg4 &= ~WM8993_FLL_N_MASK;
495 reg4 |= fll_div.n << WM8993_FLL_N_SHIFT;
496 wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4);
497
498 reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK;
499 reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
500 wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5);
501
502 /* Enable the FLL */
503 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
504
505 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
506
507 wm8993->fll_fref = Fref;
508 wm8993->fll_fout = Fout;
509
510 return 0;
511}
512
513static int configure_clock(struct snd_soc_codec *codec)
514{
515 struct wm8993_priv *wm8993 = codec->private_data;
516 unsigned int reg;
517
518 /* This should be done on init() for bypass paths */
519 switch (wm8993->sysclk_source) {
520 case WM8993_SYSCLK_MCLK:
521 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate);
522
523 reg = wm8993_read(codec, WM8993_CLOCKING_2);
524 reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC);
525 if (wm8993->mclk_rate > 13500000) {
526 reg |= WM8993_MCLK_DIV;
527 wm8993->sysclk_rate = wm8993->mclk_rate / 2;
528 } else {
529 reg &= ~WM8993_MCLK_DIV;
530 wm8993->sysclk_rate = wm8993->mclk_rate;
531 }
532 wm8993_write(codec, WM8993_CLOCKING_2, reg);
533 break;
534
535 case WM8993_SYSCLK_FLL:
536 dev_dbg(codec->dev, "Using %dHz FLL clock\n",
537 wm8993->fll_fout);
538
539 reg = wm8993_read(codec, WM8993_CLOCKING_2);
540 reg |= WM8993_SYSCLK_SRC;
541 if (wm8993->fll_fout > 13500000) {
542 reg |= WM8993_MCLK_DIV;
543 wm8993->sysclk_rate = wm8993->fll_fout / 2;
544 } else {
545 reg &= ~WM8993_MCLK_DIV;
546 wm8993->sysclk_rate = wm8993->fll_fout;
547 }
548 wm8993_write(codec, WM8993_CLOCKING_2, reg);
549 break;
550
551 default:
552 dev_err(codec->dev, "System clock not configured\n");
553 return -EINVAL;
554 }
555
556 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate);
557
558 return 0;
559}
560
561static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
562static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
563static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
564static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
565static const unsigned int drc_max_tlv[] = {
566 TLV_DB_RANGE_HEAD(4),
567 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
568 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
569};
570static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
571static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
572static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
573static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
574static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
575
576static const char *dac_deemph_text[] = {
577 "None",
578 "32kHz",
579 "44.1kHz",
580 "48kHz",
581};
582
583static const struct soc_enum dac_deemph =
584 SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text);
585
586static const char *adc_hpf_text[] = {
587 "Hi-Fi",
588 "Voice 1",
589 "Voice 2",
590 "Voice 3",
591};
592
593static const struct soc_enum adc_hpf =
594 SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text);
595
596static const char *drc_path_text[] = {
597 "ADC",
598 "DAC"
599};
600
601static const struct soc_enum drc_path =
602 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);
603
604static const char *drc_r0_text[] = {
605 "1",
606 "1/2",
607 "1/4",
608 "1/8",
609 "1/16",
610 "0",
611};
612
613static const struct soc_enum drc_r0 =
614 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text);
615
616static const char *drc_r1_text[] = {
617 "1",
618 "1/2",
619 "1/4",
620 "1/8",
621 "0",
622};
623
624static const struct soc_enum drc_r1 =
625 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text);
626
627static const char *drc_attack_text[] = {
628 "Reserved",
629 "181us",
630 "363us",
631 "726us",
632 "1.45ms",
633 "2.9ms",
634 "5.8ms",
635 "11.6ms",
636 "23.2ms",
637 "46.4ms",
638 "92.8ms",
639 "185.6ms",
640};
641
642static const struct soc_enum drc_attack =
643 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text);
644
645static const char *drc_decay_text[] = {
646 "186ms",
647 "372ms",
648 "743ms",
649 "1.49s",
650 "2.97ms",
651 "5.94ms",
652 "11.89ms",
653 "23.78ms",
654 "47.56ms",
655};
656
657static const struct soc_enum drc_decay =
658 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text);
659
660static const char *drc_ff_text[] = {
661 "5 samples",
662 "9 samples",
663};
664
665static const struct soc_enum drc_ff =
666 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text);
667
668static const char *drc_qr_rate_text[] = {
669 "0.725ms",
670 "1.45ms",
671 "5.8ms",
672};
673
674static const struct soc_enum drc_qr_rate =
675 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text);
676
677static const char *drc_smooth_text[] = {
678 "Low",
679 "Medium",
680 "High",
681};
682
683static const struct soc_enum drc_smooth =
684 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text);
685
686static const struct snd_kcontrol_new wm8993_snd_controls[] = {
687SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE,
688 5, 9, 12, 0, sidetone_tlv),
689
690SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0),
691SOC_ENUM("DRC Path", drc_path),
692SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2,
693 2, 60, 1, drc_comp_threash),
694SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3,
695 11, 30, 1, drc_comp_amp),
696SOC_ENUM("DRC R0", drc_r0),
697SOC_ENUM("DRC R1", drc_r1),
698SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1,
699 drc_min_tlv),
700SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0,
701 drc_max_tlv),
702SOC_ENUM("DRC Attack Rate", drc_attack),
703SOC_ENUM("DRC Decay Rate", drc_decay),
704SOC_ENUM("DRC FF Delay", drc_ff),
705SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0),
706SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0),
707SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0,
708 drc_qr_tlv),
709SOC_ENUM("DRC Quick Release Rate", drc_qr_rate),
710SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0),
711SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0),
712SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth),
713SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0,
714 drc_startup_tlv),
715
716SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0),
717
718SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME,
719 WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
720SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0),
721SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
722
723SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME,
724 WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
725SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0,
726 dac_boost_tlv),
727SOC_ENUM("DAC Deemphasis", dac_deemph),
728
729SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION,
730 2, 1, 1, wm_hubs_spkmix_tlv),
731
732SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION,
733 2, 1, 1, wm_hubs_spkmix_tlv),
734};
735
736static const struct snd_kcontrol_new wm8993_eq_controls[] = {
737SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv),
738SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv),
739SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv),
740SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv),
741SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv),
742};
743
744static int clk_sys_event(struct snd_soc_dapm_widget *w,
745 struct snd_kcontrol *kcontrol, int event)
746{
747 struct snd_soc_codec *codec = w->codec;
748
749 switch (event) {
750 case SND_SOC_DAPM_PRE_PMU:
751 return configure_clock(codec);
752
753 case SND_SOC_DAPM_POST_PMD:
754 break;
755 }
756
757 return 0;
758}
759
760/*
761 * When used with DAC outputs only the WM8993 charge pump supports
762 * operation in class W mode, providing very low power consumption
763 * when used with digital sources. Enable and disable this mode
764 * automatically depending on the mixer configuration.
765 *
766 * Currently the only supported paths are the direct DAC->headphone
767 * paths (which provide minimum power consumption anyway).
768 */
769static int class_w_put(struct snd_kcontrol *kcontrol,
770 struct snd_ctl_elem_value *ucontrol)
771{
772 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
773 struct snd_soc_codec *codec = widget->codec;
774 struct wm8993_priv *wm8993 = codec->private_data;
775 int ret;
776
777 /* Turn it off if we're using the main output mixer */
778 if (ucontrol->value.integer.value[0] == 0) {
779 if (wm8993->class_w_users == 0) {
780 dev_dbg(codec->dev, "Disabling Class W\n");
781 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
782 WM8993_CP_DYN_FREQ |
783 WM8993_CP_DYN_V,
784 0);
785 }
786 wm8993->class_w_users++;
787 }
788
789 /* Implement the change */
790 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
791
792 /* Enable it if we're using the direct DAC path */
793 if (ucontrol->value.integer.value[0] == 1) {
794 if (wm8993->class_w_users == 1) {
795 dev_dbg(codec->dev, "Enabling Class W\n");
796 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
797 WM8993_CP_DYN_FREQ |
798 WM8993_CP_DYN_V,
799 WM8993_CP_DYN_FREQ |
800 WM8993_CP_DYN_V);
801 }
802 wm8993->class_w_users--;
803 }
804
805 dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
806 wm8993->class_w_users);
807
808 return ret;
809}
810
811#define SOC_DAPM_ENUM_W(xname, xenum) \
812{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
813 .info = snd_soc_info_enum_double, \
814 .get = snd_soc_dapm_get_enum_double, \
815 .put = class_w_put, \
816 .private_value = (unsigned long)&xenum }
817
818static const char *hp_mux_text[] = {
819 "Mixer",
820 "DAC",
821};
822
823static const struct soc_enum hpl_enum =
824 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
825
826static const struct snd_kcontrol_new hpl_mux =
827 SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
828
829static const struct soc_enum hpr_enum =
830 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
831
832static const struct snd_kcontrol_new hpr_mux =
833 SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
834
835static const struct snd_kcontrol_new left_speaker_mixer[] = {
836SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
837SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
838SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0),
839SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
840};
841
842static const struct snd_kcontrol_new right_speaker_mixer[] = {
843SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
844SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0),
845SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0),
846SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0),
847};
848
849static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {
850SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
851 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
852SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
853SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
854
855
856SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
857SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
858
859SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
860SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
861
862SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
863SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
864
865SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
866 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
867SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0,
868 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
869
870};
871
872static const struct snd_soc_dapm_route routes[] = {
873 { "ADCL", NULL, "CLK_SYS" },
874 { "ADCL", NULL, "CLK_DSP" },
875 { "ADCR", NULL, "CLK_SYS" },
876 { "ADCR", NULL, "CLK_DSP" },
877
878 { "DACL", NULL, "CLK_SYS" },
879 { "DACL", NULL, "CLK_DSP" },
880 { "DACR", NULL, "CLK_SYS" },
881 { "DACR", NULL, "CLK_DSP" },
882
883 { "Left Output Mixer", "DAC Switch", "DACL" },
884
885 { "Right Output Mixer", "DAC Switch", "DACR" },
886
887 { "Left Output PGA", NULL, "CLK_SYS" },
888
889 { "Right Output PGA", NULL, "CLK_SYS" },
890
891 { "SPKL", "DAC Switch", "DACL" },
892 { "SPKL", NULL, "CLK_SYS" },
893
894 { "SPKR", "DAC Switch", "DACR" },
895 { "SPKR", NULL, "CLK_SYS" },
896
897 { "Left Headphone Mux", "DAC", "DACL" },
898 { "Right Headphone Mux", "DAC", "DACR" },
899};
900
901static int wm8993_set_bias_level(struct snd_soc_codec *codec,
902 enum snd_soc_bias_level level)
903{
904 struct wm8993_priv *wm8993 = codec->private_data;
905
906 switch (level) {
907 case SND_SOC_BIAS_ON:
908 case SND_SOC_BIAS_PREPARE:
909 /* VMID=2*40k */
910 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
911 WM8993_VMID_SEL_MASK, 0x2);
912 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
913 WM8993_TSHUT_ENA, WM8993_TSHUT_ENA);
914 break;
915
916 case SND_SOC_BIAS_STANDBY:
917 if (codec->bias_level == SND_SOC_BIAS_OFF) {
918 /* Bring up VMID with fast soft start */
919 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
920 WM8993_STARTUP_BIAS_ENA |
921 WM8993_VMID_BUF_ENA |
922 WM8993_VMID_RAMP_MASK |
923 WM8993_BIAS_SRC,
924 WM8993_STARTUP_BIAS_ENA |
925 WM8993_VMID_BUF_ENA |
926 WM8993_VMID_RAMP_MASK |
927 WM8993_BIAS_SRC);
928
929 /* If either line output is single ended we
930 * need the VMID buffer */
931 if (!wm8993->pdata.lineout1_diff ||
932 !wm8993->pdata.lineout2_diff)
933 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
934 WM8993_LINEOUT_VMID_BUF_ENA,
935 WM8993_LINEOUT_VMID_BUF_ENA);
936
937 /* VMID=2*40k */
938 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
939 WM8993_VMID_SEL_MASK |
940 WM8993_BIAS_ENA,
941 WM8993_BIAS_ENA | 0x2);
942 msleep(32);
943
944 /* Switch to normal bias */
945 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
946 WM8993_BIAS_SRC |
947 WM8993_STARTUP_BIAS_ENA, 0);
948 }
949
950 /* VMID=2*240k */
951 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
952 WM8993_VMID_SEL_MASK, 0x4);
953
954 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
955 WM8993_TSHUT_ENA, 0);
956 break;
957
958 case SND_SOC_BIAS_OFF:
959 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
960 WM8993_LINEOUT_VMID_BUF_ENA, 0);
961
962 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
963 WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA,
964 0);
965 break;
966 }
967
968 codec->bias_level = level;
969
970 return 0;
971}
972
973static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai,
974 int clk_id, unsigned int freq, int dir)
975{
976 struct snd_soc_codec *codec = codec_dai->codec;
977 struct wm8993_priv *wm8993 = codec->private_data;
978
979 switch (clk_id) {
980 case WM8993_SYSCLK_MCLK:
981 wm8993->mclk_rate = freq;
982 case WM8993_SYSCLK_FLL:
983 wm8993->sysclk_source = clk_id;
984 break;
985
986 default:
987 return -EINVAL;
988 }
989
990 return 0;
991}
992
993static int wm8993_set_dai_fmt(struct snd_soc_dai *dai,
994 unsigned int fmt)
995{
996 struct snd_soc_codec *codec = dai->codec;
997 struct wm8993_priv *wm8993 = codec->private_data;
998 unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
999 unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1000
1001 aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV |
1002 WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK);
1003 aif4 &= ~WM8993_LRCLK_DIR;
1004
1005 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1006 case SND_SOC_DAIFMT_CBS_CFS:
1007 wm8993->master = 0;
1008 break;
1009 case SND_SOC_DAIFMT_CBS_CFM:
1010 aif4 |= WM8993_LRCLK_DIR;
1011 wm8993->master = 1;
1012 break;
1013 case SND_SOC_DAIFMT_CBM_CFS:
1014 aif1 |= WM8993_BCLK_DIR;
1015 wm8993->master = 1;
1016 break;
1017 case SND_SOC_DAIFMT_CBM_CFM:
1018 aif1 |= WM8993_BCLK_DIR;
1019 aif4 |= WM8993_LRCLK_DIR;
1020 wm8993->master = 1;
1021 break;
1022 default:
1023 return -EINVAL;
1024 }
1025
1026 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1027 case SND_SOC_DAIFMT_DSP_B:
1028 aif1 |= WM8993_AIF_LRCLK_INV;
1029 case SND_SOC_DAIFMT_DSP_A:
1030 aif1 |= 0x18;
1031 break;
1032 case SND_SOC_DAIFMT_I2S:
1033 aif1 |= 0x10;
1034 break;
1035 case SND_SOC_DAIFMT_RIGHT_J:
1036 break;
1037 case SND_SOC_DAIFMT_LEFT_J:
1038 aif1 |= 0x8;
1039 break;
1040 default:
1041 return -EINVAL;
1042 }
1043
1044 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1045 case SND_SOC_DAIFMT_DSP_A:
1046 case SND_SOC_DAIFMT_DSP_B:
1047 /* frame inversion not valid for DSP modes */
1048 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1049 case SND_SOC_DAIFMT_NB_NF:
1050 break;
1051 case SND_SOC_DAIFMT_IB_NF:
1052 aif1 |= WM8993_AIF_BCLK_INV;
1053 break;
1054 default:
1055 return -EINVAL;
1056 }
1057 break;
1058
1059 case SND_SOC_DAIFMT_I2S:
1060 case SND_SOC_DAIFMT_RIGHT_J:
1061 case SND_SOC_DAIFMT_LEFT_J:
1062 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1063 case SND_SOC_DAIFMT_NB_NF:
1064 break;
1065 case SND_SOC_DAIFMT_IB_IF:
1066 aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV;
1067 break;
1068 case SND_SOC_DAIFMT_IB_NF:
1069 aif1 |= WM8993_AIF_BCLK_INV;
1070 break;
1071 case SND_SOC_DAIFMT_NB_IF:
1072 aif1 |= WM8993_AIF_LRCLK_INV;
1073 break;
1074 default:
1075 return -EINVAL;
1076 }
1077 break;
1078 default:
1079 return -EINVAL;
1080 }
1081
1082 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1083 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1084
1085 return 0;
1086}
1087
1088static int wm8993_hw_params(struct snd_pcm_substream *substream,
1089 struct snd_pcm_hw_params *params,
1090 struct snd_soc_dai *dai)
1091{
1092 struct snd_soc_codec *codec = dai->codec;
1093 struct wm8993_priv *wm8993 = codec->private_data;
1094 int ret, i, best, best_val, cur_val;
1095 unsigned int clocking1, clocking3, aif1, aif4;
1096
1097 clocking1 = wm8993_read(codec, WM8993_CLOCKING_1);
1098 clocking1 &= ~WM8993_BCLK_DIV_MASK;
1099
1100 clocking3 = wm8993_read(codec, WM8993_CLOCKING_3);
1101 clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK);
1102
1103 aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
1104 aif1 &= ~WM8993_AIF_WL_MASK;
1105
1106 aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1107 aif4 &= ~WM8993_LRCLK_RATE_MASK;
1108
1109 /* What BCLK do we need? */
1110 wm8993->fs = params_rate(params);
1111 wm8993->bclk = 2 * wm8993->fs;
1112 if (wm8993->tdm_slots) {
1113 dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n",
1114 wm8993->tdm_slots, wm8993->tdm_width);
1115 wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots;
1116 } else {
1117 switch (params_format(params)) {
1118 case SNDRV_PCM_FORMAT_S16_LE:
1119 wm8993->bclk *= 16;
1120 break;
1121 case SNDRV_PCM_FORMAT_S20_3LE:
1122 wm8993->bclk *= 20;
1123 aif1 |= 0x8;
1124 break;
1125 case SNDRV_PCM_FORMAT_S24_LE:
1126 wm8993->bclk *= 24;
1127 aif1 |= 0x10;
1128 break;
1129 case SNDRV_PCM_FORMAT_S32_LE:
1130 wm8993->bclk *= 32;
1131 aif1 |= 0x18;
1132 break;
1133 default:
1134 return -EINVAL;
1135 }
1136 }
1137
1138 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk);
1139
1140 ret = configure_clock(codec);
1141 if (ret != 0)
1142 return ret;
1143
1144 /* Select nearest CLK_SYS_RATE */
1145 best = 0;
1146 best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio)
1147 - wm8993->fs);
1148 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1149 cur_val = abs((wm8993->sysclk_rate /
1150 clk_sys_rates[i].ratio) - wm8993->fs);;
1151 if (cur_val < best_val) {
1152 best = i;
1153 best_val = cur_val;
1154 }
1155 }
1156 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1157 clk_sys_rates[best].ratio);
1158 clocking3 |= (clk_sys_rates[best].clk_sys_rate
1159 << WM8993_CLK_SYS_RATE_SHIFT);
1160
1161 /* SAMPLE_RATE */
1162 best = 0;
1163 best_val = abs(wm8993->fs - sample_rates[0].rate);
1164 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1165 /* Closest match */
1166 cur_val = abs(wm8993->fs - sample_rates[i].rate);
1167 if (cur_val < best_val) {
1168 best = i;
1169 best_val = cur_val;
1170 }
1171 }
1172 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1173 sample_rates[best].rate);
1174 clocking3 |= (sample_rates[best].sample_rate
1175 << WM8993_SAMPLE_RATE_SHIFT);
1176
1177 /* BCLK_DIV */
1178 best = 0;
1179 best_val = INT_MAX;
1180 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1181 cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div)
1182 - wm8993->bclk;
1183 if (cur_val < 0) /* Table is sorted */
1184 break;
1185 if (cur_val < best_val) {
1186 best = i;
1187 best_val = cur_val;
1188 }
1189 }
1190 wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div;
1191 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1192 bclk_divs[best].div, wm8993->bclk);
1193 clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT;
1194
1195 /* LRCLK is a simple fraction of BCLK */
1196 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs);
1197 aif4 |= wm8993->bclk / wm8993->fs;
1198
1199 wm8993_write(codec, WM8993_CLOCKING_1, clocking1);
1200 wm8993_write(codec, WM8993_CLOCKING_3, clocking3);
1201 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1202 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1203
1204 /* ReTune Mobile? */
1205 if (wm8993->pdata.num_retune_configs) {
1206 u16 eq1 = wm8993_read(codec, WM8993_EQ1);
1207 struct wm8993_retune_mobile_setting *s;
1208
1209 best = 0;
1210 best_val = abs(wm8993->pdata.retune_configs[0].rate
1211 - wm8993->fs);
1212 for (i = 0; i < wm8993->pdata.num_retune_configs; i++) {
1213 cur_val = abs(wm8993->pdata.retune_configs[i].rate
1214 - wm8993->fs);
1215 if (cur_val < best_val) {
1216 best_val = cur_val;
1217 best = i;
1218 }
1219 }
1220 s = &wm8993->pdata.retune_configs[best];
1221
1222 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1223 s->name, s->rate);
1224
1225 /* Disable EQ while we reconfigure */
1226 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0);
1227
1228 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1229 wm8993_write(codec, WM8993_EQ1 + i, s->config[i]);
1230
1231 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1);
1232 }
1233
1234 return 0;
1235}
1236
1237static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1238{
1239 struct snd_soc_codec *codec = codec_dai->codec;
1240 unsigned int reg;
1241
1242 reg = wm8993_read(codec, WM8993_DAC_CTRL);
1243
1244 if (mute)
1245 reg |= WM8993_DAC_MUTE;
1246 else
1247 reg &= ~WM8993_DAC_MUTE;
1248
1249 wm8993_write(codec, WM8993_DAC_CTRL, reg);
1250
1251 return 0;
1252}
1253
1254static int wm8993_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1255 unsigned int rx_mask, int slots, int slot_width)
1256{
1257 struct snd_soc_codec *codec = dai->codec;
1258 struct wm8993_priv *wm8993 = codec->private_data;
1259 int aif1 = 0;
1260 int aif2 = 0;
1261
1262 /* Don't need to validate anything if we're turning off TDM */
1263 if (slots == 0) {
1264 wm8993->tdm_slots = 0;
1265 goto out;
1266 }
1267
1268 /* Note that we allow configurations we can't handle ourselves -
1269 * for example, we can generate clocks for slots 2 and up even if
1270 * we can't use those slots ourselves.
1271 */
1272 aif1 |= WM8993_AIFADC_TDM;
1273 aif2 |= WM8993_AIFDAC_TDM;
1274
1275 switch (rx_mask) {
1276 case 3:
1277 break;
1278 case 0xc:
1279 aif1 |= WM8993_AIFADC_TDM_CHAN;
1280 break;
1281 default:
1282 return -EINVAL;
1283 }
1284
1285
1286 switch (tx_mask) {
1287 case 3:
1288 break;
1289 case 0xc:
1290 aif2 |= WM8993_AIFDAC_TDM_CHAN;
1291 break;
1292 default:
1293 return -EINVAL;
1294 }
1295
1296out:
1297 wm8993->tdm_width = slot_width;
1298 wm8993->tdm_slots = slots / 2;
1299
1300 snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_1,
1301 WM8993_AIFADC_TDM | WM8993_AIFADC_TDM_CHAN, aif1);
1302 snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_2,
1303 WM8993_AIFDAC_TDM | WM8993_AIFDAC_TDM_CHAN, aif2);
1304
1305 return 0;
1306}
1307
1308static struct snd_soc_dai_ops wm8993_ops = {
1309 .set_sysclk = wm8993_set_sysclk,
1310 .set_fmt = wm8993_set_dai_fmt,
1311 .hw_params = wm8993_hw_params,
1312 .digital_mute = wm8993_digital_mute,
1313 .set_pll = wm8993_set_fll,
1314 .set_tdm_slot = wm8993_set_tdm_slot,
1315};
1316
1317#define WM8993_RATES SNDRV_PCM_RATE_8000_48000
1318
1319#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1320 SNDRV_PCM_FMTBIT_S20_3LE |\
1321 SNDRV_PCM_FMTBIT_S24_LE |\
1322 SNDRV_PCM_FMTBIT_S32_LE)
1323
1324struct snd_soc_dai wm8993_dai = {
1325 .name = "WM8993",
1326 .playback = {
1327 .stream_name = "Playback",
1328 .channels_min = 1,
1329 .channels_max = 2,
1330 .rates = WM8993_RATES,
1331 .formats = WM8993_FORMATS,
1332 },
1333 .capture = {
1334 .stream_name = "Capture",
1335 .channels_min = 1,
1336 .channels_max = 2,
1337 .rates = WM8993_RATES,
1338 .formats = WM8993_FORMATS,
1339 },
1340 .ops = &wm8993_ops,
1341 .symmetric_rates = 1,
1342};
1343EXPORT_SYMBOL_GPL(wm8993_dai);
1344
1345static struct snd_soc_codec *wm8993_codec;
1346
1347static int wm8993_probe(struct platform_device *pdev)
1348{
1349 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1350 struct snd_soc_codec *codec;
1351 struct wm8993_priv *wm8993;
1352 int ret = 0;
1353
1354 if (!wm8993_codec) {
1355 dev_err(&pdev->dev, "I2C device not yet probed\n");
1356 goto err;
1357 }
1358
1359 socdev->card->codec = wm8993_codec;
1360 codec = wm8993_codec;
1361 wm8993 = codec->private_data;
1362
1363 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1364 if (ret < 0) {
1365 dev_err(codec->dev, "failed to create pcms\n");
1366 goto err;
1367 }
1368
1369 snd_soc_add_controls(codec, wm8993_snd_controls,
1370 ARRAY_SIZE(wm8993_snd_controls));
1371 if (wm8993->pdata.num_retune_configs != 0) {
1372 dev_dbg(codec->dev, "Using ReTune Mobile\n");
1373 } else {
1374 dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
1375 snd_soc_add_controls(codec, wm8993_eq_controls,
1376 ARRAY_SIZE(wm8993_eq_controls));
1377 }
1378
1379 snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets,
1380 ARRAY_SIZE(wm8993_dapm_widgets));
1381 wm_hubs_add_analogue_controls(codec);
1382
1383 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
1384 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
1385 wm8993->pdata.lineout2_diff);
1386
1387 snd_soc_dapm_new_widgets(codec);
1388
1389 ret = snd_soc_init_card(socdev);
1390 if (ret < 0) {
1391 dev_err(codec->dev, "failed to register card\n");
1392 goto card_err;
1393 }
1394
1395 return ret;
1396
1397card_err:
1398 snd_soc_free_pcms(socdev);
1399 snd_soc_dapm_free(socdev);
1400err:
1401 return ret;
1402}
1403
1404static int wm8993_remove(struct platform_device *pdev)
1405{
1406 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1407
1408 snd_soc_free_pcms(socdev);
1409 snd_soc_dapm_free(socdev);
1410
1411 return 0;
1412}
1413
1414struct snd_soc_codec_device soc_codec_dev_wm8993 = {
1415 .probe = wm8993_probe,
1416 .remove = wm8993_remove,
1417};
1418EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
1419
1420static int wm8993_i2c_probe(struct i2c_client *i2c,
1421 const struct i2c_device_id *id)
1422{
1423 struct wm8993_priv *wm8993;
1424 struct snd_soc_codec *codec;
1425 unsigned int val;
1426 int ret;
1427
1428 if (wm8993_codec) {
1429 dev_err(&i2c->dev, "A WM8993 is already registered\n");
1430 return -EINVAL;
1431 }
1432
1433 wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
1434 if (wm8993 == NULL)
1435 return -ENOMEM;
1436
1437 codec = &wm8993->codec;
1438 if (i2c->dev.platform_data)
1439 memcpy(&wm8993->pdata, i2c->dev.platform_data,
1440 sizeof(wm8993->pdata));
1441
1442 mutex_init(&codec->mutex);
1443 INIT_LIST_HEAD(&codec->dapm_widgets);
1444 INIT_LIST_HEAD(&codec->dapm_paths);
1445
1446 codec->name = "WM8993";
1447 codec->read = wm8993_read;
1448 codec->write = wm8993_write;
1449 codec->hw_write = (hw_write_t)i2c_master_send;
1450 codec->reg_cache = wm8993->reg_cache;
1451 codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
1452 codec->bias_level = SND_SOC_BIAS_OFF;
1453 codec->set_bias_level = wm8993_set_bias_level;
1454 codec->dai = &wm8993_dai;
1455 codec->num_dai = 1;
1456 codec->private_data = wm8993;
1457
1458 memcpy(wm8993->reg_cache, wm8993_reg_defaults,
1459 sizeof(wm8993->reg_cache));
1460
1461 i2c_set_clientdata(i2c, wm8993);
1462 codec->control_data = i2c;
1463 wm8993_codec = codec;
1464
1465 codec->dev = &i2c->dev;
1466
1467 val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET);
1468 if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
1469 dev_err(codec->dev, "Invalid ID register value %x\n", val);
1470 ret = -EINVAL;
1471 goto err;
1472 }
1473
1474 ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
1475 if (ret != 0)
1476 goto err;
1477
1478 /* By default we're using the output mixers */
1479 wm8993->class_w_users = 2;
1480
1481 /* Latch volume update bits and default ZC on */
1482 snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
1483 WM8993_DAC_VU, WM8993_DAC_VU);
1484 snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
1485 WM8993_ADC_VU, WM8993_ADC_VU);
1486
1487 /* Manualy manage the HPOUT sequencing for independent stereo
1488 * control. */
1489 snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
1490 WM8993_HPOUT1_AUTO_PU, 0);
1491
1492 /* Use automatic clock configuration */
1493 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1494
1495 if (!wm8993->pdata.lineout1_diff)
1496 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
1497 WM8993_LINEOUT1_MODE,
1498 WM8993_LINEOUT1_MODE);
1499 if (!wm8993->pdata.lineout2_diff)
1500 snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
1501 WM8993_LINEOUT2_MODE,
1502 WM8993_LINEOUT2_MODE);
1503
1504 if (wm8993->pdata.lineout1fb)
1505 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1506 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1507
1508 if (wm8993->pdata.lineout2fb)
1509 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1510 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1511
1512 /* Apply the microphone bias/detection configuration - the
1513 * platform data is directly applicable to the register. */
1514 snd_soc_update_bits(codec, WM8993_MICBIAS,
1515 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1516 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1517 wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
1518 wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
1519 wm8993->pdata.micbias1_lvl |
1520 wm8993->pdata.micbias1_lvl << 1);
1521
1522 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1523 if (ret != 0)
1524 goto err;
1525
1526 wm8993_dai.dev = codec->dev;
1527
1528 ret = snd_soc_register_dai(&wm8993_dai);
1529 if (ret != 0)
1530 goto err_bias;
1531
1532 ret = snd_soc_register_codec(codec);
1533
1534 return 0;
1535
1536err_bias:
1537 wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
1538err:
1539 wm8993_codec = NULL;
1540 kfree(wm8993);
1541 return ret;
1542}
1543
1544static int wm8993_i2c_remove(struct i2c_client *client)
1545{
1546 struct wm8993_priv *wm8993 = i2c_get_clientdata(client);
1547
1548 snd_soc_unregister_codec(&wm8993->codec);
1549 snd_soc_unregister_dai(&wm8993_dai);
1550
1551 wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
1552 kfree(wm8993);
1553
1554 return 0;
1555}
1556
1557static const struct i2c_device_id wm8993_i2c_id[] = {
1558 { "wm8993", 0 },
1559 { }
1560};
1561MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
1562
1563static struct i2c_driver wm8993_i2c_driver = {
1564 .driver = {
1565 .name = "WM8993",
1566 .owner = THIS_MODULE,
1567 },
1568 .probe = wm8993_i2c_probe,
1569 .remove = wm8993_i2c_remove,
1570 .id_table = wm8993_i2c_id,
1571};
1572
1573
1574static int __init wm8993_modinit(void)
1575{
1576 int ret;
1577
1578 ret = i2c_add_driver(&wm8993_i2c_driver);
1579 if (ret != 0)
1580 pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
1581
1582 return ret;
1583}
1584module_init(wm8993_modinit);
1585
1586static void __exit wm8993_exit(void)
1587{
1588 i2c_del_driver(&wm8993_i2c_driver);
1589}
1590module_exit(wm8993_exit);
1591
1592
1593MODULE_DESCRIPTION("ASoC WM8993 driver");
1594MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1595MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
new file mode 100644
index 000000000000..30e71ca88dad
--- /dev/null
+++ b/sound/soc/codecs/wm8993.h
@@ -0,0 +1,2132 @@
1#ifndef WM8993_H
2#define WM8993_H
3
4extern struct snd_soc_dai wm8993_dai;
5extern struct snd_soc_codec_device soc_codec_dev_wm8993;
6
7#define WM8993_SYSCLK_MCLK 1
8#define WM8993_SYSCLK_FLL 2
9
10#define WM8993_FLL_MCLK 1
11#define WM8993_FLL_BCLK 2
12#define WM8993_FLL_LRCLK 3
13
14/*
15 * Register values.
16 */
17#define WM8993_SOFTWARE_RESET 0x00
18#define WM8993_POWER_MANAGEMENT_1 0x01
19#define WM8993_POWER_MANAGEMENT_2 0x02
20#define WM8993_POWER_MANAGEMENT_3 0x03
21#define WM8993_AUDIO_INTERFACE_1 0x04
22#define WM8993_AUDIO_INTERFACE_2 0x05
23#define WM8993_CLOCKING_1 0x06
24#define WM8993_CLOCKING_2 0x07
25#define WM8993_AUDIO_INTERFACE_3 0x08
26#define WM8993_AUDIO_INTERFACE_4 0x09
27#define WM8993_DAC_CTRL 0x0A
28#define WM8993_LEFT_DAC_DIGITAL_VOLUME 0x0B
29#define WM8993_RIGHT_DAC_DIGITAL_VOLUME 0x0C
30#define WM8993_DIGITAL_SIDE_TONE 0x0D
31#define WM8993_ADC_CTRL 0x0E
32#define WM8993_LEFT_ADC_DIGITAL_VOLUME 0x0F
33#define WM8993_RIGHT_ADC_DIGITAL_VOLUME 0x10
34#define WM8993_GPIO_CTRL_1 0x12
35#define WM8993_GPIO1 0x13
36#define WM8993_IRQ_DEBOUNCE 0x14
37#define WM8993_GPIOCTRL_2 0x16
38#define WM8993_GPIO_POL 0x17
39#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18
40#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME 0x19
41#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
42#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
43#define WM8993_LEFT_OUTPUT_VOLUME 0x1C
44#define WM8993_RIGHT_OUTPUT_VOLUME 0x1D
45#define WM8993_LINE_OUTPUTS_VOLUME 0x1E
46#define WM8993_HPOUT2_VOLUME 0x1F
47#define WM8993_LEFT_OPGA_VOLUME 0x20
48#define WM8993_RIGHT_OPGA_VOLUME 0x21
49#define WM8993_SPKMIXL_ATTENUATION 0x22
50#define WM8993_SPKMIXR_ATTENUATION 0x23
51#define WM8993_SPKOUT_MIXERS 0x24
52#define WM8993_SPKOUT_BOOST 0x25
53#define WM8993_SPEAKER_VOLUME_LEFT 0x26
54#define WM8993_SPEAKER_VOLUME_RIGHT 0x27
55#define WM8993_INPUT_MIXER2 0x28
56#define WM8993_INPUT_MIXER3 0x29
57#define WM8993_INPUT_MIXER4 0x2A
58#define WM8993_INPUT_MIXER5 0x2B
59#define WM8993_INPUT_MIXER6 0x2C
60#define WM8993_OUTPUT_MIXER1 0x2D
61#define WM8993_OUTPUT_MIXER2 0x2E
62#define WM8993_OUTPUT_MIXER3 0x2F
63#define WM8993_OUTPUT_MIXER4 0x30
64#define WM8993_OUTPUT_MIXER5 0x31
65#define WM8993_OUTPUT_MIXER6 0x32
66#define WM8993_HPOUT2_MIXER 0x33
67#define WM8993_LINE_MIXER1 0x34
68#define WM8993_LINE_MIXER2 0x35
69#define WM8993_SPEAKER_MIXER 0x36
70#define WM8993_ADDITIONAL_CONTROL 0x37
71#define WM8993_ANTIPOP1 0x38
72#define WM8993_ANTIPOP2 0x39
73#define WM8993_MICBIAS 0x3A
74#define WM8993_FLL_CONTROL_1 0x3C
75#define WM8993_FLL_CONTROL_2 0x3D
76#define WM8993_FLL_CONTROL_3 0x3E
77#define WM8993_FLL_CONTROL_4 0x3F
78#define WM8993_FLL_CONTROL_5 0x40
79#define WM8993_CLOCKING_3 0x41
80#define WM8993_CLOCKING_4 0x42
81#define WM8993_MW_SLAVE_CONTROL 0x43
82#define WM8993_BUS_CONTROL_1 0x45
83#define WM8993_WRITE_SEQUENCER_0 0x46
84#define WM8993_WRITE_SEQUENCER_1 0x47
85#define WM8993_WRITE_SEQUENCER_2 0x48
86#define WM8993_WRITE_SEQUENCER_3 0x49
87#define WM8993_WRITE_SEQUENCER_4 0x4A
88#define WM8993_WRITE_SEQUENCER_5 0x4B
89#define WM8993_CHARGE_PUMP_1 0x4C
90#define WM8993_CLASS_W_0 0x51
91#define WM8993_DC_SERVO_0 0x54
92#define WM8993_DC_SERVO_1 0x55
93#define WM8993_DC_SERVO_3 0x57
94#define WM8993_DC_SERVO_READBACK_0 0x58
95#define WM8993_DC_SERVO_READBACK_1 0x59
96#define WM8993_DC_SERVO_READBACK_2 0x5A
97#define WM8993_ANALOGUE_HP_0 0x60
98#define WM8993_EQ1 0x62
99#define WM8993_EQ2 0x63
100#define WM8993_EQ3 0x64
101#define WM8993_EQ4 0x65
102#define WM8993_EQ5 0x66
103#define WM8993_EQ6 0x67
104#define WM8993_EQ7 0x68
105#define WM8993_EQ8 0x69
106#define WM8993_EQ9 0x6A
107#define WM8993_EQ10 0x6B
108#define WM8993_EQ11 0x6C
109#define WM8993_EQ12 0x6D
110#define WM8993_EQ13 0x6E
111#define WM8993_EQ14 0x6F
112#define WM8993_EQ15 0x70
113#define WM8993_EQ16 0x71
114#define WM8993_EQ17 0x72
115#define WM8993_EQ18 0x73
116#define WM8993_EQ19 0x74
117#define WM8993_EQ20 0x75
118#define WM8993_EQ21 0x76
119#define WM8993_EQ22 0x77
120#define WM8993_EQ23 0x78
121#define WM8993_EQ24 0x79
122#define WM8993_DIGITAL_PULLS 0x7A
123#define WM8993_DRC_CONTROL_1 0x7B
124#define WM8993_DRC_CONTROL_2 0x7C
125#define WM8993_DRC_CONTROL_3 0x7D
126#define WM8993_DRC_CONTROL_4 0x7E
127
128#define WM8993_REGISTER_COUNT 0x7F
129#define WM8993_MAX_REGISTER 0x7E
130
131/*
132 * Field Definitions.
133 */
134
135/*
136 * R0 (0x00) - Software Reset
137 */
138#define WM8993_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
139#define WM8993_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
140#define WM8993_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
141
142/*
143 * R1 (0x01) - Power Management (1)
144 */
145#define WM8993_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */
146#define WM8993_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */
147#define WM8993_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */
148#define WM8993_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
149#define WM8993_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */
150#define WM8993_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */
151#define WM8993_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */
152#define WM8993_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
153#define WM8993_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */
154#define WM8993_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */
155#define WM8993_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */
156#define WM8993_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */
157#define WM8993_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */
158#define WM8993_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */
159#define WM8993_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */
160#define WM8993_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */
161#define WM8993_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */
162#define WM8993_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */
163#define WM8993_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */
164#define WM8993_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */
165#define WM8993_MICB2_ENA 0x0020 /* MICB2_ENA */
166#define WM8993_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */
167#define WM8993_MICB2_ENA_SHIFT 5 /* MICB2_ENA */
168#define WM8993_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
169#define WM8993_MICB1_ENA 0x0010 /* MICB1_ENA */
170#define WM8993_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */
171#define WM8993_MICB1_ENA_SHIFT 4 /* MICB1_ENA */
172#define WM8993_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
173#define WM8993_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
174#define WM8993_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
175#define WM8993_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
176#define WM8993_BIAS_ENA 0x0001 /* BIAS_ENA */
177#define WM8993_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */
178#define WM8993_BIAS_ENA_SHIFT 0 /* BIAS_ENA */
179#define WM8993_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
180
181/*
182 * R2 (0x02) - Power Management (2)
183 */
184#define WM8993_TSHUT_ENA 0x4000 /* TSHUT_ENA */
185#define WM8993_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */
186#define WM8993_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */
187#define WM8993_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
188#define WM8993_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
189#define WM8993_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */
190#define WM8993_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */
191#define WM8993_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */
192#define WM8993_OPCLK_ENA 0x0800 /* OPCLK_ENA */
193#define WM8993_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */
194#define WM8993_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */
195#define WM8993_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
196#define WM8993_MIXINL_ENA 0x0200 /* MIXINL_ENA */
197#define WM8993_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */
198#define WM8993_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */
199#define WM8993_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
200#define WM8993_MIXINR_ENA 0x0100 /* MIXINR_ENA */
201#define WM8993_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */
202#define WM8993_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */
203#define WM8993_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
204#define WM8993_IN2L_ENA 0x0080 /* IN2L_ENA */
205#define WM8993_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */
206#define WM8993_IN2L_ENA_SHIFT 7 /* IN2L_ENA */
207#define WM8993_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
208#define WM8993_IN1L_ENA 0x0040 /* IN1L_ENA */
209#define WM8993_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */
210#define WM8993_IN1L_ENA_SHIFT 6 /* IN1L_ENA */
211#define WM8993_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
212#define WM8993_IN2R_ENA 0x0020 /* IN2R_ENA */
213#define WM8993_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */
214#define WM8993_IN2R_ENA_SHIFT 5 /* IN2R_ENA */
215#define WM8993_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
216#define WM8993_IN1R_ENA 0x0010 /* IN1R_ENA */
217#define WM8993_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */
218#define WM8993_IN1R_ENA_SHIFT 4 /* IN1R_ENA */
219#define WM8993_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
220#define WM8993_ADCL_ENA 0x0002 /* ADCL_ENA */
221#define WM8993_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */
222#define WM8993_ADCL_ENA_SHIFT 1 /* ADCL_ENA */
223#define WM8993_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
224#define WM8993_ADCR_ENA 0x0001 /* ADCR_ENA */
225#define WM8993_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */
226#define WM8993_ADCR_ENA_SHIFT 0 /* ADCR_ENA */
227#define WM8993_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
228
229/*
230 * R3 (0x03) - Power Management (3)
231 */
232#define WM8993_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */
233#define WM8993_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */
234#define WM8993_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */
235#define WM8993_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */
236#define WM8993_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */
237#define WM8993_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */
238#define WM8993_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */
239#define WM8993_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */
240#define WM8993_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */
241#define WM8993_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */
242#define WM8993_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */
243#define WM8993_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */
244#define WM8993_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */
245#define WM8993_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */
246#define WM8993_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */
247#define WM8993_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */
248#define WM8993_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */
249#define WM8993_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */
250#define WM8993_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */
251#define WM8993_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */
252#define WM8993_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */
253#define WM8993_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */
254#define WM8993_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */
255#define WM8993_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */
256#define WM8993_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */
257#define WM8993_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */
258#define WM8993_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */
259#define WM8993_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */
260#define WM8993_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */
261#define WM8993_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */
262#define WM8993_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */
263#define WM8993_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */
264#define WM8993_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */
265#define WM8993_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */
266#define WM8993_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */
267#define WM8993_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */
268#define WM8993_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */
269#define WM8993_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */
270#define WM8993_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */
271#define WM8993_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */
272#define WM8993_DACL_ENA 0x0002 /* DACL_ENA */
273#define WM8993_DACL_ENA_MASK 0x0002 /* DACL_ENA */
274#define WM8993_DACL_ENA_SHIFT 1 /* DACL_ENA */
275#define WM8993_DACL_ENA_WIDTH 1 /* DACL_ENA */
276#define WM8993_DACR_ENA 0x0001 /* DACR_ENA */
277#define WM8993_DACR_ENA_MASK 0x0001 /* DACR_ENA */
278#define WM8993_DACR_ENA_SHIFT 0 /* DACR_ENA */
279#define WM8993_DACR_ENA_WIDTH 1 /* DACR_ENA */
280
281/*
282 * R4 (0x04) - Audio Interface (1)
283 */
284#define WM8993_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */
285#define WM8993_AIFADCL_SRC_MASK 0x8000 /* AIFADCL_SRC */
286#define WM8993_AIFADCL_SRC_SHIFT 15 /* AIFADCL_SRC */
287#define WM8993_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */
288#define WM8993_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */
289#define WM8993_AIFADCR_SRC_MASK 0x4000 /* AIFADCR_SRC */
290#define WM8993_AIFADCR_SRC_SHIFT 14 /* AIFADCR_SRC */
291#define WM8993_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */
292#define WM8993_AIFADC_TDM 0x2000 /* AIFADC_TDM */
293#define WM8993_AIFADC_TDM_MASK 0x2000 /* AIFADC_TDM */
294#define WM8993_AIFADC_TDM_SHIFT 13 /* AIFADC_TDM */
295#define WM8993_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */
296#define WM8993_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */
297#define WM8993_AIFADC_TDM_CHAN_MASK 0x1000 /* AIFADC_TDM_CHAN */
298#define WM8993_AIFADC_TDM_CHAN_SHIFT 12 /* AIFADC_TDM_CHAN */
299#define WM8993_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */
300#define WM8993_BCLK_DIR 0x0200 /* BCLK_DIR */
301#define WM8993_BCLK_DIR_MASK 0x0200 /* BCLK_DIR */
302#define WM8993_BCLK_DIR_SHIFT 9 /* BCLK_DIR */
303#define WM8993_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
304#define WM8993_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */
305#define WM8993_AIF_BCLK_INV_MASK 0x0100 /* AIF_BCLK_INV */
306#define WM8993_AIF_BCLK_INV_SHIFT 8 /* AIF_BCLK_INV */
307#define WM8993_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
308#define WM8993_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */
309#define WM8993_AIF_LRCLK_INV_MASK 0x0080 /* AIF_LRCLK_INV */
310#define WM8993_AIF_LRCLK_INV_SHIFT 7 /* AIF_LRCLK_INV */
311#define WM8993_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
312#define WM8993_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */
313#define WM8993_AIF_WL_SHIFT 5 /* AIF_WL - [6:5] */
314#define WM8993_AIF_WL_WIDTH 2 /* AIF_WL - [6:5] */
315#define WM8993_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */
316#define WM8993_AIF_FMT_SHIFT 3 /* AIF_FMT - [4:3] */
317#define WM8993_AIF_FMT_WIDTH 2 /* AIF_FMT - [4:3] */
318
319/*
320 * R5 (0x05) - Audio Interface (2)
321 */
322#define WM8993_AIFDACL_SRC 0x8000 /* AIFDACL_SRC */
323#define WM8993_AIFDACL_SRC_MASK 0x8000 /* AIFDACL_SRC */
324#define WM8993_AIFDACL_SRC_SHIFT 15 /* AIFDACL_SRC */
325#define WM8993_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */
326#define WM8993_AIFDACR_SRC 0x4000 /* AIFDACR_SRC */
327#define WM8993_AIFDACR_SRC_MASK 0x4000 /* AIFDACR_SRC */
328#define WM8993_AIFDACR_SRC_SHIFT 14 /* AIFDACR_SRC */
329#define WM8993_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */
330#define WM8993_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */
331#define WM8993_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */
332#define WM8993_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */
333#define WM8993_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */
334#define WM8993_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */
335#define WM8993_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */
336#define WM8993_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */
337#define WM8993_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */
338#define WM8993_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */
339#define WM8993_DAC_BOOST_SHIFT 10 /* DAC_BOOST - [11:10] */
340#define WM8993_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [11:10] */
341#define WM8993_DAC_COMP 0x0010 /* DAC_COMP */
342#define WM8993_DAC_COMP_MASK 0x0010 /* DAC_COMP */
343#define WM8993_DAC_COMP_SHIFT 4 /* DAC_COMP */
344#define WM8993_DAC_COMP_WIDTH 1 /* DAC_COMP */
345#define WM8993_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
346#define WM8993_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */
347#define WM8993_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */
348#define WM8993_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
349#define WM8993_ADC_COMP 0x0004 /* ADC_COMP */
350#define WM8993_ADC_COMP_MASK 0x0004 /* ADC_COMP */
351#define WM8993_ADC_COMP_SHIFT 2 /* ADC_COMP */
352#define WM8993_ADC_COMP_WIDTH 1 /* ADC_COMP */
353#define WM8993_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
354#define WM8993_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */
355#define WM8993_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */
356#define WM8993_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */
357#define WM8993_LOOPBACK 0x0001 /* LOOPBACK */
358#define WM8993_LOOPBACK_MASK 0x0001 /* LOOPBACK */
359#define WM8993_LOOPBACK_SHIFT 0 /* LOOPBACK */
360#define WM8993_LOOPBACK_WIDTH 1 /* LOOPBACK */
361
362/*
363 * R6 (0x06) - Clocking 1
364 */
365#define WM8993_TOCLK_RATE 0x8000 /* TOCLK_RATE */
366#define WM8993_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */
367#define WM8993_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */
368#define WM8993_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */
369#define WM8993_TOCLK_ENA 0x4000 /* TOCLK_ENA */
370#define WM8993_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */
371#define WM8993_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */
372#define WM8993_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
373#define WM8993_OPCLK_DIV_MASK 0x1E00 /* OPCLK_DIV - [12:9] */
374#define WM8993_OPCLK_DIV_SHIFT 9 /* OPCLK_DIV - [12:9] */
375#define WM8993_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [12:9] */
376#define WM8993_DCLK_DIV_MASK 0x01C0 /* DCLK_DIV - [8:6] */
377#define WM8993_DCLK_DIV_SHIFT 6 /* DCLK_DIV - [8:6] */
378#define WM8993_DCLK_DIV_WIDTH 3 /* DCLK_DIV - [8:6] */
379#define WM8993_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */
380#define WM8993_BCLK_DIV_SHIFT 1 /* BCLK_DIV - [4:1] */
381#define WM8993_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [4:1] */
382
383/*
384 * R7 (0x07) - Clocking 2
385 */
386#define WM8993_MCLK_SRC 0x8000 /* MCLK_SRC */
387#define WM8993_MCLK_SRC_MASK 0x8000 /* MCLK_SRC */
388#define WM8993_MCLK_SRC_SHIFT 15 /* MCLK_SRC */
389#define WM8993_MCLK_SRC_WIDTH 1 /* MCLK_SRC */
390#define WM8993_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */
391#define WM8993_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */
392#define WM8993_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */
393#define WM8993_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */
394#define WM8993_MCLK_DIV 0x1000 /* MCLK_DIV */
395#define WM8993_MCLK_DIV_MASK 0x1000 /* MCLK_DIV */
396#define WM8993_MCLK_DIV_SHIFT 12 /* MCLK_DIV */
397#define WM8993_MCLK_DIV_WIDTH 1 /* MCLK_DIV */
398#define WM8993_MCLK_INV 0x0400 /* MCLK_INV */
399#define WM8993_MCLK_INV_MASK 0x0400 /* MCLK_INV */
400#define WM8993_MCLK_INV_SHIFT 10 /* MCLK_INV */
401#define WM8993_MCLK_INV_WIDTH 1 /* MCLK_INV */
402#define WM8993_ADC_DIV_MASK 0x00E0 /* ADC_DIV - [7:5] */
403#define WM8993_ADC_DIV_SHIFT 5 /* ADC_DIV - [7:5] */
404#define WM8993_ADC_DIV_WIDTH 3 /* ADC_DIV - [7:5] */
405#define WM8993_DAC_DIV_MASK 0x001C /* DAC_DIV - [4:2] */
406#define WM8993_DAC_DIV_SHIFT 2 /* DAC_DIV - [4:2] */
407#define WM8993_DAC_DIV_WIDTH 3 /* DAC_DIV - [4:2] */
408
409/*
410 * R8 (0x08) - Audio Interface (3)
411 */
412#define WM8993_AIF_MSTR1 0x8000 /* AIF_MSTR1 */
413#define WM8993_AIF_MSTR1_MASK 0x8000 /* AIF_MSTR1 */
414#define WM8993_AIF_MSTR1_SHIFT 15 /* AIF_MSTR1 */
415#define WM8993_AIF_MSTR1_WIDTH 1 /* AIF_MSTR1 */
416
417/*
418 * R9 (0x09) - Audio Interface (4)
419 */
420#define WM8993_AIF_TRIS 0x2000 /* AIF_TRIS */
421#define WM8993_AIF_TRIS_MASK 0x2000 /* AIF_TRIS */
422#define WM8993_AIF_TRIS_SHIFT 13 /* AIF_TRIS */
423#define WM8993_AIF_TRIS_WIDTH 1 /* AIF_TRIS */
424#define WM8993_LRCLK_DIR 0x0800 /* LRCLK_DIR */
425#define WM8993_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */
426#define WM8993_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */
427#define WM8993_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
428#define WM8993_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
429#define WM8993_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
430#define WM8993_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
431
432/*
433 * R10 (0x0A) - DAC CTRL
434 */
435#define WM8993_DAC_OSR128 0x2000 /* DAC_OSR128 */
436#define WM8993_DAC_OSR128_MASK 0x2000 /* DAC_OSR128 */
437#define WM8993_DAC_OSR128_SHIFT 13 /* DAC_OSR128 */
438#define WM8993_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
439#define WM8993_DAC_MONO 0x0200 /* DAC_MONO */
440#define WM8993_DAC_MONO_MASK 0x0200 /* DAC_MONO */
441#define WM8993_DAC_MONO_SHIFT 9 /* DAC_MONO */
442#define WM8993_DAC_MONO_WIDTH 1 /* DAC_MONO */
443#define WM8993_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */
444#define WM8993_DAC_SB_FILT_MASK 0x0100 /* DAC_SB_FILT */
445#define WM8993_DAC_SB_FILT_SHIFT 8 /* DAC_SB_FILT */
446#define WM8993_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */
447#define WM8993_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */
448#define WM8993_DAC_MUTERATE_MASK 0x0080 /* DAC_MUTERATE */
449#define WM8993_DAC_MUTERATE_SHIFT 7 /* DAC_MUTERATE */
450#define WM8993_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
451#define WM8993_DAC_UNMUTE_RAMP 0x0040 /* DAC_UNMUTE_RAMP */
452#define WM8993_DAC_UNMUTE_RAMP_MASK 0x0040 /* DAC_UNMUTE_RAMP */
453#define WM8993_DAC_UNMUTE_RAMP_SHIFT 6 /* DAC_UNMUTE_RAMP */
454#define WM8993_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */
455#define WM8993_DEEMPH_MASK 0x0030 /* DEEMPH - [5:4] */
456#define WM8993_DEEMPH_SHIFT 4 /* DEEMPH - [5:4] */
457#define WM8993_DEEMPH_WIDTH 2 /* DEEMPH - [5:4] */
458#define WM8993_DAC_MUTE 0x0004 /* DAC_MUTE */
459#define WM8993_DAC_MUTE_MASK 0x0004 /* DAC_MUTE */
460#define WM8993_DAC_MUTE_SHIFT 2 /* DAC_MUTE */
461#define WM8993_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
462#define WM8993_DACL_DATINV 0x0002 /* DACL_DATINV */
463#define WM8993_DACL_DATINV_MASK 0x0002 /* DACL_DATINV */
464#define WM8993_DACL_DATINV_SHIFT 1 /* DACL_DATINV */
465#define WM8993_DACL_DATINV_WIDTH 1 /* DACL_DATINV */
466#define WM8993_DACR_DATINV 0x0001 /* DACR_DATINV */
467#define WM8993_DACR_DATINV_MASK 0x0001 /* DACR_DATINV */
468#define WM8993_DACR_DATINV_SHIFT 0 /* DACR_DATINV */
469#define WM8993_DACR_DATINV_WIDTH 1 /* DACR_DATINV */
470
471/*
472 * R11 (0x0B) - Left DAC Digital Volume
473 */
474#define WM8993_DAC_VU 0x0100 /* DAC_VU */
475#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */
476#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */
477#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */
478#define WM8993_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
479#define WM8993_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */
480#define WM8993_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */
481
482/*
483 * R12 (0x0C) - Right DAC Digital Volume
484 */
485#define WM8993_DAC_VU 0x0100 /* DAC_VU */
486#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */
487#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */
488#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */
489#define WM8993_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
490#define WM8993_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */
491#define WM8993_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */
492
493/*
494 * R13 (0x0D) - Digital Side Tone
495 */
496#define WM8993_ADCL_DAC_SVOL_MASK 0x1E00 /* ADCL_DAC_SVOL - [12:9] */
497#define WM8993_ADCL_DAC_SVOL_SHIFT 9 /* ADCL_DAC_SVOL - [12:9] */
498#define WM8993_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [12:9] */
499#define WM8993_ADCR_DAC_SVOL_MASK 0x01E0 /* ADCR_DAC_SVOL - [8:5] */
500#define WM8993_ADCR_DAC_SVOL_SHIFT 5 /* ADCR_DAC_SVOL - [8:5] */
501#define WM8993_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [8:5] */
502#define WM8993_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
503#define WM8993_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
504#define WM8993_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
505#define WM8993_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */
506#define WM8993_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */
507#define WM8993_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */
508
509/*
510 * R14 (0x0E) - ADC CTRL
511 */
512#define WM8993_ADC_OSR128 0x0200 /* ADC_OSR128 */
513#define WM8993_ADC_OSR128_MASK 0x0200 /* ADC_OSR128 */
514#define WM8993_ADC_OSR128_SHIFT 9 /* ADC_OSR128 */
515#define WM8993_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */
516#define WM8993_ADC_HPF 0x0100 /* ADC_HPF */
517#define WM8993_ADC_HPF_MASK 0x0100 /* ADC_HPF */
518#define WM8993_ADC_HPF_SHIFT 8 /* ADC_HPF */
519#define WM8993_ADC_HPF_WIDTH 1 /* ADC_HPF */
520#define WM8993_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */
521#define WM8993_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */
522#define WM8993_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */
523#define WM8993_ADCL_DATINV 0x0002 /* ADCL_DATINV */
524#define WM8993_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */
525#define WM8993_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */
526#define WM8993_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */
527#define WM8993_ADCR_DATINV 0x0001 /* ADCR_DATINV */
528#define WM8993_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */
529#define WM8993_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */
530#define WM8993_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */
531
532/*
533 * R15 (0x0F) - Left ADC Digital Volume
534 */
535#define WM8993_ADC_VU 0x0100 /* ADC_VU */
536#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */
537#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */
538#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */
539#define WM8993_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
540#define WM8993_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */
541#define WM8993_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */
542
543/*
544 * R16 (0x10) - Right ADC Digital Volume
545 */
546#define WM8993_ADC_VU 0x0100 /* ADC_VU */
547#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */
548#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */
549#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */
550#define WM8993_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
551#define WM8993_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */
552#define WM8993_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */
553
554/*
555 * R18 (0x12) - GPIO CTRL 1
556 */
557#define WM8993_JD2_SC_EINT 0x8000 /* JD2_SC_EINT */
558#define WM8993_JD2_SC_EINT_MASK 0x8000 /* JD2_SC_EINT */
559#define WM8993_JD2_SC_EINT_SHIFT 15 /* JD2_SC_EINT */
560#define WM8993_JD2_SC_EINT_WIDTH 1 /* JD2_SC_EINT */
561#define WM8993_JD2_EINT 0x4000 /* JD2_EINT */
562#define WM8993_JD2_EINT_MASK 0x4000 /* JD2_EINT */
563#define WM8993_JD2_EINT_SHIFT 14 /* JD2_EINT */
564#define WM8993_JD2_EINT_WIDTH 1 /* JD2_EINT */
565#define WM8993_WSEQ_EINT 0x2000 /* WSEQ_EINT */
566#define WM8993_WSEQ_EINT_MASK 0x2000 /* WSEQ_EINT */
567#define WM8993_WSEQ_EINT_SHIFT 13 /* WSEQ_EINT */
568#define WM8993_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */
569#define WM8993_IRQ 0x1000 /* IRQ */
570#define WM8993_IRQ_MASK 0x1000 /* IRQ */
571#define WM8993_IRQ_SHIFT 12 /* IRQ */
572#define WM8993_IRQ_WIDTH 1 /* IRQ */
573#define WM8993_TEMPOK_EINT 0x0800 /* TEMPOK_EINT */
574#define WM8993_TEMPOK_EINT_MASK 0x0800 /* TEMPOK_EINT */
575#define WM8993_TEMPOK_EINT_SHIFT 11 /* TEMPOK_EINT */
576#define WM8993_TEMPOK_EINT_WIDTH 1 /* TEMPOK_EINT */
577#define WM8993_JD1_SC_EINT 0x0400 /* JD1_SC_EINT */
578#define WM8993_JD1_SC_EINT_MASK 0x0400 /* JD1_SC_EINT */
579#define WM8993_JD1_SC_EINT_SHIFT 10 /* JD1_SC_EINT */
580#define WM8993_JD1_SC_EINT_WIDTH 1 /* JD1_SC_EINT */
581#define WM8993_JD1_EINT 0x0200 /* JD1_EINT */
582#define WM8993_JD1_EINT_MASK 0x0200 /* JD1_EINT */
583#define WM8993_JD1_EINT_SHIFT 9 /* JD1_EINT */
584#define WM8993_JD1_EINT_WIDTH 1 /* JD1_EINT */
585#define WM8993_FLL_LOCK_EINT 0x0100 /* FLL_LOCK_EINT */
586#define WM8993_FLL_LOCK_EINT_MASK 0x0100 /* FLL_LOCK_EINT */
587#define WM8993_FLL_LOCK_EINT_SHIFT 8 /* FLL_LOCK_EINT */
588#define WM8993_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
589#define WM8993_GPI8_EINT 0x0080 /* GPI8_EINT */
590#define WM8993_GPI8_EINT_MASK 0x0080 /* GPI8_EINT */
591#define WM8993_GPI8_EINT_SHIFT 7 /* GPI8_EINT */
592#define WM8993_GPI8_EINT_WIDTH 1 /* GPI8_EINT */
593#define WM8993_GPI7_EINT 0x0040 /* GPI7_EINT */
594#define WM8993_GPI7_EINT_MASK 0x0040 /* GPI7_EINT */
595#define WM8993_GPI7_EINT_SHIFT 6 /* GPI7_EINT */
596#define WM8993_GPI7_EINT_WIDTH 1 /* GPI7_EINT */
597#define WM8993_GPIO1_EINT 0x0001 /* GPIO1_EINT */
598#define WM8993_GPIO1_EINT_MASK 0x0001 /* GPIO1_EINT */
599#define WM8993_GPIO1_EINT_SHIFT 0 /* GPIO1_EINT */
600#define WM8993_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */
601
602/*
603 * R19 (0x13) - GPIO1
604 */
605#define WM8993_GPIO1_PU 0x0020 /* GPIO1_PU */
606#define WM8993_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
607#define WM8993_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
608#define WM8993_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
609#define WM8993_GPIO1_PD 0x0010 /* GPIO1_PD */
610#define WM8993_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
611#define WM8993_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
612#define WM8993_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
613#define WM8993_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
614#define WM8993_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
615#define WM8993_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
616
617/*
618 * R20 (0x14) - IRQ_DEBOUNCE
619 */
620#define WM8993_JD2_SC_DB 0x8000 /* JD2_SC_DB */
621#define WM8993_JD2_SC_DB_MASK 0x8000 /* JD2_SC_DB */
622#define WM8993_JD2_SC_DB_SHIFT 15 /* JD2_SC_DB */
623#define WM8993_JD2_SC_DB_WIDTH 1 /* JD2_SC_DB */
624#define WM8993_JD2_DB 0x4000 /* JD2_DB */
625#define WM8993_JD2_DB_MASK 0x4000 /* JD2_DB */
626#define WM8993_JD2_DB_SHIFT 14 /* JD2_DB */
627#define WM8993_JD2_DB_WIDTH 1 /* JD2_DB */
628#define WM8993_WSEQ_DB 0x2000 /* WSEQ_DB */
629#define WM8993_WSEQ_DB_MASK 0x2000 /* WSEQ_DB */
630#define WM8993_WSEQ_DB_SHIFT 13 /* WSEQ_DB */
631#define WM8993_WSEQ_DB_WIDTH 1 /* WSEQ_DB */
632#define WM8993_TEMPOK_DB 0x0800 /* TEMPOK_DB */
633#define WM8993_TEMPOK_DB_MASK 0x0800 /* TEMPOK_DB */
634#define WM8993_TEMPOK_DB_SHIFT 11 /* TEMPOK_DB */
635#define WM8993_TEMPOK_DB_WIDTH 1 /* TEMPOK_DB */
636#define WM8993_JD1_SC_DB 0x0400 /* JD1_SC_DB */
637#define WM8993_JD1_SC_DB_MASK 0x0400 /* JD1_SC_DB */
638#define WM8993_JD1_SC_DB_SHIFT 10 /* JD1_SC_DB */
639#define WM8993_JD1_SC_DB_WIDTH 1 /* JD1_SC_DB */
640#define WM8993_JD1_DB 0x0200 /* JD1_DB */
641#define WM8993_JD1_DB_MASK 0x0200 /* JD1_DB */
642#define WM8993_JD1_DB_SHIFT 9 /* JD1_DB */
643#define WM8993_JD1_DB_WIDTH 1 /* JD1_DB */
644#define WM8993_FLL_LOCK_DB 0x0100 /* FLL_LOCK_DB */
645#define WM8993_FLL_LOCK_DB_MASK 0x0100 /* FLL_LOCK_DB */
646#define WM8993_FLL_LOCK_DB_SHIFT 8 /* FLL_LOCK_DB */
647#define WM8993_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */
648#define WM8993_GPI8_DB 0x0080 /* GPI8_DB */
649#define WM8993_GPI8_DB_MASK 0x0080 /* GPI8_DB */
650#define WM8993_GPI8_DB_SHIFT 7 /* GPI8_DB */
651#define WM8993_GPI8_DB_WIDTH 1 /* GPI8_DB */
652#define WM8993_GPI7_DB 0x0008 /* GPI7_DB */
653#define WM8993_GPI7_DB_MASK 0x0008 /* GPI7_DB */
654#define WM8993_GPI7_DB_SHIFT 3 /* GPI7_DB */
655#define WM8993_GPI7_DB_WIDTH 1 /* GPI7_DB */
656#define WM8993_GPIO1_DB 0x0001 /* GPIO1_DB */
657#define WM8993_GPIO1_DB_MASK 0x0001 /* GPIO1_DB */
658#define WM8993_GPIO1_DB_SHIFT 0 /* GPIO1_DB */
659#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */
660
661/*
662 * R22 (0x16) - GPIOCTRL 2
663 */
664#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */
665#define WM8993_IM_JD2_EINT_MASK 0x2000 /* IM_JD2_EINT */
666#define WM8993_IM_JD2_EINT_SHIFT 13 /* IM_JD2_EINT */
667#define WM8993_IM_JD2_EINT_WIDTH 1 /* IM_JD2_EINT */
668#define WM8993_IM_JD2_SC_EINT 0x1000 /* IM_JD2_SC_EINT */
669#define WM8993_IM_JD2_SC_EINT_MASK 0x1000 /* IM_JD2_SC_EINT */
670#define WM8993_IM_JD2_SC_EINT_SHIFT 12 /* IM_JD2_SC_EINT */
671#define WM8993_IM_JD2_SC_EINT_WIDTH 1 /* IM_JD2_SC_EINT */
672#define WM8993_IM_TEMPOK_EINT 0x0800 /* IM_TEMPOK_EINT */
673#define WM8993_IM_TEMPOK_EINT_MASK 0x0800 /* IM_TEMPOK_EINT */
674#define WM8993_IM_TEMPOK_EINT_SHIFT 11 /* IM_TEMPOK_EINT */
675#define WM8993_IM_TEMPOK_EINT_WIDTH 1 /* IM_TEMPOK_EINT */
676#define WM8993_IM_JD1_SC_EINT 0x0400 /* IM_JD1_SC_EINT */
677#define WM8993_IM_JD1_SC_EINT_MASK 0x0400 /* IM_JD1_SC_EINT */
678#define WM8993_IM_JD1_SC_EINT_SHIFT 10 /* IM_JD1_SC_EINT */
679#define WM8993_IM_JD1_SC_EINT_WIDTH 1 /* IM_JD1_SC_EINT */
680#define WM8993_IM_JD1_EINT 0x0200 /* IM_JD1_EINT */
681#define WM8993_IM_JD1_EINT_MASK 0x0200 /* IM_JD1_EINT */
682#define WM8993_IM_JD1_EINT_SHIFT 9 /* IM_JD1_EINT */
683#define WM8993_IM_JD1_EINT_WIDTH 1 /* IM_JD1_EINT */
684#define WM8993_IM_FLL_LOCK_EINT 0x0100 /* IM_FLL_LOCK_EINT */
685#define WM8993_IM_FLL_LOCK_EINT_MASK 0x0100 /* IM_FLL_LOCK_EINT */
686#define WM8993_IM_FLL_LOCK_EINT_SHIFT 8 /* IM_FLL_LOCK_EINT */
687#define WM8993_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
688#define WM8993_IM_GPI8_EINT 0x0040 /* IM_GPI8_EINT */
689#define WM8993_IM_GPI8_EINT_MASK 0x0040 /* IM_GPI8_EINT */
690#define WM8993_IM_GPI8_EINT_SHIFT 6 /* IM_GPI8_EINT */
691#define WM8993_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */
692#define WM8993_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */
693#define WM8993_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */
694#define WM8993_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */
695#define WM8993_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */
696#define WM8993_GPI8_ENA 0x0010 /* GPI8_ENA */
697#define WM8993_GPI8_ENA_MASK 0x0010 /* GPI8_ENA */
698#define WM8993_GPI8_ENA_SHIFT 4 /* GPI8_ENA */
699#define WM8993_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
700#define WM8993_IM_GPI7_EINT 0x0004 /* IM_GPI7_EINT */
701#define WM8993_IM_GPI7_EINT_MASK 0x0004 /* IM_GPI7_EINT */
702#define WM8993_IM_GPI7_EINT_SHIFT 2 /* IM_GPI7_EINT */
703#define WM8993_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */
704#define WM8993_IM_WSEQ_EINT 0x0002 /* IM_WSEQ_EINT */
705#define WM8993_IM_WSEQ_EINT_MASK 0x0002 /* IM_WSEQ_EINT */
706#define WM8993_IM_WSEQ_EINT_SHIFT 1 /* IM_WSEQ_EINT */
707#define WM8993_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */
708#define WM8993_GPI7_ENA 0x0001 /* GPI7_ENA */
709#define WM8993_GPI7_ENA_MASK 0x0001 /* GPI7_ENA */
710#define WM8993_GPI7_ENA_SHIFT 0 /* GPI7_ENA */
711#define WM8993_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
712
713/*
714 * R23 (0x17) - GPIO_POL
715 */
716#define WM8993_JD2_SC_POL 0x8000 /* JD2_SC_POL */
717#define WM8993_JD2_SC_POL_MASK 0x8000 /* JD2_SC_POL */
718#define WM8993_JD2_SC_POL_SHIFT 15 /* JD2_SC_POL */
719#define WM8993_JD2_SC_POL_WIDTH 1 /* JD2_SC_POL */
720#define WM8993_JD2_POL 0x4000 /* JD2_POL */
721#define WM8993_JD2_POL_MASK 0x4000 /* JD2_POL */
722#define WM8993_JD2_POL_SHIFT 14 /* JD2_POL */
723#define WM8993_JD2_POL_WIDTH 1 /* JD2_POL */
724#define WM8993_WSEQ_POL 0x2000 /* WSEQ_POL */
725#define WM8993_WSEQ_POL_MASK 0x2000 /* WSEQ_POL */
726#define WM8993_WSEQ_POL_SHIFT 13 /* WSEQ_POL */
727#define WM8993_WSEQ_POL_WIDTH 1 /* WSEQ_POL */
728#define WM8993_IRQ_POL 0x1000 /* IRQ_POL */
729#define WM8993_IRQ_POL_MASK 0x1000 /* IRQ_POL */
730#define WM8993_IRQ_POL_SHIFT 12 /* IRQ_POL */
731#define WM8993_IRQ_POL_WIDTH 1 /* IRQ_POL */
732#define WM8993_TEMPOK_POL 0x0800 /* TEMPOK_POL */
733#define WM8993_TEMPOK_POL_MASK 0x0800 /* TEMPOK_POL */
734#define WM8993_TEMPOK_POL_SHIFT 11 /* TEMPOK_POL */
735#define WM8993_TEMPOK_POL_WIDTH 1 /* TEMPOK_POL */
736#define WM8993_JD1_SC_POL 0x0400 /* JD1_SC_POL */
737#define WM8993_JD1_SC_POL_MASK 0x0400 /* JD1_SC_POL */
738#define WM8993_JD1_SC_POL_SHIFT 10 /* JD1_SC_POL */
739#define WM8993_JD1_SC_POL_WIDTH 1 /* JD1_SC_POL */
740#define WM8993_JD1_POL 0x0200 /* JD1_POL */
741#define WM8993_JD1_POL_MASK 0x0200 /* JD1_POL */
742#define WM8993_JD1_POL_SHIFT 9 /* JD1_POL */
743#define WM8993_JD1_POL_WIDTH 1 /* JD1_POL */
744#define WM8993_FLL_LOCK_POL 0x0100 /* FLL_LOCK_POL */
745#define WM8993_FLL_LOCK_POL_MASK 0x0100 /* FLL_LOCK_POL */
746#define WM8993_FLL_LOCK_POL_SHIFT 8 /* FLL_LOCK_POL */
747#define WM8993_FLL_LOCK_POL_WIDTH 1 /* FLL_LOCK_POL */
748#define WM8993_GPI8_POL 0x0080 /* GPI8_POL */
749#define WM8993_GPI8_POL_MASK 0x0080 /* GPI8_POL */
750#define WM8993_GPI8_POL_SHIFT 7 /* GPI8_POL */
751#define WM8993_GPI8_POL_WIDTH 1 /* GPI8_POL */
752#define WM8993_GPI7_POL 0x0040 /* GPI7_POL */
753#define WM8993_GPI7_POL_MASK 0x0040 /* GPI7_POL */
754#define WM8993_GPI7_POL_SHIFT 6 /* GPI7_POL */
755#define WM8993_GPI7_POL_WIDTH 1 /* GPI7_POL */
756#define WM8993_GPIO1_POL 0x0001 /* GPIO1_POL */
757#define WM8993_GPIO1_POL_MASK 0x0001 /* GPIO1_POL */
758#define WM8993_GPIO1_POL_SHIFT 0 /* GPIO1_POL */
759#define WM8993_GPIO1_POL_WIDTH 1 /* GPIO1_POL */
760
761/*
762 * R24 (0x18) - Left Line Input 1&2 Volume
763 */
764#define WM8993_IN1_VU 0x0100 /* IN1_VU */
765#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */
766#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */
767#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */
768#define WM8993_IN1L_MUTE 0x0080 /* IN1L_MUTE */
769#define WM8993_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */
770#define WM8993_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */
771#define WM8993_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
772#define WM8993_IN1L_ZC 0x0040 /* IN1L_ZC */
773#define WM8993_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */
774#define WM8993_IN1L_ZC_SHIFT 6 /* IN1L_ZC */
775#define WM8993_IN1L_ZC_WIDTH 1 /* IN1L_ZC */
776#define WM8993_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */
777#define WM8993_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */
778#define WM8993_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */
779
780/*
781 * R25 (0x19) - Left Line Input 3&4 Volume
782 */
783#define WM8993_IN2_VU 0x0100 /* IN2_VU */
784#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */
785#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */
786#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */
787#define WM8993_IN2L_MUTE 0x0080 /* IN2L_MUTE */
788#define WM8993_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */
789#define WM8993_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */
790#define WM8993_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
791#define WM8993_IN2L_ZC 0x0040 /* IN2L_ZC */
792#define WM8993_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */
793#define WM8993_IN2L_ZC_SHIFT 6 /* IN2L_ZC */
794#define WM8993_IN2L_ZC_WIDTH 1 /* IN2L_ZC */
795#define WM8993_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */
796#define WM8993_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */
797#define WM8993_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */
798
799/*
800 * R26 (0x1A) - Right Line Input 1&2 Volume
801 */
802#define WM8993_IN1_VU 0x0100 /* IN1_VU */
803#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */
804#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */
805#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */
806#define WM8993_IN1R_MUTE 0x0080 /* IN1R_MUTE */
807#define WM8993_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */
808#define WM8993_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */
809#define WM8993_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
810#define WM8993_IN1R_ZC 0x0040 /* IN1R_ZC */
811#define WM8993_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */
812#define WM8993_IN1R_ZC_SHIFT 6 /* IN1R_ZC */
813#define WM8993_IN1R_ZC_WIDTH 1 /* IN1R_ZC */
814#define WM8993_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */
815#define WM8993_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */
816#define WM8993_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */
817
818/*
819 * R27 (0x1B) - Right Line Input 3&4 Volume
820 */
821#define WM8993_IN2_VU 0x0100 /* IN2_VU */
822#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */
823#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */
824#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */
825#define WM8993_IN2R_MUTE 0x0080 /* IN2R_MUTE */
826#define WM8993_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */
827#define WM8993_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */
828#define WM8993_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
829#define WM8993_IN2R_ZC 0x0040 /* IN2R_ZC */
830#define WM8993_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */
831#define WM8993_IN2R_ZC_SHIFT 6 /* IN2R_ZC */
832#define WM8993_IN2R_ZC_WIDTH 1 /* IN2R_ZC */
833#define WM8993_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */
834#define WM8993_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */
835#define WM8993_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */
836
837/*
838 * R28 (0x1C) - Left Output Volume
839 */
840#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */
841#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
842#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
843#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
844#define WM8993_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */
845#define WM8993_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */
846#define WM8993_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */
847#define WM8993_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */
848#define WM8993_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */
849#define WM8993_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */
850#define WM8993_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */
851#define WM8993_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */
852#define WM8993_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */
853#define WM8993_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */
854#define WM8993_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */
855
856/*
857 * R29 (0x1D) - Right Output Volume
858 */
859#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */
860#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
861#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
862#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
863#define WM8993_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */
864#define WM8993_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */
865#define WM8993_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */
866#define WM8993_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */
867#define WM8993_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */
868#define WM8993_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */
869#define WM8993_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */
870#define WM8993_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */
871#define WM8993_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */
872#define WM8993_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */
873#define WM8993_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */
874
875/*
876 * R30 (0x1E) - Line Outputs Volume
877 */
878#define WM8993_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */
879#define WM8993_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */
880#define WM8993_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */
881#define WM8993_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */
882#define WM8993_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */
883#define WM8993_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */
884#define WM8993_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */
885#define WM8993_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */
886#define WM8993_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */
887#define WM8993_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */
888#define WM8993_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */
889#define WM8993_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */
890#define WM8993_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */
891#define WM8993_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */
892#define WM8993_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */
893#define WM8993_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */
894#define WM8993_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */
895#define WM8993_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */
896#define WM8993_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */
897#define WM8993_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */
898#define WM8993_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */
899#define WM8993_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */
900#define WM8993_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */
901#define WM8993_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */
902
903/*
904 * R31 (0x1F) - HPOUT2 Volume
905 */
906#define WM8993_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */
907#define WM8993_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */
908#define WM8993_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */
909#define WM8993_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */
910#define WM8993_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */
911#define WM8993_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */
912#define WM8993_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */
913#define WM8993_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */
914
915/*
916 * R32 (0x20) - Left OPGA Volume
917 */
918#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */
919#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
920#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
921#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
922#define WM8993_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */
923#define WM8993_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */
924#define WM8993_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */
925#define WM8993_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */
926#define WM8993_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */
927#define WM8993_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */
928#define WM8993_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */
929#define WM8993_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */
930#define WM8993_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */
931#define WM8993_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */
932#define WM8993_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */
933
934/*
935 * R33 (0x21) - Right OPGA Volume
936 */
937#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */
938#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
939#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
940#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
941#define WM8993_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */
942#define WM8993_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */
943#define WM8993_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */
944#define WM8993_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */
945#define WM8993_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */
946#define WM8993_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */
947#define WM8993_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */
948#define WM8993_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */
949#define WM8993_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */
950#define WM8993_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */
951#define WM8993_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */
952
953/*
954 * R34 (0x22) - SPKMIXL Attenuation
955 */
956#define WM8993_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */
957#define WM8993_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */
958#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */
959#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
960#define WM8993_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */
961#define WM8993_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */
962#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */
963#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */
964#define WM8993_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */
965#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */
966#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */
967#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */
968#define WM8993_DACL_SPKMIXL_VOL 0x0004 /* DACL_SPKMIXL_VOL */
969#define WM8993_DACL_SPKMIXL_VOL_MASK 0x0004 /* DACL_SPKMIXL_VOL */
970#define WM8993_DACL_SPKMIXL_VOL_SHIFT 2 /* DACL_SPKMIXL_VOL */
971#define WM8993_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */
972#define WM8993_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */
973#define WM8993_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */
974#define WM8993_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */
975
976/*
977 * R35 (0x23) - SPKMIXR Attenuation
978 */
979#define WM8993_SPKOUT_CLASSAB_MODE 0x0100 /* SPKOUT_CLASSAB_MODE */
980#define WM8993_SPKOUT_CLASSAB_MODE_MASK 0x0100 /* SPKOUT_CLASSAB_MODE */
981#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT 8 /* SPKOUT_CLASSAB_MODE */
982#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH 1 /* SPKOUT_CLASSAB_MODE */
983#define WM8993_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */
984#define WM8993_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */
985#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */
986#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
987#define WM8993_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */
988#define WM8993_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */
989#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */
990#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */
991#define WM8993_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */
992#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */
993#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */
994#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */
995#define WM8993_DACR_SPKMIXR_VOL 0x0004 /* DACR_SPKMIXR_VOL */
996#define WM8993_DACR_SPKMIXR_VOL_MASK 0x0004 /* DACR_SPKMIXR_VOL */
997#define WM8993_DACR_SPKMIXR_VOL_SHIFT 2 /* DACR_SPKMIXR_VOL */
998#define WM8993_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */
999#define WM8993_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */
1000#define WM8993_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */
1001#define WM8993_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */
1002
1003/*
1004 * R36 (0x24) - SPKOUT Mixers
1005 */
1006#define WM8993_VRX_TO_SPKOUTL 0x0020 /* VRX_TO_SPKOUTL */
1007#define WM8993_VRX_TO_SPKOUTL_MASK 0x0020 /* VRX_TO_SPKOUTL */
1008#define WM8993_VRX_TO_SPKOUTL_SHIFT 5 /* VRX_TO_SPKOUTL */
1009#define WM8993_VRX_TO_SPKOUTL_WIDTH 1 /* VRX_TO_SPKOUTL */
1010#define WM8993_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */
1011#define WM8993_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */
1012#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */
1013#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */
1014#define WM8993_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */
1015#define WM8993_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */
1016#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */
1017#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */
1018#define WM8993_VRX_TO_SPKOUTR 0x0004 /* VRX_TO_SPKOUTR */
1019#define WM8993_VRX_TO_SPKOUTR_MASK 0x0004 /* VRX_TO_SPKOUTR */
1020#define WM8993_VRX_TO_SPKOUTR_SHIFT 2 /* VRX_TO_SPKOUTR */
1021#define WM8993_VRX_TO_SPKOUTR_WIDTH 1 /* VRX_TO_SPKOUTR */
1022#define WM8993_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */
1023#define WM8993_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */
1024#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */
1025#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */
1026#define WM8993_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */
1027#define WM8993_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */
1028#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */
1029#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */
1030
1031/*
1032 * R37 (0x25) - SPKOUT Boost
1033 */
1034#define WM8993_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */
1035#define WM8993_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */
1036#define WM8993_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */
1037#define WM8993_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */
1038#define WM8993_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */
1039#define WM8993_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */
1040
1041/*
1042 * R38 (0x26) - Speaker Volume Left
1043 */
1044#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */
1045#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
1046#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
1047#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
1048#define WM8993_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
1049#define WM8993_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
1050#define WM8993_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
1051#define WM8993_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
1052#define WM8993_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */
1053#define WM8993_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */
1054#define WM8993_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */
1055#define WM8993_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */
1056#define WM8993_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */
1057#define WM8993_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */
1058#define WM8993_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */
1059
1060/*
1061 * R39 (0x27) - Speaker Volume Right
1062 */
1063#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */
1064#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
1065#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
1066#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
1067#define WM8993_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
1068#define WM8993_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
1069#define WM8993_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
1070#define WM8993_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
1071#define WM8993_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */
1072#define WM8993_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */
1073#define WM8993_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */
1074#define WM8993_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */
1075#define WM8993_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */
1076#define WM8993_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */
1077#define WM8993_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */
1078
1079/*
1080 * R40 (0x28) - Input Mixer2
1081 */
1082#define WM8993_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */
1083#define WM8993_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */
1084#define WM8993_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */
1085#define WM8993_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */
1086#define WM8993_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */
1087#define WM8993_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */
1088#define WM8993_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */
1089#define WM8993_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */
1090#define WM8993_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */
1091#define WM8993_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */
1092#define WM8993_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */
1093#define WM8993_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */
1094#define WM8993_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */
1095#define WM8993_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */
1096#define WM8993_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */
1097#define WM8993_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */
1098#define WM8993_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */
1099#define WM8993_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */
1100#define WM8993_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */
1101#define WM8993_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */
1102#define WM8993_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */
1103#define WM8993_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */
1104#define WM8993_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */
1105#define WM8993_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */
1106#define WM8993_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */
1107#define WM8993_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */
1108#define WM8993_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */
1109#define WM8993_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */
1110#define WM8993_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */
1111#define WM8993_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */
1112#define WM8993_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */
1113#define WM8993_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */
1114
1115/*
1116 * R41 (0x29) - Input Mixer3
1117 */
1118#define WM8993_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */
1119#define WM8993_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */
1120#define WM8993_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */
1121#define WM8993_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
1122#define WM8993_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */
1123#define WM8993_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */
1124#define WM8993_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */
1125#define WM8993_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */
1126#define WM8993_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */
1127#define WM8993_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */
1128#define WM8993_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */
1129#define WM8993_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */
1130#define WM8993_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */
1131#define WM8993_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */
1132#define WM8993_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */
1133#define WM8993_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */
1134#define WM8993_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */
1135#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */
1136#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */
1137
1138/*
1139 * R42 (0x2A) - Input Mixer4
1140 */
1141#define WM8993_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */
1142#define WM8993_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */
1143#define WM8993_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */
1144#define WM8993_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
1145#define WM8993_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */
1146#define WM8993_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */
1147#define WM8993_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */
1148#define WM8993_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */
1149#define WM8993_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */
1150#define WM8993_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */
1151#define WM8993_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */
1152#define WM8993_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */
1153#define WM8993_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */
1154#define WM8993_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */
1155#define WM8993_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */
1156#define WM8993_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */
1157#define WM8993_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */
1158#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */
1159#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */
1160
1161/*
1162 * R43 (0x2B) - Input Mixer5
1163 */
1164#define WM8993_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */
1165#define WM8993_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */
1166#define WM8993_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */
1167#define WM8993_VRX_MIXINL_VOL_MASK 0x0007 /* VRX_MIXINL_VOL - [2:0] */
1168#define WM8993_VRX_MIXINL_VOL_SHIFT 0 /* VRX_MIXINL_VOL - [2:0] */
1169#define WM8993_VRX_MIXINL_VOL_WIDTH 3 /* VRX_MIXINL_VOL - [2:0] */
1170
1171/*
1172 * R44 (0x2C) - Input Mixer6
1173 */
1174#define WM8993_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */
1175#define WM8993_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */
1176#define WM8993_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */
1177#define WM8993_VRX_MIXINR_VOL_MASK 0x0007 /* VRX_MIXINR_VOL - [2:0] */
1178#define WM8993_VRX_MIXINR_VOL_SHIFT 0 /* VRX_MIXINR_VOL - [2:0] */
1179#define WM8993_VRX_MIXINR_VOL_WIDTH 3 /* VRX_MIXINR_VOL - [2:0] */
1180
1181/*
1182 * R45 (0x2D) - Output Mixer1
1183 */
1184#define WM8993_DACL_TO_HPOUT1L 0x0100 /* DACL_TO_HPOUT1L */
1185#define WM8993_DACL_TO_HPOUT1L_MASK 0x0100 /* DACL_TO_HPOUT1L */
1186#define WM8993_DACL_TO_HPOUT1L_SHIFT 8 /* DACL_TO_HPOUT1L */
1187#define WM8993_DACL_TO_HPOUT1L_WIDTH 1 /* DACL_TO_HPOUT1L */
1188#define WM8993_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */
1189#define WM8993_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */
1190#define WM8993_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */
1191#define WM8993_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */
1192#define WM8993_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */
1193#define WM8993_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */
1194#define WM8993_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */
1195#define WM8993_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */
1196#define WM8993_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */
1197#define WM8993_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */
1198#define WM8993_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */
1199#define WM8993_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */
1200#define WM8993_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */
1201#define WM8993_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */
1202#define WM8993_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */
1203#define WM8993_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */
1204#define WM8993_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */
1205#define WM8993_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */
1206#define WM8993_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */
1207#define WM8993_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */
1208#define WM8993_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */
1209#define WM8993_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */
1210#define WM8993_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */
1211#define WM8993_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */
1212#define WM8993_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */
1213#define WM8993_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */
1214#define WM8993_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */
1215#define WM8993_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */
1216#define WM8993_DACL_TO_MIXOUTL 0x0001 /* DACL_TO_MIXOUTL */
1217#define WM8993_DACL_TO_MIXOUTL_MASK 0x0001 /* DACL_TO_MIXOUTL */
1218#define WM8993_DACL_TO_MIXOUTL_SHIFT 0 /* DACL_TO_MIXOUTL */
1219#define WM8993_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */
1220
1221/*
1222 * R46 (0x2E) - Output Mixer2
1223 */
1224#define WM8993_DACR_TO_HPOUT1R 0x0100 /* DACR_TO_HPOUT1R */
1225#define WM8993_DACR_TO_HPOUT1R_MASK 0x0100 /* DACR_TO_HPOUT1R */
1226#define WM8993_DACR_TO_HPOUT1R_SHIFT 8 /* DACR_TO_HPOUT1R */
1227#define WM8993_DACR_TO_HPOUT1R_WIDTH 1 /* DACR_TO_HPOUT1R */
1228#define WM8993_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */
1229#define WM8993_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */
1230#define WM8993_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */
1231#define WM8993_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */
1232#define WM8993_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */
1233#define WM8993_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */
1234#define WM8993_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */
1235#define WM8993_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */
1236#define WM8993_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */
1237#define WM8993_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */
1238#define WM8993_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */
1239#define WM8993_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */
1240#define WM8993_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */
1241#define WM8993_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */
1242#define WM8993_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */
1243#define WM8993_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */
1244#define WM8993_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */
1245#define WM8993_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */
1246#define WM8993_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */
1247#define WM8993_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */
1248#define WM8993_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */
1249#define WM8993_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */
1250#define WM8993_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */
1251#define WM8993_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */
1252#define WM8993_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */
1253#define WM8993_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */
1254#define WM8993_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */
1255#define WM8993_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */
1256#define WM8993_DACR_TO_MIXOUTR 0x0001 /* DACR_TO_MIXOUTR */
1257#define WM8993_DACR_TO_MIXOUTR_MASK 0x0001 /* DACR_TO_MIXOUTR */
1258#define WM8993_DACR_TO_MIXOUTR_SHIFT 0 /* DACR_TO_MIXOUTR */
1259#define WM8993_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */
1260
1261/*
1262 * R47 (0x2F) - Output Mixer3
1263 */
1264#define WM8993_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */
1265#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */
1266#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */
1267#define WM8993_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */
1268#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */
1269#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */
1270#define WM8993_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */
1271#define WM8993_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */
1272#define WM8993_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */
1273#define WM8993_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */
1274#define WM8993_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */
1275#define WM8993_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */
1276
1277/*
1278 * R48 (0x30) - Output Mixer4
1279 */
1280#define WM8993_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */
1281#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */
1282#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */
1283#define WM8993_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */
1284#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */
1285#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */
1286#define WM8993_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */
1287#define WM8993_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */
1288#define WM8993_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */
1289#define WM8993_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */
1290#define WM8993_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */
1291#define WM8993_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */
1292
1293/*
1294 * R49 (0x31) - Output Mixer5
1295 */
1296#define WM8993_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */
1297#define WM8993_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */
1298#define WM8993_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */
1299#define WM8993_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */
1300#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */
1301#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */
1302#define WM8993_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */
1303#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
1304#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
1305#define WM8993_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */
1306#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */
1307#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */
1308
1309/*
1310 * R50 (0x32) - Output Mixer6
1311 */
1312#define WM8993_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */
1313#define WM8993_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */
1314#define WM8993_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */
1315#define WM8993_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */
1316#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */
1317#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */
1318#define WM8993_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */
1319#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
1320#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
1321#define WM8993_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */
1322#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */
1323#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */
1324
1325/*
1326 * R51 (0x33) - HPOUT2 Mixer
1327 */
1328#define WM8993_VRX_TO_HPOUT2 0x0020 /* VRX_TO_HPOUT2 */
1329#define WM8993_VRX_TO_HPOUT2_MASK 0x0020 /* VRX_TO_HPOUT2 */
1330#define WM8993_VRX_TO_HPOUT2_SHIFT 5 /* VRX_TO_HPOUT2 */
1331#define WM8993_VRX_TO_HPOUT2_WIDTH 1 /* VRX_TO_HPOUT2 */
1332#define WM8993_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
1333#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
1334#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */
1335#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */
1336#define WM8993_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
1337#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
1338#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */
1339#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */
1340
1341/*
1342 * R52 (0x34) - Line Mixer1
1343 */
1344#define WM8993_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */
1345#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */
1346#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */
1347#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */
1348#define WM8993_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */
1349#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */
1350#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */
1351#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */
1352#define WM8993_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */
1353#define WM8993_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */
1354#define WM8993_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */
1355#define WM8993_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */
1356#define WM8993_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */
1357#define WM8993_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */
1358#define WM8993_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */
1359#define WM8993_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */
1360#define WM8993_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */
1361#define WM8993_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */
1362#define WM8993_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */
1363#define WM8993_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */
1364#define WM8993_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */
1365#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */
1366#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */
1367#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */
1368
1369/*
1370 * R53 (0x35) - Line Mixer2
1371 */
1372#define WM8993_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */
1373#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */
1374#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */
1375#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */
1376#define WM8993_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */
1377#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */
1378#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */
1379#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */
1380#define WM8993_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */
1381#define WM8993_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */
1382#define WM8993_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */
1383#define WM8993_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */
1384#define WM8993_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */
1385#define WM8993_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */
1386#define WM8993_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */
1387#define WM8993_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */
1388#define WM8993_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */
1389#define WM8993_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */
1390#define WM8993_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */
1391#define WM8993_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */
1392#define WM8993_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */
1393#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */
1394#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */
1395#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */
1396
1397/*
1398 * R54 (0x36) - Speaker Mixer
1399 */
1400#define WM8993_SPKAB_REF_SEL 0x0100 /* SPKAB_REF_SEL */
1401#define WM8993_SPKAB_REF_SEL_MASK 0x0100 /* SPKAB_REF_SEL */
1402#define WM8993_SPKAB_REF_SEL_SHIFT 8 /* SPKAB_REF_SEL */
1403#define WM8993_SPKAB_REF_SEL_WIDTH 1 /* SPKAB_REF_SEL */
1404#define WM8993_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */
1405#define WM8993_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */
1406#define WM8993_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */
1407#define WM8993_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
1408#define WM8993_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */
1409#define WM8993_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */
1410#define WM8993_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */
1411#define WM8993_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
1412#define WM8993_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */
1413#define WM8993_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */
1414#define WM8993_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */
1415#define WM8993_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */
1416#define WM8993_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */
1417#define WM8993_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */
1418#define WM8993_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */
1419#define WM8993_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */
1420#define WM8993_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */
1421#define WM8993_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */
1422#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */
1423#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */
1424#define WM8993_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */
1425#define WM8993_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */
1426#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */
1427#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */
1428#define WM8993_DACL_TO_SPKMIXL 0x0002 /* DACL_TO_SPKMIXL */
1429#define WM8993_DACL_TO_SPKMIXL_MASK 0x0002 /* DACL_TO_SPKMIXL */
1430#define WM8993_DACL_TO_SPKMIXL_SHIFT 1 /* DACL_TO_SPKMIXL */
1431#define WM8993_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */
1432#define WM8993_DACR_TO_SPKMIXR 0x0001 /* DACR_TO_SPKMIXR */
1433#define WM8993_DACR_TO_SPKMIXR_MASK 0x0001 /* DACR_TO_SPKMIXR */
1434#define WM8993_DACR_TO_SPKMIXR_SHIFT 0 /* DACR_TO_SPKMIXR */
1435#define WM8993_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */
1436
1437/*
1438 * R55 (0x37) - Additional Control
1439 */
1440#define WM8993_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */
1441#define WM8993_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */
1442#define WM8993_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */
1443#define WM8993_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */
1444#define WM8993_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */
1445#define WM8993_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */
1446#define WM8993_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */
1447#define WM8993_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */
1448#define WM8993_VROI 0x0001 /* VROI */
1449#define WM8993_VROI_MASK 0x0001 /* VROI */
1450#define WM8993_VROI_SHIFT 0 /* VROI */
1451#define WM8993_VROI_WIDTH 1 /* VROI */
1452
1453/*
1454 * R56 (0x38) - AntiPOP1
1455 */
1456#define WM8993_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */
1457#define WM8993_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */
1458#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */
1459#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */
1460#define WM8993_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */
1461#define WM8993_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */
1462#define WM8993_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */
1463#define WM8993_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */
1464#define WM8993_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */
1465#define WM8993_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */
1466#define WM8993_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */
1467#define WM8993_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */
1468#define WM8993_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */
1469#define WM8993_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */
1470#define WM8993_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */
1471#define WM8993_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */
1472
1473/*
1474 * R57 (0x39) - AntiPOP2
1475 */
1476#define WM8993_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */
1477#define WM8993_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */
1478#define WM8993_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */
1479#define WM8993_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
1480#define WM8993_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
1481#define WM8993_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
1482#define WM8993_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
1483#define WM8993_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */
1484#define WM8993_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */
1485#define WM8993_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */
1486#define WM8993_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
1487#define WM8993_BIAS_SRC 0x0002 /* BIAS_SRC */
1488#define WM8993_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */
1489#define WM8993_BIAS_SRC_SHIFT 1 /* BIAS_SRC */
1490#define WM8993_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
1491#define WM8993_VMID_DISCH 0x0001 /* VMID_DISCH */
1492#define WM8993_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */
1493#define WM8993_VMID_DISCH_SHIFT 0 /* VMID_DISCH */
1494#define WM8993_VMID_DISCH_WIDTH 1 /* VMID_DISCH */
1495
1496/*
1497 * R58 (0x3A) - MICBIAS
1498 */
1499#define WM8993_JD_SCTHR_MASK 0x00C0 /* JD_SCTHR - [7:6] */
1500#define WM8993_JD_SCTHR_SHIFT 6 /* JD_SCTHR - [7:6] */
1501#define WM8993_JD_SCTHR_WIDTH 2 /* JD_SCTHR - [7:6] */
1502#define WM8993_JD_THR_MASK 0x0030 /* JD_THR - [5:4] */
1503#define WM8993_JD_THR_SHIFT 4 /* JD_THR - [5:4] */
1504#define WM8993_JD_THR_WIDTH 2 /* JD_THR - [5:4] */
1505#define WM8993_JD_ENA 0x0004 /* JD_ENA */
1506#define WM8993_JD_ENA_MASK 0x0004 /* JD_ENA */
1507#define WM8993_JD_ENA_SHIFT 2 /* JD_ENA */
1508#define WM8993_JD_ENA_WIDTH 1 /* JD_ENA */
1509#define WM8993_MICB2_LVL 0x0002 /* MICB2_LVL */
1510#define WM8993_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */
1511#define WM8993_MICB2_LVL_SHIFT 1 /* MICB2_LVL */
1512#define WM8993_MICB2_LVL_WIDTH 1 /* MICB2_LVL */
1513#define WM8993_MICB1_LVL 0x0001 /* MICB1_LVL */
1514#define WM8993_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */
1515#define WM8993_MICB1_LVL_SHIFT 0 /* MICB1_LVL */
1516#define WM8993_MICB1_LVL_WIDTH 1 /* MICB1_LVL */
1517
1518/*
1519 * R60 (0x3C) - FLL Control 1
1520 */
1521#define WM8993_FLL_FRAC 0x0004 /* FLL_FRAC */
1522#define WM8993_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
1523#define WM8993_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
1524#define WM8993_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
1525#define WM8993_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */
1526#define WM8993_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */
1527#define WM8993_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */
1528#define WM8993_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */
1529#define WM8993_FLL_ENA 0x0001 /* FLL_ENA */
1530#define WM8993_FLL_ENA_MASK 0x0001 /* FLL_ENA */
1531#define WM8993_FLL_ENA_SHIFT 0 /* FLL_ENA */
1532#define WM8993_FLL_ENA_WIDTH 1 /* FLL_ENA */
1533
1534/*
1535 * R61 (0x3D) - FLL Control 2
1536 */
1537#define WM8993_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */
1538#define WM8993_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */
1539#define WM8993_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */
1540#define WM8993_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */
1541#define WM8993_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */
1542#define WM8993_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */
1543#define WM8993_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
1544#define WM8993_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
1545#define WM8993_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
1546
1547/*
1548 * R62 (0x3E) - FLL Control 3
1549 */
1550#define WM8993_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */
1551#define WM8993_FLL_K_SHIFT 0 /* FLL_K - [15:0] */
1552#define WM8993_FLL_K_WIDTH 16 /* FLL_K - [15:0] */
1553
1554/*
1555 * R63 (0x3F) - FLL Control 4
1556 */
1557#define WM8993_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */
1558#define WM8993_FLL_N_SHIFT 5 /* FLL_N - [14:5] */
1559#define WM8993_FLL_N_WIDTH 10 /* FLL_N - [14:5] */
1560#define WM8993_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */
1561#define WM8993_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */
1562#define WM8993_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */
1563
1564/*
1565 * R64 (0x40) - FLL Control 5
1566 */
1567#define WM8993_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */
1568#define WM8993_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */
1569#define WM8993_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */
1570#define WM8993_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */
1571#define WM8993_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */
1572#define WM8993_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */
1573#define WM8993_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */
1574#define WM8993_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */
1575#define WM8993_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */
1576#define WM8993_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */
1577#define WM8993_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */
1578#define WM8993_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */
1579#define WM8993_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */
1580
1581/*
1582 * R65 (0x41) - Clocking 3
1583 */
1584#define WM8993_CLK_DCS_DIV_MASK 0x3C00 /* CLK_DCS_DIV - [13:10] */
1585#define WM8993_CLK_DCS_DIV_SHIFT 10 /* CLK_DCS_DIV - [13:10] */
1586#define WM8993_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [13:10] */
1587#define WM8993_SAMPLE_RATE_MASK 0x0380 /* SAMPLE_RATE - [9:7] */
1588#define WM8993_SAMPLE_RATE_SHIFT 7 /* SAMPLE_RATE - [9:7] */
1589#define WM8993_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [9:7] */
1590#define WM8993_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */
1591#define WM8993_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */
1592#define WM8993_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */
1593#define WM8993_CLK_DSP_ENA 0x0001 /* CLK_DSP_ENA */
1594#define WM8993_CLK_DSP_ENA_MASK 0x0001 /* CLK_DSP_ENA */
1595#define WM8993_CLK_DSP_ENA_SHIFT 0 /* CLK_DSP_ENA */
1596#define WM8993_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
1597
1598/*
1599 * R66 (0x42) - Clocking 4
1600 */
1601#define WM8993_DAC_DIV4 0x0200 /* DAC_DIV4 */
1602#define WM8993_DAC_DIV4_MASK 0x0200 /* DAC_DIV4 */
1603#define WM8993_DAC_DIV4_SHIFT 9 /* DAC_DIV4 */
1604#define WM8993_DAC_DIV4_WIDTH 1 /* DAC_DIV4 */
1605#define WM8993_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */
1606#define WM8993_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */
1607#define WM8993_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */
1608#define WM8993_SR_MODE 0x0001 /* SR_MODE */
1609#define WM8993_SR_MODE_MASK 0x0001 /* SR_MODE */
1610#define WM8993_SR_MODE_SHIFT 0 /* SR_MODE */
1611#define WM8993_SR_MODE_WIDTH 1 /* SR_MODE */
1612
1613/*
1614 * R67 (0x43) - MW Slave Control
1615 */
1616#define WM8993_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */
1617#define WM8993_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */
1618#define WM8993_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */
1619#define WM8993_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */
1620
1621/*
1622 * R69 (0x45) - Bus Control 1
1623 */
1624#define WM8993_CLK_SYS_ENA 0x0002 /* CLK_SYS_ENA */
1625#define WM8993_CLK_SYS_ENA_MASK 0x0002 /* CLK_SYS_ENA */
1626#define WM8993_CLK_SYS_ENA_SHIFT 1 /* CLK_SYS_ENA */
1627#define WM8993_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
1628
1629/*
1630 * R70 (0x46) - Write Sequencer 0
1631 */
1632#define WM8993_WSEQ_ENA 0x0100 /* WSEQ_ENA */
1633#define WM8993_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */
1634#define WM8993_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */
1635#define WM8993_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
1636#define WM8993_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */
1637#define WM8993_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */
1638#define WM8993_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */
1639
1640/*
1641 * R71 (0x47) - Write Sequencer 1
1642 */
1643#define WM8993_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */
1644#define WM8993_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */
1645#define WM8993_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */
1646#define WM8993_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */
1647#define WM8993_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */
1648#define WM8993_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */
1649#define WM8993_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */
1650#define WM8993_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */
1651#define WM8993_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */
1652
1653/*
1654 * R72 (0x48) - Write Sequencer 2
1655 */
1656#define WM8993_WSEQ_EOS 0x4000 /* WSEQ_EOS */
1657#define WM8993_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */
1658#define WM8993_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */
1659#define WM8993_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */
1660#define WM8993_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */
1661#define WM8993_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */
1662#define WM8993_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */
1663#define WM8993_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */
1664#define WM8993_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */
1665#define WM8993_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */
1666
1667/*
1668 * R73 (0x49) - Write Sequencer 3
1669 */
1670#define WM8993_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
1671#define WM8993_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
1672#define WM8993_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
1673#define WM8993_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
1674#define WM8993_WSEQ_START 0x0100 /* WSEQ_START */
1675#define WM8993_WSEQ_START_MASK 0x0100 /* WSEQ_START */
1676#define WM8993_WSEQ_START_SHIFT 8 /* WSEQ_START */
1677#define WM8993_WSEQ_START_WIDTH 1 /* WSEQ_START */
1678#define WM8993_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */
1679#define WM8993_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */
1680#define WM8993_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */
1681
1682/*
1683 * R74 (0x4A) - Write Sequencer 4
1684 */
1685#define WM8993_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
1686#define WM8993_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
1687#define WM8993_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
1688#define WM8993_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
1689
1690/*
1691 * R75 (0x4B) - Write Sequencer 5
1692 */
1693#define WM8993_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */
1694#define WM8993_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */
1695#define WM8993_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */
1696
1697/*
1698 * R76 (0x4C) - Charge Pump 1
1699 */
1700#define WM8993_CP_ENA 0x8000 /* CP_ENA */
1701#define WM8993_CP_ENA_MASK 0x8000 /* CP_ENA */
1702#define WM8993_CP_ENA_SHIFT 15 /* CP_ENA */
1703#define WM8993_CP_ENA_WIDTH 1 /* CP_ENA */
1704
1705/*
1706 * R81 (0x51) - Class W 0
1707 */
1708#define WM8993_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */
1709#define WM8993_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */
1710#define WM8993_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */
1711#define WM8993_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */
1712#define WM8993_CP_DYN_V 0x0001 /* CP_DYN_V */
1713#define WM8993_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */
1714#define WM8993_CP_DYN_V_SHIFT 0 /* CP_DYN_V */
1715#define WM8993_CP_DYN_V_WIDTH 1 /* CP_DYN_V */
1716
1717/*
1718 * R84 (0x54) - DC Servo 0
1719 */
1720#define WM8993_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */
1721#define WM8993_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */
1722#define WM8993_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */
1723#define WM8993_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */
1724#define WM8993_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */
1725#define WM8993_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */
1726#define WM8993_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */
1727#define WM8993_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */
1728#define WM8993_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */
1729#define WM8993_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */
1730#define WM8993_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */
1731#define WM8993_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */
1732#define WM8993_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */
1733#define WM8993_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */
1734#define WM8993_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */
1735#define WM8993_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */
1736#define WM8993_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */
1737#define WM8993_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */
1738#define WM8993_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */
1739#define WM8993_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */
1740#define WM8993_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */
1741#define WM8993_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */
1742#define WM8993_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */
1743#define WM8993_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */
1744#define WM8993_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */
1745#define WM8993_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */
1746#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */
1747#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */
1748#define WM8993_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */
1749#define WM8993_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */
1750#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */
1751#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */
1752#define WM8993_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */
1753#define WM8993_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */
1754#define WM8993_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */
1755#define WM8993_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */
1756#define WM8993_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */
1757#define WM8993_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */
1758#define WM8993_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */
1759#define WM8993_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */
1760
1761/*
1762 * R85 (0x55) - DC Servo 1
1763 */
1764#define WM8993_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */
1765#define WM8993_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */
1766#define WM8993_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */
1767#define WM8993_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */
1768#define WM8993_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */
1769#define WM8993_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */
1770
1771/*
1772 * R87 (0x57) - DC Servo 3
1773 */
1774#define WM8993_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */
1775#define WM8993_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
1776#define WM8993_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
1777#define WM8993_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */
1778#define WM8993_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */
1779#define WM8993_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */
1780
1781/*
1782 * R88 (0x58) - DC Servo Readback 0
1783 */
1784#define WM8993_DCS_DATAPATH_BUSY 0x4000 /* DCS_DATAPATH_BUSY */
1785#define WM8993_DCS_DATAPATH_BUSY_MASK 0x4000 /* DCS_DATAPATH_BUSY */
1786#define WM8993_DCS_DATAPATH_BUSY_SHIFT 14 /* DCS_DATAPATH_BUSY */
1787#define WM8993_DCS_DATAPATH_BUSY_WIDTH 1 /* DCS_DATAPATH_BUSY */
1788#define WM8993_DCS_CHANNEL_MASK 0x3000 /* DCS_CHANNEL - [13:12] */
1789#define WM8993_DCS_CHANNEL_SHIFT 12 /* DCS_CHANNEL - [13:12] */
1790#define WM8993_DCS_CHANNEL_WIDTH 2 /* DCS_CHANNEL - [13:12] */
1791#define WM8993_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */
1792#define WM8993_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */
1793#define WM8993_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */
1794#define WM8993_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */
1795#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */
1796#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */
1797#define WM8993_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */
1798#define WM8993_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */
1799#define WM8993_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */
1800
1801/*
1802 * R89 (0x59) - DC Servo Readback 1
1803 */
1804#define WM8993_DCS_INTEG_CHAN_1_MASK 0x00FF /* DCS_INTEG_CHAN_1 - [7:0] */
1805#define WM8993_DCS_INTEG_CHAN_1_SHIFT 0 /* DCS_INTEG_CHAN_1 - [7:0] */
1806#define WM8993_DCS_INTEG_CHAN_1_WIDTH 8 /* DCS_INTEG_CHAN_1 - [7:0] */
1807
1808/*
1809 * R90 (0x5A) - DC Servo Readback 2
1810 */
1811#define WM8993_DCS_INTEG_CHAN_0_MASK 0x00FF /* DCS_INTEG_CHAN_0 - [7:0] */
1812#define WM8993_DCS_INTEG_CHAN_0_SHIFT 0 /* DCS_INTEG_CHAN_0 - [7:0] */
1813#define WM8993_DCS_INTEG_CHAN_0_WIDTH 8 /* DCS_INTEG_CHAN_0 - [7:0] */
1814
1815/*
1816 * R96 (0x60) - Analogue HP 0
1817 */
1818#define WM8993_HPOUT1_AUTO_PU 0x0100 /* HPOUT1_AUTO_PU */
1819#define WM8993_HPOUT1_AUTO_PU_MASK 0x0100 /* HPOUT1_AUTO_PU */
1820#define WM8993_HPOUT1_AUTO_PU_SHIFT 8 /* HPOUT1_AUTO_PU */
1821#define WM8993_HPOUT1_AUTO_PU_WIDTH 1 /* HPOUT1_AUTO_PU */
1822#define WM8993_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */
1823#define WM8993_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */
1824#define WM8993_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */
1825#define WM8993_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */
1826#define WM8993_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */
1827#define WM8993_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */
1828#define WM8993_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */
1829#define WM8993_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */
1830#define WM8993_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */
1831#define WM8993_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */
1832#define WM8993_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */
1833#define WM8993_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */
1834#define WM8993_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */
1835#define WM8993_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */
1836#define WM8993_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */
1837#define WM8993_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */
1838#define WM8993_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */
1839#define WM8993_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */
1840#define WM8993_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */
1841#define WM8993_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */
1842#define WM8993_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */
1843#define WM8993_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */
1844#define WM8993_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */
1845#define WM8993_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */
1846
1847/*
1848 * R98 (0x62) - EQ1
1849 */
1850#define WM8993_EQ_ENA 0x0001 /* EQ_ENA */
1851#define WM8993_EQ_ENA_MASK 0x0001 /* EQ_ENA */
1852#define WM8993_EQ_ENA_SHIFT 0 /* EQ_ENA */
1853#define WM8993_EQ_ENA_WIDTH 1 /* EQ_ENA */
1854
1855/*
1856 * R99 (0x63) - EQ2
1857 */
1858#define WM8993_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */
1859#define WM8993_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */
1860#define WM8993_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */
1861
1862/*
1863 * R100 (0x64) - EQ3
1864 */
1865#define WM8993_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */
1866#define WM8993_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */
1867#define WM8993_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */
1868
1869/*
1870 * R101 (0x65) - EQ4
1871 */
1872#define WM8993_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */
1873#define WM8993_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */
1874#define WM8993_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */
1875
1876/*
1877 * R102 (0x66) - EQ5
1878 */
1879#define WM8993_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */
1880#define WM8993_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */
1881#define WM8993_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */
1882
1883/*
1884 * R103 (0x67) - EQ6
1885 */
1886#define WM8993_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */
1887#define WM8993_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */
1888#define WM8993_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */
1889
1890/*
1891 * R104 (0x68) - EQ7
1892 */
1893#define WM8993_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */
1894#define WM8993_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */
1895#define WM8993_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */
1896
1897/*
1898 * R105 (0x69) - EQ8
1899 */
1900#define WM8993_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */
1901#define WM8993_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */
1902#define WM8993_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */
1903
1904/*
1905 * R106 (0x6A) - EQ9
1906 */
1907#define WM8993_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */
1908#define WM8993_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */
1909#define WM8993_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */
1910
1911/*
1912 * R107 (0x6B) - EQ10
1913 */
1914#define WM8993_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */
1915#define WM8993_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */
1916#define WM8993_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */
1917
1918/*
1919 * R108 (0x6C) - EQ11
1920 */
1921#define WM8993_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */
1922#define WM8993_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */
1923#define WM8993_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */
1924
1925/*
1926 * R109 (0x6D) - EQ12
1927 */
1928#define WM8993_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */
1929#define WM8993_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */
1930#define WM8993_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */
1931
1932/*
1933 * R110 (0x6E) - EQ13
1934 */
1935#define WM8993_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */
1936#define WM8993_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */
1937#define WM8993_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */
1938
1939/*
1940 * R111 (0x6F) - EQ14
1941 */
1942#define WM8993_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */
1943#define WM8993_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */
1944#define WM8993_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */
1945
1946/*
1947 * R112 (0x70) - EQ15
1948 */
1949#define WM8993_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */
1950#define WM8993_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */
1951#define WM8993_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */
1952
1953/*
1954 * R113 (0x71) - EQ16
1955 */
1956#define WM8993_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */
1957#define WM8993_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */
1958#define WM8993_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */
1959
1960/*
1961 * R114 (0x72) - EQ17
1962 */
1963#define WM8993_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */
1964#define WM8993_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */
1965#define WM8993_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */
1966
1967/*
1968 * R115 (0x73) - EQ18
1969 */
1970#define WM8993_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */
1971#define WM8993_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */
1972#define WM8993_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */
1973
1974/*
1975 * R116 (0x74) - EQ19
1976 */
1977#define WM8993_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */
1978#define WM8993_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */
1979#define WM8993_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */
1980
1981/*
1982 * R117 (0x75) - EQ20
1983 */
1984#define WM8993_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */
1985#define WM8993_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */
1986#define WM8993_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */
1987
1988/*
1989 * R118 (0x76) - EQ21
1990 */
1991#define WM8993_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */
1992#define WM8993_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */
1993#define WM8993_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */
1994
1995/*
1996 * R119 (0x77) - EQ22
1997 */
1998#define WM8993_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */
1999#define WM8993_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */
2000#define WM8993_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */
2001
2002/*
2003 * R120 (0x78) - EQ23
2004 */
2005#define WM8993_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */
2006#define WM8993_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */
2007#define WM8993_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */
2008
2009/*
2010 * R121 (0x79) - EQ24
2011 */
2012#define WM8993_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */
2013#define WM8993_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */
2014#define WM8993_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */
2015
2016/*
2017 * R122 (0x7A) - Digital Pulls
2018 */
2019#define WM8993_MCLK_PU 0x0080 /* MCLK_PU */
2020#define WM8993_MCLK_PU_MASK 0x0080 /* MCLK_PU */
2021#define WM8993_MCLK_PU_SHIFT 7 /* MCLK_PU */
2022#define WM8993_MCLK_PU_WIDTH 1 /* MCLK_PU */
2023#define WM8993_MCLK_PD 0x0040 /* MCLK_PD */
2024#define WM8993_MCLK_PD_MASK 0x0040 /* MCLK_PD */
2025#define WM8993_MCLK_PD_SHIFT 6 /* MCLK_PD */
2026#define WM8993_MCLK_PD_WIDTH 1 /* MCLK_PD */
2027#define WM8993_DACDAT_PU 0x0020 /* DACDAT_PU */
2028#define WM8993_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */
2029#define WM8993_DACDAT_PU_SHIFT 5 /* DACDAT_PU */
2030#define WM8993_DACDAT_PU_WIDTH 1 /* DACDAT_PU */
2031#define WM8993_DACDAT_PD 0x0010 /* DACDAT_PD */
2032#define WM8993_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */
2033#define WM8993_DACDAT_PD_SHIFT 4 /* DACDAT_PD */
2034#define WM8993_DACDAT_PD_WIDTH 1 /* DACDAT_PD */
2035#define WM8993_LRCLK_PU 0x0008 /* LRCLK_PU */
2036#define WM8993_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */
2037#define WM8993_LRCLK_PU_SHIFT 3 /* LRCLK_PU */
2038#define WM8993_LRCLK_PU_WIDTH 1 /* LRCLK_PU */
2039#define WM8993_LRCLK_PD 0x0004 /* LRCLK_PD */
2040#define WM8993_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */
2041#define WM8993_LRCLK_PD_SHIFT 2 /* LRCLK_PD */
2042#define WM8993_LRCLK_PD_WIDTH 1 /* LRCLK_PD */
2043#define WM8993_BCLK_PU 0x0002 /* BCLK_PU */
2044#define WM8993_BCLK_PU_MASK 0x0002 /* BCLK_PU */
2045#define WM8993_BCLK_PU_SHIFT 1 /* BCLK_PU */
2046#define WM8993_BCLK_PU_WIDTH 1 /* BCLK_PU */
2047#define WM8993_BCLK_PD 0x0001 /* BCLK_PD */
2048#define WM8993_BCLK_PD_MASK 0x0001 /* BCLK_PD */
2049#define WM8993_BCLK_PD_SHIFT 0 /* BCLK_PD */
2050#define WM8993_BCLK_PD_WIDTH 1 /* BCLK_PD */
2051
2052/*
2053 * R123 (0x7B) - DRC Control 1
2054 */
2055#define WM8993_DRC_ENA 0x8000 /* DRC_ENA */
2056#define WM8993_DRC_ENA_MASK 0x8000 /* DRC_ENA */
2057#define WM8993_DRC_ENA_SHIFT 15 /* DRC_ENA */
2058#define WM8993_DRC_ENA_WIDTH 1 /* DRC_ENA */
2059#define WM8993_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */
2060#define WM8993_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */
2061#define WM8993_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */
2062#define WM8993_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */
2063#define WM8993_DRC_SMOOTH_ENA 0x0800 /* DRC_SMOOTH_ENA */
2064#define WM8993_DRC_SMOOTH_ENA_MASK 0x0800 /* DRC_SMOOTH_ENA */
2065#define WM8993_DRC_SMOOTH_ENA_SHIFT 11 /* DRC_SMOOTH_ENA */
2066#define WM8993_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */
2067#define WM8993_DRC_QR_ENA 0x0400 /* DRC_QR_ENA */
2068#define WM8993_DRC_QR_ENA_MASK 0x0400 /* DRC_QR_ENA */
2069#define WM8993_DRC_QR_ENA_SHIFT 10 /* DRC_QR_ENA */
2070#define WM8993_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */
2071#define WM8993_DRC_ANTICLIP_ENA 0x0200 /* DRC_ANTICLIP_ENA */
2072#define WM8993_DRC_ANTICLIP_ENA_MASK 0x0200 /* DRC_ANTICLIP_ENA */
2073#define WM8993_DRC_ANTICLIP_ENA_SHIFT 9 /* DRC_ANTICLIP_ENA */
2074#define WM8993_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */
2075#define WM8993_DRC_HYST_ENA 0x0100 /* DRC_HYST_ENA */
2076#define WM8993_DRC_HYST_ENA_MASK 0x0100 /* DRC_HYST_ENA */
2077#define WM8993_DRC_HYST_ENA_SHIFT 8 /* DRC_HYST_ENA */
2078#define WM8993_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */
2079#define WM8993_DRC_THRESH_HYST_MASK 0x0030 /* DRC_THRESH_HYST - [5:4] */
2080#define WM8993_DRC_THRESH_HYST_SHIFT 4 /* DRC_THRESH_HYST - [5:4] */
2081#define WM8993_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [5:4] */
2082#define WM8993_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
2083#define WM8993_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
2084#define WM8993_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
2085#define WM8993_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
2086#define WM8993_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
2087#define WM8993_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
2088
2089/*
2090 * R124 (0x7C) - DRC Control 2
2091 */
2092#define WM8993_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */
2093#define WM8993_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */
2094#define WM8993_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */
2095#define WM8993_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */
2096#define WM8993_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */
2097#define WM8993_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */
2098#define WM8993_DRC_THRESH_COMP_MASK 0x00FC /* DRC_THRESH_COMP - [7:2] */
2099#define WM8993_DRC_THRESH_COMP_SHIFT 2 /* DRC_THRESH_COMP - [7:2] */
2100#define WM8993_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [7:2] */
2101
2102/*
2103 * R125 (0x7D) - DRC Control 3
2104 */
2105#define WM8993_DRC_AMP_COMP_MASK 0xF800 /* DRC_AMP_COMP - [15:11] */
2106#define WM8993_DRC_AMP_COMP_SHIFT 11 /* DRC_AMP_COMP - [15:11] */
2107#define WM8993_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [15:11] */
2108#define WM8993_DRC_R0_SLOPE_COMP_MASK 0x0700 /* DRC_R0_SLOPE_COMP - [10:8] */
2109#define WM8993_DRC_R0_SLOPE_COMP_SHIFT 8 /* DRC_R0_SLOPE_COMP - [10:8] */
2110#define WM8993_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [10:8] */
2111#define WM8993_DRC_FF_DELAY 0x0080 /* DRC_FF_DELAY */
2112#define WM8993_DRC_FF_DELAY_MASK 0x0080 /* DRC_FF_DELAY */
2113#define WM8993_DRC_FF_DELAY_SHIFT 7 /* DRC_FF_DELAY */
2114#define WM8993_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */
2115#define WM8993_DRC_THRESH_QR_MASK 0x000C /* DRC_THRESH_QR - [3:2] */
2116#define WM8993_DRC_THRESH_QR_SHIFT 2 /* DRC_THRESH_QR - [3:2] */
2117#define WM8993_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [3:2] */
2118#define WM8993_DRC_RATE_QR_MASK 0x0003 /* DRC_RATE_QR - [1:0] */
2119#define WM8993_DRC_RATE_QR_SHIFT 0 /* DRC_RATE_QR - [1:0] */
2120#define WM8993_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [1:0] */
2121
2122/*
2123 * R126 (0x7E) - DRC Control 4
2124 */
2125#define WM8993_DRC_R1_SLOPE_COMP_MASK 0xE000 /* DRC_R1_SLOPE_COMP - [15:13] */
2126#define WM8993_DRC_R1_SLOPE_COMP_SHIFT 13 /* DRC_R1_SLOPE_COMP - [15:13] */
2127#define WM8993_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [15:13] */
2128#define WM8993_DRC_STARTUP_GAIN_MASK 0x1F00 /* DRC_STARTUP_GAIN - [12:8] */
2129#define WM8993_DRC_STARTUP_GAIN_SHIFT 8 /* DRC_STARTUP_GAIN - [12:8] */
2130#define WM8993_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [12:8] */
2131
2132#endif
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
new file mode 100644
index 000000000000..c64e55aa63b6
--- /dev/null
+++ b/sound/soc/codecs/wm9081.c
@@ -0,0 +1,1511 @@
1/*
2 * wm9081.c -- WM9081 ALSA SoC Audio driver
3 *
4 * Author: Mark Brown
5 *
6 * Copyright 2009 Wolfson Microelectronics plc
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
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 <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include <sound/wm9081.h>
30#include "wm9081.h"
31
32static u16 wm9081_reg_defaults[] = {
33 0x0000, /* R0 - Software Reset */
34 0x0000, /* R1 */
35 0x00B9, /* R2 - Analogue Lineout */
36 0x00B9, /* R3 - Analogue Speaker PGA */
37 0x0001, /* R4 - VMID Control */
38 0x0068, /* R5 - Bias Control 1 */
39 0x0000, /* R6 */
40 0x0000, /* R7 - Analogue Mixer */
41 0x0000, /* R8 - Anti Pop Control */
42 0x01DB, /* R9 - Analogue Speaker 1 */
43 0x0018, /* R10 - Analogue Speaker 2 */
44 0x0180, /* R11 - Power Management */
45 0x0000, /* R12 - Clock Control 1 */
46 0x0038, /* R13 - Clock Control 2 */
47 0x4000, /* R14 - Clock Control 3 */
48 0x0000, /* R15 */
49 0x0000, /* R16 - FLL Control 1 */
50 0x0200, /* R17 - FLL Control 2 */
51 0x0000, /* R18 - FLL Control 3 */
52 0x0204, /* R19 - FLL Control 4 */
53 0x0000, /* R20 - FLL Control 5 */
54 0x0000, /* R21 */
55 0x0000, /* R22 - Audio Interface 1 */
56 0x0002, /* R23 - Audio Interface 2 */
57 0x0008, /* R24 - Audio Interface 3 */
58 0x0022, /* R25 - Audio Interface 4 */
59 0x0000, /* R26 - Interrupt Status */
60 0x0006, /* R27 - Interrupt Status Mask */
61 0x0000, /* R28 - Interrupt Polarity */
62 0x0000, /* R29 - Interrupt Control */
63 0x00C0, /* R30 - DAC Digital 1 */
64 0x0008, /* R31 - DAC Digital 2 */
65 0x09AF, /* R32 - DRC 1 */
66 0x4201, /* R33 - DRC 2 */
67 0x0000, /* R34 - DRC 3 */
68 0x0000, /* R35 - DRC 4 */
69 0x0000, /* R36 */
70 0x0000, /* R37 */
71 0x0000, /* R38 - Write Sequencer 1 */
72 0x0000, /* R39 - Write Sequencer 2 */
73 0x0002, /* R40 - MW Slave 1 */
74 0x0000, /* R41 */
75 0x0000, /* R42 - EQ 1 */
76 0x0000, /* R43 - EQ 2 */
77 0x0FCA, /* R44 - EQ 3 */
78 0x0400, /* R45 - EQ 4 */
79 0x00B8, /* R46 - EQ 5 */
80 0x1EB5, /* R47 - EQ 6 */
81 0xF145, /* R48 - EQ 7 */
82 0x0B75, /* R49 - EQ 8 */
83 0x01C5, /* R50 - EQ 9 */
84 0x169E, /* R51 - EQ 10 */
85 0xF829, /* R52 - EQ 11 */
86 0x07AD, /* R53 - EQ 12 */
87 0x1103, /* R54 - EQ 13 */
88 0x1C58, /* R55 - EQ 14 */
89 0xF373, /* R56 - EQ 15 */
90 0x0A54, /* R57 - EQ 16 */
91 0x0558, /* R58 - EQ 17 */
92 0x0564, /* R59 - EQ 18 */
93 0x0559, /* R60 - EQ 19 */
94 0x4000, /* R61 - EQ 20 */
95};
96
97static struct {
98 int ratio;
99 int clk_sys_rate;
100} clk_sys_rates[] = {
101 { 64, 0 },
102 { 128, 1 },
103 { 192, 2 },
104 { 256, 3 },
105 { 384, 4 },
106 { 512, 5 },
107 { 768, 6 },
108 { 1024, 7 },
109 { 1408, 8 },
110 { 1536, 9 },
111};
112
113static struct {
114 int rate;
115 int sample_rate;
116} sample_rates[] = {
117 { 8000, 0 },
118 { 11025, 1 },
119 { 12000, 2 },
120 { 16000, 3 },
121 { 22050, 4 },
122 { 24000, 5 },
123 { 32000, 6 },
124 { 44100, 7 },
125 { 48000, 8 },
126 { 88200, 9 },
127 { 96000, 10 },
128};
129
130static struct {
131 int div; /* *10 due to .5s */
132 int bclk_div;
133} bclk_divs[] = {
134 { 10, 0 },
135 { 15, 1 },
136 { 20, 2 },
137 { 30, 3 },
138 { 40, 4 },
139 { 50, 5 },
140 { 55, 6 },
141 { 60, 7 },
142 { 80, 8 },
143 { 100, 9 },
144 { 110, 10 },
145 { 120, 11 },
146 { 160, 12 },
147 { 200, 13 },
148 { 220, 14 },
149 { 240, 15 },
150 { 250, 16 },
151 { 300, 17 },
152 { 320, 18 },
153 { 440, 19 },
154 { 480, 20 },
155};
156
157struct wm9081_priv {
158 struct snd_soc_codec codec;
159 u16 reg_cache[WM9081_MAX_REGISTER + 1];
160 int sysclk_source;
161 int mclk_rate;
162 int sysclk_rate;
163 int fs;
164 int bclk;
165 int master;
166 int fll_fref;
167 int fll_fout;
168 int tdm_width;
169 struct wm9081_retune_mobile_config *retune;
170};
171
172static int wm9081_volatile_register(unsigned int reg)
173{
174 switch (reg) {
175 case WM9081_SOFTWARE_RESET:
176 return 1;
177 default:
178 return 0;
179 }
180}
181
182static int wm9081_reset(struct snd_soc_codec *codec)
183{
184 return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
185}
186
187static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
188static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
189static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
190static unsigned int drc_max_tlv[] = {
191 TLV_DB_RANGE_HEAD(4),
192 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
193 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
194 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
195 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
196};
197static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
198static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
199
200static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
201
202static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0);
203static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
204static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
205
206static const char *drc_high_text[] = {
207 "1",
208 "1/2",
209 "1/4",
210 "1/8",
211 "1/16",
212 "0",
213};
214
215static const struct soc_enum drc_high =
216 SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text);
217
218static const char *drc_low_text[] = {
219 "1",
220 "1/2",
221 "1/4",
222 "1/8",
223 "0",
224};
225
226static const struct soc_enum drc_low =
227 SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text);
228
229static const char *drc_atk_text[] = {
230 "181us",
231 "181us",
232 "363us",
233 "726us",
234 "1.45ms",
235 "2.9ms",
236 "5.8ms",
237 "11.6ms",
238 "23.2ms",
239 "46.4ms",
240 "92.8ms",
241 "185.6ms",
242};
243
244static const struct soc_enum drc_atk =
245 SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text);
246
247static const char *drc_dcy_text[] = {
248 "186ms",
249 "372ms",
250 "743ms",
251 "1.49s",
252 "2.97s",
253 "5.94s",
254 "11.89s",
255 "23.78s",
256 "47.56s",
257};
258
259static const struct soc_enum drc_dcy =
260 SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text);
261
262static const char *drc_qr_dcy_text[] = {
263 "0.725ms",
264 "1.45ms",
265 "5.8ms",
266};
267
268static const struct soc_enum drc_qr_dcy =
269 SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text);
270
271static const char *dac_deemph_text[] = {
272 "None",
273 "32kHz",
274 "44.1kHz",
275 "48kHz",
276};
277
278static const struct soc_enum dac_deemph =
279 SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text);
280
281static const char *speaker_mode_text[] = {
282 "Class D",
283 "Class AB",
284};
285
286static const struct soc_enum speaker_mode =
287 SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text);
288
289static int speaker_mode_get(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_value *ucontrol)
291{
292 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
293 unsigned int reg;
294
295 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
296 if (reg & WM9081_SPK_MODE)
297 ucontrol->value.integer.value[0] = 1;
298 else
299 ucontrol->value.integer.value[0] = 0;
300
301 return 0;
302}
303
304/*
305 * Stop any attempts to change speaker mode while the speaker is enabled.
306 *
307 * We also have some special anti-pop controls dependant on speaker
308 * mode which must be changed along with the mode.
309 */
310static int speaker_mode_put(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol)
312{
313 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
314 unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
315 unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
316
317 /* Are we changing anything? */
318 if (ucontrol->value.integer.value[0] ==
319 ((reg2 & WM9081_SPK_MODE) != 0))
320 return 0;
321
322 /* Don't try to change modes while enabled */
323 if (reg_pwr & WM9081_SPK_ENA)
324 return -EINVAL;
325
326 if (ucontrol->value.integer.value[0]) {
327 /* Class AB */
328 reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
329 reg2 |= WM9081_SPK_MODE;
330 } else {
331 /* Class D */
332 reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL;
333 reg2 &= ~WM9081_SPK_MODE;
334 }
335
336 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
337
338 return 0;
339}
340
341static const struct snd_kcontrol_new wm9081_snd_controls[] = {
342SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv),
343SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv),
344
345SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv),
346
347SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1),
348SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0),
349SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv),
350
351SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0),
352SOC_ENUM("DRC High Slope", drc_high),
353SOC_ENUM("DRC Low Slope", drc_low),
354SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv),
355SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv),
356SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv),
357SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv),
358SOC_ENUM("DRC Attack", drc_atk),
359SOC_ENUM("DRC Decay", drc_dcy),
360SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0),
361SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv),
362SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy),
363SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv),
364
365SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0),
366
367SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0),
368SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0),
369SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1),
370SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0),
371SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0,
372 out_tlv),
373SOC_ENUM("DAC Deemphasis", dac_deemph),
374SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put),
375};
376
377static const struct snd_kcontrol_new wm9081_eq_controls[] = {
378SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv),
379SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv),
380SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv),
381SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv),
382SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv),
383};
384
385static const struct snd_kcontrol_new mixer[] = {
386SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0),
387SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
388SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
389};
390
391static int speaker_event(struct snd_soc_dapm_widget *w,
392 struct snd_kcontrol *kcontrol, int event)
393{
394 struct snd_soc_codec *codec = w->codec;
395 unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
396
397 switch (event) {
398 case SND_SOC_DAPM_POST_PMU:
399 reg |= WM9081_SPK_ENA;
400 break;
401
402 case SND_SOC_DAPM_PRE_PMD:
403 reg &= ~WM9081_SPK_ENA;
404 break;
405 }
406
407 snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg);
408
409 return 0;
410}
411
412struct _fll_div {
413 u16 fll_fratio;
414 u16 fll_outdiv;
415 u16 fll_clk_ref_div;
416 u16 n;
417 u16 k;
418};
419
420/* The size in bits of the FLL divide multiplied by 10
421 * to allow rounding later */
422#define FIXED_FLL_SIZE ((1 << 16) * 10)
423
424static struct {
425 unsigned int min;
426 unsigned int max;
427 u16 fll_fratio;
428 int ratio;
429} fll_fratios[] = {
430 { 0, 64000, 4, 16 },
431 { 64000, 128000, 3, 8 },
432 { 128000, 256000, 2, 4 },
433 { 256000, 1000000, 1, 2 },
434 { 1000000, 13500000, 0, 1 },
435};
436
437static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
438 unsigned int Fout)
439{
440 u64 Kpart;
441 unsigned int K, Ndiv, Nmod, target;
442 unsigned int div;
443 int i;
444
445 /* Fref must be <=13.5MHz */
446 div = 1;
447 while ((Fref / div) > 13500000) {
448 div *= 2;
449
450 if (div > 8) {
451 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
452 Fref);
453 return -EINVAL;
454 }
455 }
456 fll_div->fll_clk_ref_div = div / 2;
457
458 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
459
460 /* Apply the division for our remaining calculations */
461 Fref /= div;
462
463 /* Fvco should be 90-100MHz; don't check the upper bound */
464 div = 0;
465 target = Fout * 2;
466 while (target < 90000000) {
467 div++;
468 target *= 2;
469 if (div > 7) {
470 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
471 Fout);
472 return -EINVAL;
473 }
474 }
475 fll_div->fll_outdiv = div;
476
477 pr_debug("Fvco=%dHz\n", target);
478
479 /* Find an appropraite FLL_FRATIO and factor it out of the target */
480 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
481 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
482 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
483 target /= fll_fratios[i].ratio;
484 break;
485 }
486 }
487 if (i == ARRAY_SIZE(fll_fratios)) {
488 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
489 return -EINVAL;
490 }
491
492 /* Now, calculate N.K */
493 Ndiv = target / Fref;
494
495 fll_div->n = Ndiv;
496 Nmod = target % Fref;
497 pr_debug("Nmod=%d\n", Nmod);
498
499 /* Calculate fractional part - scale up so we can round. */
500 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
501
502 do_div(Kpart, Fref);
503
504 K = Kpart & 0xFFFFFFFF;
505
506 if ((K % 10) >= 5)
507 K += 5;
508
509 /* Move down to proper range now rounding is done */
510 fll_div->k = K / 10;
511
512 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
513 fll_div->n, fll_div->k,
514 fll_div->fll_fratio, fll_div->fll_outdiv,
515 fll_div->fll_clk_ref_div);
516
517 return 0;
518}
519
520static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
521 unsigned int Fref, unsigned int Fout)
522{
523 struct wm9081_priv *wm9081 = codec->private_data;
524 u16 reg1, reg4, reg5;
525 struct _fll_div fll_div;
526 int ret;
527 int clk_sys_reg;
528
529 /* Any change? */
530 if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout)
531 return 0;
532
533 /* Disable the FLL */
534 if (Fout == 0) {
535 dev_dbg(codec->dev, "FLL disabled\n");
536 wm9081->fll_fref = 0;
537 wm9081->fll_fout = 0;
538
539 return 0;
540 }
541
542 ret = fll_factors(&fll_div, Fref, Fout);
543 if (ret != 0)
544 return ret;
545
546 reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5);
547 reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
548
549 switch (fll_id) {
550 case WM9081_SYSCLK_FLL_MCLK:
551 reg5 |= 0x1;
552 break;
553
554 default:
555 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
556 return -EINVAL;
557 }
558
559 /* Disable CLK_SYS while we reconfigure */
560 clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
561 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
562 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3,
563 clk_sys_reg & ~WM9081_CLK_SYS_ENA);
564
565 /* Any FLL configuration change requires that the FLL be
566 * disabled first. */
567 reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1);
568 reg1 &= ~WM9081_FLL_ENA;
569 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
570
571 /* Apply the configuration */
572 if (fll_div.k)
573 reg1 |= WM9081_FLL_FRAC_MASK;
574 else
575 reg1 &= ~WM9081_FLL_FRAC_MASK;
576 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
577
578 snd_soc_write(codec, WM9081_FLL_CONTROL_2,
579 (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
580 (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
581 snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
582
583 reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4);
584 reg4 &= ~WM9081_FLL_N_MASK;
585 reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
586 snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4);
587
588 reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
589 reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
590 snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5);
591
592 /* Enable the FLL */
593 snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
594
595 /* Then bring CLK_SYS up again if it was disabled */
596 if (clk_sys_reg & WM9081_CLK_SYS_ENA)
597 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
598
599 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
600
601 wm9081->fll_fref = Fref;
602 wm9081->fll_fout = Fout;
603
604 return 0;
605}
606
607static int configure_clock(struct snd_soc_codec *codec)
608{
609 struct wm9081_priv *wm9081 = codec->private_data;
610 int new_sysclk, i, target;
611 unsigned int reg;
612 int ret = 0;
613 int mclkdiv = 0;
614 int fll = 0;
615
616 switch (wm9081->sysclk_source) {
617 case WM9081_SYSCLK_MCLK:
618 if (wm9081->mclk_rate > 12225000) {
619 mclkdiv = 1;
620 wm9081->sysclk_rate = wm9081->mclk_rate / 2;
621 } else {
622 wm9081->sysclk_rate = wm9081->mclk_rate;
623 }
624 wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0);
625 break;
626
627 case WM9081_SYSCLK_FLL_MCLK:
628 /* If we have a sample rate calculate a CLK_SYS that
629 * gives us a suitable DAC configuration, plus BCLK.
630 * Ideally we would check to see if we can clock
631 * directly from MCLK and only use the FLL if this is
632 * not the case, though care must be taken with free
633 * running mode.
634 */
635 if (wm9081->master && wm9081->bclk) {
636 /* Make sure we can generate CLK_SYS and BCLK
637 * and that we've got 3MHz for optimal
638 * performance. */
639 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
640 target = wm9081->fs * clk_sys_rates[i].ratio;
641 new_sysclk = target;
642 if (target >= wm9081->bclk &&
643 target > 3000000)
644 break;
645 }
646
647 if (i == ARRAY_SIZE(clk_sys_rates))
648 return -EINVAL;
649
650 } else if (wm9081->fs) {
651 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
652 new_sysclk = clk_sys_rates[i].ratio
653 * wm9081->fs;
654 if (new_sysclk > 3000000)
655 break;
656 }
657
658 if (i == ARRAY_SIZE(clk_sys_rates))
659 return -EINVAL;
660
661 } else {
662 new_sysclk = 12288000;
663 }
664
665 ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK,
666 wm9081->mclk_rate, new_sysclk);
667 if (ret == 0) {
668 wm9081->sysclk_rate = new_sysclk;
669
670 /* Switch SYSCLK over to FLL */
671 fll = 1;
672 } else {
673 wm9081->sysclk_rate = wm9081->mclk_rate;
674 }
675 break;
676
677 default:
678 return -EINVAL;
679 }
680
681 reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1);
682 if (mclkdiv)
683 reg |= WM9081_MCLKDIV2;
684 else
685 reg &= ~WM9081_MCLKDIV2;
686 snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg);
687
688 reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
689 if (fll)
690 reg |= WM9081_CLK_SRC_SEL;
691 else
692 reg &= ~WM9081_CLK_SRC_SEL;
693 snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg);
694
695 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
696
697 return ret;
698}
699
700static int clk_sys_event(struct snd_soc_dapm_widget *w,
701 struct snd_kcontrol *kcontrol, int event)
702{
703 struct snd_soc_codec *codec = w->codec;
704 struct wm9081_priv *wm9081 = codec->private_data;
705
706 /* This should be done on init() for bypass paths */
707 switch (wm9081->sysclk_source) {
708 case WM9081_SYSCLK_MCLK:
709 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm9081->mclk_rate);
710 break;
711 case WM9081_SYSCLK_FLL_MCLK:
712 dev_dbg(codec->dev, "Using %dHz MCLK with FLL\n",
713 wm9081->mclk_rate);
714 break;
715 default:
716 dev_err(codec->dev, "System clock not configured\n");
717 return -EINVAL;
718 }
719
720 switch (event) {
721 case SND_SOC_DAPM_PRE_PMU:
722 configure_clock(codec);
723 break;
724
725 case SND_SOC_DAPM_POST_PMD:
726 /* Disable the FLL if it's running */
727 wm9081_set_fll(codec, 0, 0, 0);
728 break;
729 }
730
731 return 0;
732}
733
734static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
735SND_SOC_DAPM_INPUT("IN1"),
736SND_SOC_DAPM_INPUT("IN2"),
737
738SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0),
739
740SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
741 mixer, ARRAY_SIZE(mixer)),
742
743SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
744
745SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0,
746 speaker_event,
747 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
748
749SND_SOC_DAPM_OUTPUT("LINEOUT"),
750SND_SOC_DAPM_OUTPUT("SPKN"),
751SND_SOC_DAPM_OUTPUT("SPKP"),
752
753SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
754 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
755SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
756SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
757};
758
759
760static const struct snd_soc_dapm_route audio_paths[] = {
761 { "DAC", NULL, "CLK_SYS" },
762 { "DAC", NULL, "CLK_DSP" },
763
764 { "Mixer", "IN1 Switch", "IN1" },
765 { "Mixer", "IN2 Switch", "IN2" },
766 { "Mixer", "Playback Switch", "DAC" },
767
768 { "LINEOUT PGA", NULL, "Mixer" },
769 { "LINEOUT PGA", NULL, "TOCLK" },
770 { "LINEOUT PGA", NULL, "CLK_SYS" },
771
772 { "LINEOUT", NULL, "LINEOUT PGA" },
773
774 { "Speaker PGA", NULL, "Mixer" },
775 { "Speaker PGA", NULL, "TOCLK" },
776 { "Speaker PGA", NULL, "CLK_SYS" },
777
778 { "SPKN", NULL, "Speaker PGA" },
779 { "SPKP", NULL, "Speaker PGA" },
780};
781
782static int wm9081_set_bias_level(struct snd_soc_codec *codec,
783 enum snd_soc_bias_level level)
784{
785 u16 reg;
786
787 switch (level) {
788 case SND_SOC_BIAS_ON:
789 break;
790
791 case SND_SOC_BIAS_PREPARE:
792 /* VMID=2*40k */
793 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
794 reg &= ~WM9081_VMID_SEL_MASK;
795 reg |= 0x2;
796 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
797
798 /* Normal bias current */
799 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
800 reg &= ~WM9081_STBY_BIAS_ENA;
801 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
802 break;
803
804 case SND_SOC_BIAS_STANDBY:
805 /* Initial cold start */
806 if (codec->bias_level == SND_SOC_BIAS_OFF) {
807 /* Disable LINEOUT discharge */
808 reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
809 reg &= ~WM9081_LINEOUT_DISCH;
810 snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
811
812 /* Select startup bias source */
813 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
814 reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
815 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
816
817 /* VMID 2*4k; Soft VMID ramp enable */
818 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
819 reg |= WM9081_VMID_RAMP | 0x6;
820 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
821
822 mdelay(100);
823
824 /* Normal bias enable & soft start off */
825 reg |= WM9081_BIAS_ENA;
826 reg &= ~WM9081_VMID_RAMP;
827 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
828
829 /* Standard bias source */
830 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
831 reg &= ~WM9081_BIAS_SRC;
832 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
833 }
834
835 /* VMID 2*240k */
836 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
837 reg &= ~WM9081_VMID_SEL_MASK;
838 reg |= 0x40;
839 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
840
841 /* Standby bias current on */
842 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
843 reg |= WM9081_STBY_BIAS_ENA;
844 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
845 break;
846
847 case SND_SOC_BIAS_OFF:
848 /* Startup bias source */
849 reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
850 reg |= WM9081_BIAS_SRC;
851 snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
852
853 /* Disable VMID and biases with soft ramping */
854 reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
855 reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
856 reg |= WM9081_VMID_RAMP;
857 snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
858
859 /* Actively discharge LINEOUT */
860 reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
861 reg |= WM9081_LINEOUT_DISCH;
862 snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
863 break;
864 }
865
866 codec->bias_level = level;
867
868 return 0;
869}
870
871static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
872 unsigned int fmt)
873{
874 struct snd_soc_codec *codec = dai->codec;
875 struct wm9081_priv *wm9081 = codec->private_data;
876 unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
877
878 aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
879 WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
880
881 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
882 case SND_SOC_DAIFMT_CBS_CFS:
883 wm9081->master = 0;
884 break;
885 case SND_SOC_DAIFMT_CBS_CFM:
886 aif2 |= WM9081_LRCLK_DIR;
887 wm9081->master = 1;
888 break;
889 case SND_SOC_DAIFMT_CBM_CFS:
890 aif2 |= WM9081_BCLK_DIR;
891 wm9081->master = 1;
892 break;
893 case SND_SOC_DAIFMT_CBM_CFM:
894 aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
895 wm9081->master = 1;
896 break;
897 default:
898 return -EINVAL;
899 }
900
901 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
902 case SND_SOC_DAIFMT_DSP_B:
903 aif2 |= WM9081_AIF_LRCLK_INV;
904 case SND_SOC_DAIFMT_DSP_A:
905 aif2 |= 0x3;
906 break;
907 case SND_SOC_DAIFMT_I2S:
908 aif2 |= 0x2;
909 break;
910 case SND_SOC_DAIFMT_RIGHT_J:
911 break;
912 case SND_SOC_DAIFMT_LEFT_J:
913 aif2 |= 0x1;
914 break;
915 default:
916 return -EINVAL;
917 }
918
919 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
920 case SND_SOC_DAIFMT_DSP_A:
921 case SND_SOC_DAIFMT_DSP_B:
922 /* frame inversion not valid for DSP modes */
923 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
924 case SND_SOC_DAIFMT_NB_NF:
925 break;
926 case SND_SOC_DAIFMT_IB_NF:
927 aif2 |= WM9081_AIF_BCLK_INV;
928 break;
929 default:
930 return -EINVAL;
931 }
932 break;
933
934 case SND_SOC_DAIFMT_I2S:
935 case SND_SOC_DAIFMT_RIGHT_J:
936 case SND_SOC_DAIFMT_LEFT_J:
937 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
938 case SND_SOC_DAIFMT_NB_NF:
939 break;
940 case SND_SOC_DAIFMT_IB_IF:
941 aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
942 break;
943 case SND_SOC_DAIFMT_IB_NF:
944 aif2 |= WM9081_AIF_BCLK_INV;
945 break;
946 case SND_SOC_DAIFMT_NB_IF:
947 aif2 |= WM9081_AIF_LRCLK_INV;
948 break;
949 default:
950 return -EINVAL;
951 }
952 break;
953 default:
954 return -EINVAL;
955 }
956
957 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
958
959 return 0;
960}
961
962static int wm9081_hw_params(struct snd_pcm_substream *substream,
963 struct snd_pcm_hw_params *params,
964 struct snd_soc_dai *dai)
965{
966 struct snd_soc_codec *codec = dai->codec;
967 struct wm9081_priv *wm9081 = codec->private_data;
968 int ret, i, best, best_val, cur_val;
969 unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
970
971 clk_ctrl2 = snd_soc_read(codec, WM9081_CLOCK_CONTROL_2);
972 clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
973
974 aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
975
976 aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
977 aif2 &= ~WM9081_AIF_WL_MASK;
978
979 aif3 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_3);
980 aif3 &= ~WM9081_BCLK_DIV_MASK;
981
982 aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4);
983 aif4 &= ~WM9081_LRCLK_RATE_MASK;
984
985 wm9081->fs = params_rate(params);
986
987 if (wm9081->tdm_width) {
988 /* If TDM is set up then that fixes our BCLK. */
989 int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
990 WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
991
992 wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots;
993 } else {
994 /* Otherwise work out a BCLK from the sample size */
995 wm9081->bclk = 2 * wm9081->fs;
996
997 switch (params_format(params)) {
998 case SNDRV_PCM_FORMAT_S16_LE:
999 wm9081->bclk *= 16;
1000 break;
1001 case SNDRV_PCM_FORMAT_S20_3LE:
1002 wm9081->bclk *= 20;
1003 aif2 |= 0x4;
1004 break;
1005 case SNDRV_PCM_FORMAT_S24_LE:
1006 wm9081->bclk *= 24;
1007 aif2 |= 0x8;
1008 break;
1009 case SNDRV_PCM_FORMAT_S32_LE:
1010 wm9081->bclk *= 32;
1011 aif2 |= 0xc;
1012 break;
1013 default:
1014 return -EINVAL;
1015 }
1016 }
1017
1018 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk);
1019
1020 ret = configure_clock(codec);
1021 if (ret != 0)
1022 return ret;
1023
1024 /* Select nearest CLK_SYS_RATE */
1025 best = 0;
1026 best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio)
1027 - wm9081->fs);
1028 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1029 cur_val = abs((wm9081->sysclk_rate /
1030 clk_sys_rates[i].ratio) - wm9081->fs);;
1031 if (cur_val < best_val) {
1032 best = i;
1033 best_val = cur_val;
1034 }
1035 }
1036 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1037 clk_sys_rates[best].ratio);
1038 clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate
1039 << WM9081_CLK_SYS_RATE_SHIFT);
1040
1041 /* SAMPLE_RATE */
1042 best = 0;
1043 best_val = abs(wm9081->fs - sample_rates[0].rate);
1044 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1045 /* Closest match */
1046 cur_val = abs(wm9081->fs - sample_rates[i].rate);
1047 if (cur_val < best_val) {
1048 best = i;
1049 best_val = cur_val;
1050 }
1051 }
1052 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1053 sample_rates[best].rate);
1054 clk_ctrl2 |= (sample_rates[best].sample_rate
1055 << WM9081_SAMPLE_RATE_SHIFT);
1056
1057 /* BCLK_DIV */
1058 best = 0;
1059 best_val = INT_MAX;
1060 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1061 cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div)
1062 - wm9081->bclk;
1063 if (cur_val < 0) /* Table is sorted */
1064 break;
1065 if (cur_val < best_val) {
1066 best = i;
1067 best_val = cur_val;
1068 }
1069 }
1070 wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div;
1071 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1072 bclk_divs[best].div, wm9081->bclk);
1073 aif3 |= bclk_divs[best].bclk_div;
1074
1075 /* LRCLK is a simple fraction of BCLK */
1076 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs);
1077 aif4 |= wm9081->bclk / wm9081->fs;
1078
1079 /* Apply a ReTune Mobile configuration if it's in use */
1080 if (wm9081->retune) {
1081 struct wm9081_retune_mobile_config *retune = wm9081->retune;
1082 struct wm9081_retune_mobile_setting *s;
1083 int eq1;
1084
1085 best = 0;
1086 best_val = abs(retune->configs[0].rate - wm9081->fs);
1087 for (i = 0; i < retune->num_configs; i++) {
1088 cur_val = abs(retune->configs[i].rate - wm9081->fs);
1089 if (cur_val < best_val) {
1090 best_val = cur_val;
1091 best = i;
1092 }
1093 }
1094 s = &retune->configs[best];
1095
1096 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1097 s->name, s->rate);
1098
1099 /* If the EQ is enabled then disable it while we write out */
1100 eq1 = snd_soc_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
1101 if (eq1 & WM9081_EQ_ENA)
1102 snd_soc_write(codec, WM9081_EQ_1, 0);
1103
1104 /* Write out the other values */
1105 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1106 snd_soc_write(codec, WM9081_EQ_1 + i, s->config[i]);
1107
1108 eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
1109 snd_soc_write(codec, WM9081_EQ_1, eq1);
1110 }
1111
1112 snd_soc_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
1113 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
1114 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
1115 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
1116
1117 return 0;
1118}
1119
1120static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1121{
1122 struct snd_soc_codec *codec = codec_dai->codec;
1123 unsigned int reg;
1124
1125 reg = snd_soc_read(codec, WM9081_DAC_DIGITAL_2);
1126
1127 if (mute)
1128 reg |= WM9081_DAC_MUTE;
1129 else
1130 reg &= ~WM9081_DAC_MUTE;
1131
1132 snd_soc_write(codec, WM9081_DAC_DIGITAL_2, reg);
1133
1134 return 0;
1135}
1136
1137static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
1138 int clk_id, unsigned int freq, int dir)
1139{
1140 struct snd_soc_codec *codec = codec_dai->codec;
1141 struct wm9081_priv *wm9081 = codec->private_data;
1142
1143 switch (clk_id) {
1144 case WM9081_SYSCLK_MCLK:
1145 case WM9081_SYSCLK_FLL_MCLK:
1146 wm9081->sysclk_source = clk_id;
1147 wm9081->mclk_rate = freq;
1148 break;
1149
1150 default:
1151 return -EINVAL;
1152 }
1153
1154 return 0;
1155}
1156
1157static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
1158 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
1159{
1160 struct snd_soc_codec *codec = dai->codec;
1161 struct wm9081_priv *wm9081 = codec->private_data;
1162 unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
1163
1164 aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
1165
1166 if (slots < 0 || slots > 4)
1167 return -EINVAL;
1168
1169 wm9081->tdm_width = slot_width;
1170
1171 if (slots == 0)
1172 slots = 1;
1173
1174 aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
1175
1176 switch (rx_mask) {
1177 case 1:
1178 break;
1179 case 2:
1180 aif1 |= 0x10;
1181 break;
1182 case 4:
1183 aif1 |= 0x20;
1184 break;
1185 case 8:
1186 aif1 |= 0x30;
1187 break;
1188 default:
1189 return -EINVAL;
1190 }
1191
1192 snd_soc_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
1193
1194 return 0;
1195}
1196
1197#define WM9081_RATES SNDRV_PCM_RATE_8000_96000
1198
1199#define WM9081_FORMATS \
1200 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1201 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1202
1203static struct snd_soc_dai_ops wm9081_dai_ops = {
1204 .hw_params = wm9081_hw_params,
1205 .set_sysclk = wm9081_set_sysclk,
1206 .set_fmt = wm9081_set_dai_fmt,
1207 .digital_mute = wm9081_digital_mute,
1208 .set_tdm_slot = wm9081_set_tdm_slot,
1209};
1210
1211/* We report two channels because the CODEC processes a stereo signal, even
1212 * though it is only capable of handling a mono output.
1213 */
1214struct snd_soc_dai wm9081_dai = {
1215 .name = "WM9081",
1216 .playback = {
1217 .stream_name = "HiFi Playback",
1218 .channels_min = 1,
1219 .channels_max = 2,
1220 .rates = WM9081_RATES,
1221 .formats = WM9081_FORMATS,
1222 },
1223 .ops = &wm9081_dai_ops,
1224};
1225EXPORT_SYMBOL_GPL(wm9081_dai);
1226
1227
1228static struct snd_soc_codec *wm9081_codec;
1229
1230static int wm9081_probe(struct platform_device *pdev)
1231{
1232 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1233 struct snd_soc_codec *codec;
1234 struct wm9081_priv *wm9081;
1235 int ret = 0;
1236
1237 if (wm9081_codec == NULL) {
1238 dev_err(&pdev->dev, "Codec device not registered\n");
1239 return -ENODEV;
1240 }
1241
1242 socdev->card->codec = wm9081_codec;
1243 codec = wm9081_codec;
1244 wm9081 = codec->private_data;
1245
1246 /* register pcms */
1247 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1248 if (ret < 0) {
1249 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
1250 goto pcm_err;
1251 }
1252
1253 snd_soc_add_controls(codec, wm9081_snd_controls,
1254 ARRAY_SIZE(wm9081_snd_controls));
1255 if (!wm9081->retune) {
1256 dev_dbg(codec->dev,
1257 "No ReTune Mobile data, using normal EQ\n");
1258 snd_soc_add_controls(codec, wm9081_eq_controls,
1259 ARRAY_SIZE(wm9081_eq_controls));
1260 }
1261
1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
1263 ARRAY_SIZE(wm9081_dapm_widgets));
1264 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
1273 return ret;
1274
1275card_err:
1276 snd_soc_free_pcms(socdev);
1277 snd_soc_dapm_free(socdev);
1278pcm_err:
1279 return ret;
1280}
1281
1282static int wm9081_remove(struct platform_device *pdev)
1283{
1284 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1285
1286 snd_soc_free_pcms(socdev);
1287 snd_soc_dapm_free(socdev);
1288
1289 return 0;
1290}
1291
1292#ifdef CONFIG_PM
1293static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
1294{
1295 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1296 struct snd_soc_codec *codec = socdev->card->codec;
1297
1298 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
1299
1300 return 0;
1301}
1302
1303static int wm9081_resume(struct platform_device *pdev)
1304{
1305 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1306 struct snd_soc_codec *codec = socdev->card->codec;
1307 u16 *reg_cache = codec->reg_cache;
1308 int i;
1309
1310 for (i = 0; i < codec->reg_cache_size; i++) {
1311 if (i == WM9081_SOFTWARE_RESET)
1312 continue;
1313
1314 snd_soc_write(codec, i, reg_cache[i]);
1315 }
1316
1317 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1318
1319 return 0;
1320}
1321#else
1322#define wm9081_suspend NULL
1323#define wm9081_resume NULL
1324#endif
1325
1326struct snd_soc_codec_device soc_codec_dev_wm9081 = {
1327 .probe = wm9081_probe,
1328 .remove = wm9081_remove,
1329 .suspend = wm9081_suspend,
1330 .resume = wm9081_resume,
1331};
1332EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
1333
1334static int wm9081_register(struct wm9081_priv *wm9081,
1335 enum snd_soc_control_type control)
1336{
1337 struct snd_soc_codec *codec = &wm9081->codec;
1338 int ret;
1339 u16 reg;
1340
1341 if (wm9081_codec) {
1342 dev_err(codec->dev, "Another WM9081 is registered\n");
1343 ret = -EINVAL;
1344 goto err;
1345 }
1346
1347 mutex_init(&codec->mutex);
1348 INIT_LIST_HEAD(&codec->dapm_widgets);
1349 INIT_LIST_HEAD(&codec->dapm_paths);
1350
1351 codec->private_data = wm9081;
1352 codec->name = "WM9081";
1353 codec->owner = THIS_MODULE;
1354 codec->dai = &wm9081_dai;
1355 codec->num_dai = 1;
1356 codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
1357 codec->reg_cache = &wm9081->reg_cache;
1358 codec->bias_level = SND_SOC_BIAS_OFF;
1359 codec->set_bias_level = wm9081_set_bias_level;
1360 codec->volatile_register = wm9081_volatile_register;
1361
1362 memcpy(codec->reg_cache, wm9081_reg_defaults,
1363 sizeof(wm9081_reg_defaults));
1364
1365 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
1366 if (ret != 0) {
1367 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1368 return ret;
1369 }
1370
1371 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
1372 if (reg != 0x9081) {
1373 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1374 ret = -EINVAL;
1375 goto err;
1376 }
1377
1378 ret = wm9081_reset(codec);
1379 if (ret < 0) {
1380 dev_err(codec->dev, "Failed to issue reset\n");
1381 return ret;
1382 }
1383
1384 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1385
1386 /* Enable zero cross by default */
1387 reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
1388 snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
1389 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
1390 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
1391 reg | WM9081_SPKPGAZC);
1392
1393 wm9081_dai.dev = codec->dev;
1394
1395 wm9081_codec = codec;
1396
1397 ret = snd_soc_register_codec(codec);
1398 if (ret != 0) {
1399 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1400 return ret;
1401 }
1402
1403 ret = snd_soc_register_dai(&wm9081_dai);
1404 if (ret != 0) {
1405 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1406 snd_soc_unregister_codec(codec);
1407 return ret;
1408 }
1409
1410 return 0;
1411
1412err:
1413 kfree(wm9081);
1414 return ret;
1415}
1416
1417static void wm9081_unregister(struct wm9081_priv *wm9081)
1418{
1419 wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
1420 snd_soc_unregister_dai(&wm9081_dai);
1421 snd_soc_unregister_codec(&wm9081->codec);
1422 kfree(wm9081);
1423 wm9081_codec = NULL;
1424}
1425
1426static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1427 const struct i2c_device_id *id)
1428{
1429 struct wm9081_priv *wm9081;
1430 struct snd_soc_codec *codec;
1431
1432 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
1433 if (wm9081 == NULL)
1434 return -ENOMEM;
1435
1436 codec = &wm9081->codec;
1437 codec->hw_write = (hw_write_t)i2c_master_send;
1438 wm9081->retune = i2c->dev.platform_data;
1439
1440 i2c_set_clientdata(i2c, wm9081);
1441 codec->control_data = i2c;
1442
1443 codec->dev = &i2c->dev;
1444
1445 return wm9081_register(wm9081, SND_SOC_I2C);
1446}
1447
1448static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1449{
1450 struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
1451 wm9081_unregister(wm9081);
1452 return 0;
1453}
1454
1455#ifdef CONFIG_PM
1456static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1457{
1458 return snd_soc_suspend_device(&client->dev);
1459}
1460
1461static 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
1470static const struct i2c_device_id wm9081_i2c_id[] = {
1471 { "wm9081", 0 },
1472 { }
1473};
1474MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
1475
1476static struct i2c_driver wm9081_i2c_driver = {
1477 .driver = {
1478 .name = "wm9081",
1479 .owner = THIS_MODULE,
1480 },
1481 .probe = wm9081_i2c_probe,
1482 .remove = __devexit_p(wm9081_i2c_remove),
1483 .suspend = wm9081_i2c_suspend,
1484 .resume = wm9081_i2c_resume,
1485 .id_table = wm9081_i2c_id,
1486};
1487
1488static int __init wm9081_modinit(void)
1489{
1490 int ret;
1491
1492 ret = i2c_add_driver(&wm9081_i2c_driver);
1493 if (ret != 0) {
1494 printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
1495 ret);
1496 }
1497
1498 return ret;
1499}
1500module_init(wm9081_modinit);
1501
1502static void __exit wm9081_exit(void)
1503{
1504 i2c_del_driver(&wm9081_i2c_driver);
1505}
1506module_exit(wm9081_exit);
1507
1508
1509MODULE_DESCRIPTION("ASoC WM9081 driver");
1510MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1511MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h
new file mode 100644
index 000000000000..42d3bc757021
--- /dev/null
+++ b/sound/soc/codecs/wm9081.h
@@ -0,0 +1,787 @@
1#ifndef WM9081_H
2#define WM9081_H
3
4/*
5 * wm9081.c -- WM9081 ALSA SoC Audio driver
6 *
7 * Author: Mark Brown
8 *
9 * Copyright 2009 Wolfson Microelectronics plc
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <sound/soc.h>
17
18extern struct snd_soc_dai wm9081_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm9081;
20
21/*
22 * SYSCLK sources
23 */
24#define WM9081_SYSCLK_MCLK 1 /* Use MCLK without FLL */
25#define WM9081_SYSCLK_FLL_MCLK 2 /* Use MCLK, enabling FLL if required */
26
27/*
28 * Register values.
29 */
30#define WM9081_SOFTWARE_RESET 0x00
31#define WM9081_ANALOGUE_LINEOUT 0x02
32#define WM9081_ANALOGUE_SPEAKER_PGA 0x03
33#define WM9081_VMID_CONTROL 0x04
34#define WM9081_BIAS_CONTROL_1 0x05
35#define WM9081_ANALOGUE_MIXER 0x07
36#define WM9081_ANTI_POP_CONTROL 0x08
37#define WM9081_ANALOGUE_SPEAKER_1 0x09
38#define WM9081_ANALOGUE_SPEAKER_2 0x0A
39#define WM9081_POWER_MANAGEMENT 0x0B
40#define WM9081_CLOCK_CONTROL_1 0x0C
41#define WM9081_CLOCK_CONTROL_2 0x0D
42#define WM9081_CLOCK_CONTROL_3 0x0E
43#define WM9081_FLL_CONTROL_1 0x10
44#define WM9081_FLL_CONTROL_2 0x11
45#define WM9081_FLL_CONTROL_3 0x12
46#define WM9081_FLL_CONTROL_4 0x13
47#define WM9081_FLL_CONTROL_5 0x14
48#define WM9081_AUDIO_INTERFACE_1 0x16
49#define WM9081_AUDIO_INTERFACE_2 0x17
50#define WM9081_AUDIO_INTERFACE_3 0x18
51#define WM9081_AUDIO_INTERFACE_4 0x19
52#define WM9081_INTERRUPT_STATUS 0x1A
53#define WM9081_INTERRUPT_STATUS_MASK 0x1B
54#define WM9081_INTERRUPT_POLARITY 0x1C
55#define WM9081_INTERRUPT_CONTROL 0x1D
56#define WM9081_DAC_DIGITAL_1 0x1E
57#define WM9081_DAC_DIGITAL_2 0x1F
58#define WM9081_DRC_1 0x20
59#define WM9081_DRC_2 0x21
60#define WM9081_DRC_3 0x22
61#define WM9081_DRC_4 0x23
62#define WM9081_WRITE_SEQUENCER_1 0x26
63#define WM9081_WRITE_SEQUENCER_2 0x27
64#define WM9081_MW_SLAVE_1 0x28
65#define WM9081_EQ_1 0x2A
66#define WM9081_EQ_2 0x2B
67#define WM9081_EQ_3 0x2C
68#define WM9081_EQ_4 0x2D
69#define WM9081_EQ_5 0x2E
70#define WM9081_EQ_6 0x2F
71#define WM9081_EQ_7 0x30
72#define WM9081_EQ_8 0x31
73#define WM9081_EQ_9 0x32
74#define WM9081_EQ_10 0x33
75#define WM9081_EQ_11 0x34
76#define WM9081_EQ_12 0x35
77#define WM9081_EQ_13 0x36
78#define WM9081_EQ_14 0x37
79#define WM9081_EQ_15 0x38
80#define WM9081_EQ_16 0x39
81#define WM9081_EQ_17 0x3A
82#define WM9081_EQ_18 0x3B
83#define WM9081_EQ_19 0x3C
84#define WM9081_EQ_20 0x3D
85
86#define WM9081_REGISTER_COUNT 55
87#define WM9081_MAX_REGISTER 0x3D
88
89/*
90 * Field Definitions.
91 */
92
93/*
94 * R0 (0x00) - Software Reset
95 */
96#define WM9081_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
97#define WM9081_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
98#define WM9081_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
99
100/*
101 * R2 (0x02) - Analogue Lineout
102 */
103#define WM9081_LINEOUT_MUTE 0x0080 /* LINEOUT_MUTE */
104#define WM9081_LINEOUT_MUTE_MASK 0x0080 /* LINEOUT_MUTE */
105#define WM9081_LINEOUT_MUTE_SHIFT 7 /* LINEOUT_MUTE */
106#define WM9081_LINEOUT_MUTE_WIDTH 1 /* LINEOUT_MUTE */
107#define WM9081_LINEOUTZC 0x0040 /* LINEOUTZC */
108#define WM9081_LINEOUTZC_MASK 0x0040 /* LINEOUTZC */
109#define WM9081_LINEOUTZC_SHIFT 6 /* LINEOUTZC */
110#define WM9081_LINEOUTZC_WIDTH 1 /* LINEOUTZC */
111#define WM9081_LINEOUT_VOL_MASK 0x003F /* LINEOUT_VOL - [5:0] */
112#define WM9081_LINEOUT_VOL_SHIFT 0 /* LINEOUT_VOL - [5:0] */
113#define WM9081_LINEOUT_VOL_WIDTH 6 /* LINEOUT_VOL - [5:0] */
114
115/*
116 * R3 (0x03) - Analogue Speaker PGA
117 */
118#define WM9081_SPKPGA_MUTE 0x0080 /* SPKPGA_MUTE */
119#define WM9081_SPKPGA_MUTE_MASK 0x0080 /* SPKPGA_MUTE */
120#define WM9081_SPKPGA_MUTE_SHIFT 7 /* SPKPGA_MUTE */
121#define WM9081_SPKPGA_MUTE_WIDTH 1 /* SPKPGA_MUTE */
122#define WM9081_SPKPGAZC 0x0040 /* SPKPGAZC */
123#define WM9081_SPKPGAZC_MASK 0x0040 /* SPKPGAZC */
124#define WM9081_SPKPGAZC_SHIFT 6 /* SPKPGAZC */
125#define WM9081_SPKPGAZC_WIDTH 1 /* SPKPGAZC */
126#define WM9081_SPKPGA_VOL_MASK 0x003F /* SPKPGA_VOL - [5:0] */
127#define WM9081_SPKPGA_VOL_SHIFT 0 /* SPKPGA_VOL - [5:0] */
128#define WM9081_SPKPGA_VOL_WIDTH 6 /* SPKPGA_VOL - [5:0] */
129
130/*
131 * R4 (0x04) - VMID Control
132 */
133#define WM9081_VMID_BUF_ENA 0x0020 /* VMID_BUF_ENA */
134#define WM9081_VMID_BUF_ENA_MASK 0x0020 /* VMID_BUF_ENA */
135#define WM9081_VMID_BUF_ENA_SHIFT 5 /* VMID_BUF_ENA */
136#define WM9081_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
137#define WM9081_VMID_RAMP 0x0008 /* VMID_RAMP */
138#define WM9081_VMID_RAMP_MASK 0x0008 /* VMID_RAMP */
139#define WM9081_VMID_RAMP_SHIFT 3 /* VMID_RAMP */
140#define WM9081_VMID_RAMP_WIDTH 1 /* VMID_RAMP */
141#define WM9081_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
142#define WM9081_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
143#define WM9081_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
144#define WM9081_VMID_FAST_ST 0x0001 /* VMID_FAST_ST */
145#define WM9081_VMID_FAST_ST_MASK 0x0001 /* VMID_FAST_ST */
146#define WM9081_VMID_FAST_ST_SHIFT 0 /* VMID_FAST_ST */
147#define WM9081_VMID_FAST_ST_WIDTH 1 /* VMID_FAST_ST */
148
149/*
150 * R5 (0x05) - Bias Control 1
151 */
152#define WM9081_BIAS_SRC 0x0040 /* BIAS_SRC */
153#define WM9081_BIAS_SRC_MASK 0x0040 /* BIAS_SRC */
154#define WM9081_BIAS_SRC_SHIFT 6 /* BIAS_SRC */
155#define WM9081_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
156#define WM9081_STBY_BIAS_LVL 0x0020 /* STBY_BIAS_LVL */
157#define WM9081_STBY_BIAS_LVL_MASK 0x0020 /* STBY_BIAS_LVL */
158#define WM9081_STBY_BIAS_LVL_SHIFT 5 /* STBY_BIAS_LVL */
159#define WM9081_STBY_BIAS_LVL_WIDTH 1 /* STBY_BIAS_LVL */
160#define WM9081_STBY_BIAS_ENA 0x0010 /* STBY_BIAS_ENA */
161#define WM9081_STBY_BIAS_ENA_MASK 0x0010 /* STBY_BIAS_ENA */
162#define WM9081_STBY_BIAS_ENA_SHIFT 4 /* STBY_BIAS_ENA */
163#define WM9081_STBY_BIAS_ENA_WIDTH 1 /* STBY_BIAS_ENA */
164#define WM9081_BIAS_LVL_MASK 0x000C /* BIAS_LVL - [3:2] */
165#define WM9081_BIAS_LVL_SHIFT 2 /* BIAS_LVL - [3:2] */
166#define WM9081_BIAS_LVL_WIDTH 2 /* BIAS_LVL - [3:2] */
167#define WM9081_BIAS_ENA 0x0002 /* BIAS_ENA */
168#define WM9081_BIAS_ENA_MASK 0x0002 /* BIAS_ENA */
169#define WM9081_BIAS_ENA_SHIFT 1 /* BIAS_ENA */
170#define WM9081_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
171#define WM9081_STARTUP_BIAS_ENA 0x0001 /* STARTUP_BIAS_ENA */
172#define WM9081_STARTUP_BIAS_ENA_MASK 0x0001 /* STARTUP_BIAS_ENA */
173#define WM9081_STARTUP_BIAS_ENA_SHIFT 0 /* STARTUP_BIAS_ENA */
174#define WM9081_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
175
176/*
177 * R7 (0x07) - Analogue Mixer
178 */
179#define WM9081_DAC_SEL 0x0010 /* DAC_SEL */
180#define WM9081_DAC_SEL_MASK 0x0010 /* DAC_SEL */
181#define WM9081_DAC_SEL_SHIFT 4 /* DAC_SEL */
182#define WM9081_DAC_SEL_WIDTH 1 /* DAC_SEL */
183#define WM9081_IN2_VOL 0x0008 /* IN2_VOL */
184#define WM9081_IN2_VOL_MASK 0x0008 /* IN2_VOL */
185#define WM9081_IN2_VOL_SHIFT 3 /* IN2_VOL */
186#define WM9081_IN2_VOL_WIDTH 1 /* IN2_VOL */
187#define WM9081_IN2_ENA 0x0004 /* IN2_ENA */
188#define WM9081_IN2_ENA_MASK 0x0004 /* IN2_ENA */
189#define WM9081_IN2_ENA_SHIFT 2 /* IN2_ENA */
190#define WM9081_IN2_ENA_WIDTH 1 /* IN2_ENA */
191#define WM9081_IN1_VOL 0x0002 /* IN1_VOL */
192#define WM9081_IN1_VOL_MASK 0x0002 /* IN1_VOL */
193#define WM9081_IN1_VOL_SHIFT 1 /* IN1_VOL */
194#define WM9081_IN1_VOL_WIDTH 1 /* IN1_VOL */
195#define WM9081_IN1_ENA 0x0001 /* IN1_ENA */
196#define WM9081_IN1_ENA_MASK 0x0001 /* IN1_ENA */
197#define WM9081_IN1_ENA_SHIFT 0 /* IN1_ENA */
198#define WM9081_IN1_ENA_WIDTH 1 /* IN1_ENA */
199
200/*
201 * R8 (0x08) - Anti Pop Control
202 */
203#define WM9081_LINEOUT_DISCH 0x0004 /* LINEOUT_DISCH */
204#define WM9081_LINEOUT_DISCH_MASK 0x0004 /* LINEOUT_DISCH */
205#define WM9081_LINEOUT_DISCH_SHIFT 2 /* LINEOUT_DISCH */
206#define WM9081_LINEOUT_DISCH_WIDTH 1 /* LINEOUT_DISCH */
207#define WM9081_LINEOUT_VROI 0x0002 /* LINEOUT_VROI */
208#define WM9081_LINEOUT_VROI_MASK 0x0002 /* LINEOUT_VROI */
209#define WM9081_LINEOUT_VROI_SHIFT 1 /* LINEOUT_VROI */
210#define WM9081_LINEOUT_VROI_WIDTH 1 /* LINEOUT_VROI */
211#define WM9081_LINEOUT_CLAMP 0x0001 /* LINEOUT_CLAMP */
212#define WM9081_LINEOUT_CLAMP_MASK 0x0001 /* LINEOUT_CLAMP */
213#define WM9081_LINEOUT_CLAMP_SHIFT 0 /* LINEOUT_CLAMP */
214#define WM9081_LINEOUT_CLAMP_WIDTH 1 /* LINEOUT_CLAMP */
215
216/*
217 * R9 (0x09) - Analogue Speaker 1
218 */
219#define WM9081_SPK_DCGAIN_MASK 0x0038 /* SPK_DCGAIN - [5:3] */
220#define WM9081_SPK_DCGAIN_SHIFT 3 /* SPK_DCGAIN - [5:3] */
221#define WM9081_SPK_DCGAIN_WIDTH 3 /* SPK_DCGAIN - [5:3] */
222#define WM9081_SPK_ACGAIN_MASK 0x0007 /* SPK_ACGAIN - [2:0] */
223#define WM9081_SPK_ACGAIN_SHIFT 0 /* SPK_ACGAIN - [2:0] */
224#define WM9081_SPK_ACGAIN_WIDTH 3 /* SPK_ACGAIN - [2:0] */
225
226/*
227 * R10 (0x0A) - Analogue Speaker 2
228 */
229#define WM9081_SPK_MODE 0x0040 /* SPK_MODE */
230#define WM9081_SPK_MODE_MASK 0x0040 /* SPK_MODE */
231#define WM9081_SPK_MODE_SHIFT 6 /* SPK_MODE */
232#define WM9081_SPK_MODE_WIDTH 1 /* SPK_MODE */
233#define WM9081_SPK_INV_MUTE 0x0010 /* SPK_INV_MUTE */
234#define WM9081_SPK_INV_MUTE_MASK 0x0010 /* SPK_INV_MUTE */
235#define WM9081_SPK_INV_MUTE_SHIFT 4 /* SPK_INV_MUTE */
236#define WM9081_SPK_INV_MUTE_WIDTH 1 /* SPK_INV_MUTE */
237#define WM9081_OUT_SPK_CTRL 0x0008 /* OUT_SPK_CTRL */
238#define WM9081_OUT_SPK_CTRL_MASK 0x0008 /* OUT_SPK_CTRL */
239#define WM9081_OUT_SPK_CTRL_SHIFT 3 /* OUT_SPK_CTRL */
240#define WM9081_OUT_SPK_CTRL_WIDTH 1 /* OUT_SPK_CTRL */
241
242/*
243 * R11 (0x0B) - Power Management
244 */
245#define WM9081_TSHUT_ENA 0x0100 /* TSHUT_ENA */
246#define WM9081_TSHUT_ENA_MASK 0x0100 /* TSHUT_ENA */
247#define WM9081_TSHUT_ENA_SHIFT 8 /* TSHUT_ENA */
248#define WM9081_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
249#define WM9081_TSENSE_ENA 0x0080 /* TSENSE_ENA */
250#define WM9081_TSENSE_ENA_MASK 0x0080 /* TSENSE_ENA */
251#define WM9081_TSENSE_ENA_SHIFT 7 /* TSENSE_ENA */
252#define WM9081_TSENSE_ENA_WIDTH 1 /* TSENSE_ENA */
253#define WM9081_TEMP_SHUT 0x0040 /* TEMP_SHUT */
254#define WM9081_TEMP_SHUT_MASK 0x0040 /* TEMP_SHUT */
255#define WM9081_TEMP_SHUT_SHIFT 6 /* TEMP_SHUT */
256#define WM9081_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
257#define WM9081_LINEOUT_ENA 0x0010 /* LINEOUT_ENA */
258#define WM9081_LINEOUT_ENA_MASK 0x0010 /* LINEOUT_ENA */
259#define WM9081_LINEOUT_ENA_SHIFT 4 /* LINEOUT_ENA */
260#define WM9081_LINEOUT_ENA_WIDTH 1 /* LINEOUT_ENA */
261#define WM9081_SPKPGA_ENA 0x0004 /* SPKPGA_ENA */
262#define WM9081_SPKPGA_ENA_MASK 0x0004 /* SPKPGA_ENA */
263#define WM9081_SPKPGA_ENA_SHIFT 2 /* SPKPGA_ENA */
264#define WM9081_SPKPGA_ENA_WIDTH 1 /* SPKPGA_ENA */
265#define WM9081_SPK_ENA 0x0002 /* SPK_ENA */
266#define WM9081_SPK_ENA_MASK 0x0002 /* SPK_ENA */
267#define WM9081_SPK_ENA_SHIFT 1 /* SPK_ENA */
268#define WM9081_SPK_ENA_WIDTH 1 /* SPK_ENA */
269#define WM9081_DAC_ENA 0x0001 /* DAC_ENA */
270#define WM9081_DAC_ENA_MASK 0x0001 /* DAC_ENA */
271#define WM9081_DAC_ENA_SHIFT 0 /* DAC_ENA */
272#define WM9081_DAC_ENA_WIDTH 1 /* DAC_ENA */
273
274/*
275 * R12 (0x0C) - Clock Control 1
276 */
277#define WM9081_CLK_OP_DIV_MASK 0x1C00 /* CLK_OP_DIV - [12:10] */
278#define WM9081_CLK_OP_DIV_SHIFT 10 /* CLK_OP_DIV - [12:10] */
279#define WM9081_CLK_OP_DIV_WIDTH 3 /* CLK_OP_DIV - [12:10] */
280#define WM9081_CLK_TO_DIV_MASK 0x0300 /* CLK_TO_DIV - [9:8] */
281#define WM9081_CLK_TO_DIV_SHIFT 8 /* CLK_TO_DIV - [9:8] */
282#define WM9081_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [9:8] */
283#define WM9081_MCLKDIV2 0x0080 /* MCLKDIV2 */
284#define WM9081_MCLKDIV2_MASK 0x0080 /* MCLKDIV2 */
285#define WM9081_MCLKDIV2_SHIFT 7 /* MCLKDIV2 */
286#define WM9081_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */
287
288/*
289 * R13 (0x0D) - Clock Control 2
290 */
291#define WM9081_CLK_SYS_RATE_MASK 0x00F0 /* CLK_SYS_RATE - [7:4] */
292#define WM9081_CLK_SYS_RATE_SHIFT 4 /* CLK_SYS_RATE - [7:4] */
293#define WM9081_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [7:4] */
294#define WM9081_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */
295#define WM9081_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */
296#define WM9081_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */
297
298/*
299 * R14 (0x0E) - Clock Control 3
300 */
301#define WM9081_CLK_SRC_SEL 0x2000 /* CLK_SRC_SEL */
302#define WM9081_CLK_SRC_SEL_MASK 0x2000 /* CLK_SRC_SEL */
303#define WM9081_CLK_SRC_SEL_SHIFT 13 /* CLK_SRC_SEL */
304#define WM9081_CLK_SRC_SEL_WIDTH 1 /* CLK_SRC_SEL */
305#define WM9081_CLK_OP_ENA 0x0020 /* CLK_OP_ENA */
306#define WM9081_CLK_OP_ENA_MASK 0x0020 /* CLK_OP_ENA */
307#define WM9081_CLK_OP_ENA_SHIFT 5 /* CLK_OP_ENA */
308#define WM9081_CLK_OP_ENA_WIDTH 1 /* CLK_OP_ENA */
309#define WM9081_CLK_TO_ENA 0x0004 /* CLK_TO_ENA */
310#define WM9081_CLK_TO_ENA_MASK 0x0004 /* CLK_TO_ENA */
311#define WM9081_CLK_TO_ENA_SHIFT 2 /* CLK_TO_ENA */
312#define WM9081_CLK_TO_ENA_WIDTH 1 /* CLK_TO_ENA */
313#define WM9081_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */
314#define WM9081_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */
315#define WM9081_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */
316#define WM9081_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
317#define WM9081_CLK_SYS_ENA 0x0001 /* CLK_SYS_ENA */
318#define WM9081_CLK_SYS_ENA_MASK 0x0001 /* CLK_SYS_ENA */
319#define WM9081_CLK_SYS_ENA_SHIFT 0 /* CLK_SYS_ENA */
320#define WM9081_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
321
322/*
323 * R16 (0x10) - FLL Control 1
324 */
325#define WM9081_FLL_HOLD 0x0008 /* FLL_HOLD */
326#define WM9081_FLL_HOLD_MASK 0x0008 /* FLL_HOLD */
327#define WM9081_FLL_HOLD_SHIFT 3 /* FLL_HOLD */
328#define WM9081_FLL_HOLD_WIDTH 1 /* FLL_HOLD */
329#define WM9081_FLL_FRAC 0x0004 /* FLL_FRAC */
330#define WM9081_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
331#define WM9081_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
332#define WM9081_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
333#define WM9081_FLL_ENA 0x0001 /* FLL_ENA */
334#define WM9081_FLL_ENA_MASK 0x0001 /* FLL_ENA */
335#define WM9081_FLL_ENA_SHIFT 0 /* FLL_ENA */
336#define WM9081_FLL_ENA_WIDTH 1 /* FLL_ENA */
337
338/*
339 * R17 (0x11) - FLL Control 2
340 */
341#define WM9081_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */
342#define WM9081_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */
343#define WM9081_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */
344#define WM9081_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */
345#define WM9081_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */
346#define WM9081_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */
347#define WM9081_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
348#define WM9081_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
349#define WM9081_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
350
351/*
352 * R18 (0x12) - FLL Control 3
353 */
354#define WM9081_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */
355#define WM9081_FLL_K_SHIFT 0 /* FLL_K - [15:0] */
356#define WM9081_FLL_K_WIDTH 16 /* FLL_K - [15:0] */
357
358/*
359 * R19 (0x13) - FLL Control 4
360 */
361#define WM9081_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */
362#define WM9081_FLL_N_SHIFT 5 /* FLL_N - [14:5] */
363#define WM9081_FLL_N_WIDTH 10 /* FLL_N - [14:5] */
364#define WM9081_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */
365#define WM9081_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */
366#define WM9081_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */
367
368/*
369 * R20 (0x14) - FLL Control 5
370 */
371#define WM9081_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */
372#define WM9081_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */
373#define WM9081_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */
374#define WM9081_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */
375#define WM9081_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */
376#define WM9081_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */
377
378/*
379 * R22 (0x16) - Audio Interface 1
380 */
381#define WM9081_AIFDAC_CHAN 0x0040 /* AIFDAC_CHAN */
382#define WM9081_AIFDAC_CHAN_MASK 0x0040 /* AIFDAC_CHAN */
383#define WM9081_AIFDAC_CHAN_SHIFT 6 /* AIFDAC_CHAN */
384#define WM9081_AIFDAC_CHAN_WIDTH 1 /* AIFDAC_CHAN */
385#define WM9081_AIFDAC_TDM_SLOT_MASK 0x0030 /* AIFDAC_TDM_SLOT - [5:4] */
386#define WM9081_AIFDAC_TDM_SLOT_SHIFT 4 /* AIFDAC_TDM_SLOT - [5:4] */
387#define WM9081_AIFDAC_TDM_SLOT_WIDTH 2 /* AIFDAC_TDM_SLOT - [5:4] */
388#define WM9081_AIFDAC_TDM_MODE_MASK 0x000C /* AIFDAC_TDM_MODE - [3:2] */
389#define WM9081_AIFDAC_TDM_MODE_SHIFT 2 /* AIFDAC_TDM_MODE - [3:2] */
390#define WM9081_AIFDAC_TDM_MODE_WIDTH 2 /* AIFDAC_TDM_MODE - [3:2] */
391#define WM9081_DAC_COMP 0x0002 /* DAC_COMP */
392#define WM9081_DAC_COMP_MASK 0x0002 /* DAC_COMP */
393#define WM9081_DAC_COMP_SHIFT 1 /* DAC_COMP */
394#define WM9081_DAC_COMP_WIDTH 1 /* DAC_COMP */
395#define WM9081_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */
396#define WM9081_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */
397#define WM9081_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */
398#define WM9081_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
399
400/*
401 * R23 (0x17) - Audio Interface 2
402 */
403#define WM9081_AIF_TRIS 0x0200 /* AIF_TRIS */
404#define WM9081_AIF_TRIS_MASK 0x0200 /* AIF_TRIS */
405#define WM9081_AIF_TRIS_SHIFT 9 /* AIF_TRIS */
406#define WM9081_AIF_TRIS_WIDTH 1 /* AIF_TRIS */
407#define WM9081_DAC_DAT_INV 0x0100 /* DAC_DAT_INV */
408#define WM9081_DAC_DAT_INV_MASK 0x0100 /* DAC_DAT_INV */
409#define WM9081_DAC_DAT_INV_SHIFT 8 /* DAC_DAT_INV */
410#define WM9081_DAC_DAT_INV_WIDTH 1 /* DAC_DAT_INV */
411#define WM9081_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */
412#define WM9081_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */
413#define WM9081_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */
414#define WM9081_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
415#define WM9081_BCLK_DIR 0x0040 /* BCLK_DIR */
416#define WM9081_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */
417#define WM9081_BCLK_DIR_SHIFT 6 /* BCLK_DIR */
418#define WM9081_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
419#define WM9081_LRCLK_DIR 0x0020 /* LRCLK_DIR */
420#define WM9081_LRCLK_DIR_MASK 0x0020 /* LRCLK_DIR */
421#define WM9081_LRCLK_DIR_SHIFT 5 /* LRCLK_DIR */
422#define WM9081_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
423#define WM9081_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */
424#define WM9081_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */
425#define WM9081_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */
426#define WM9081_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
427#define WM9081_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */
428#define WM9081_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */
429#define WM9081_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */
430#define WM9081_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */
431#define WM9081_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */
432#define WM9081_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */
433
434/*
435 * R24 (0x18) - Audio Interface 3
436 */
437#define WM9081_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */
438#define WM9081_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */
439#define WM9081_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */
440
441/*
442 * R25 (0x19) - Audio Interface 4
443 */
444#define WM9081_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
445#define WM9081_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
446#define WM9081_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
447
448/*
449 * R26 (0x1A) - Interrupt Status
450 */
451#define WM9081_WSEQ_BUSY_EINT 0x0004 /* WSEQ_BUSY_EINT */
452#define WM9081_WSEQ_BUSY_EINT_MASK 0x0004 /* WSEQ_BUSY_EINT */
453#define WM9081_WSEQ_BUSY_EINT_SHIFT 2 /* WSEQ_BUSY_EINT */
454#define WM9081_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
455#define WM9081_TSHUT_EINT 0x0001 /* TSHUT_EINT */
456#define WM9081_TSHUT_EINT_MASK 0x0001 /* TSHUT_EINT */
457#define WM9081_TSHUT_EINT_SHIFT 0 /* TSHUT_EINT */
458#define WM9081_TSHUT_EINT_WIDTH 1 /* TSHUT_EINT */
459
460/*
461 * R27 (0x1B) - Interrupt Status Mask
462 */
463#define WM9081_IM_WSEQ_BUSY_EINT 0x0004 /* IM_WSEQ_BUSY_EINT */
464#define WM9081_IM_WSEQ_BUSY_EINT_MASK 0x0004 /* IM_WSEQ_BUSY_EINT */
465#define WM9081_IM_WSEQ_BUSY_EINT_SHIFT 2 /* IM_WSEQ_BUSY_EINT */
466#define WM9081_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
467#define WM9081_IM_TSHUT_EINT 0x0001 /* IM_TSHUT_EINT */
468#define WM9081_IM_TSHUT_EINT_MASK 0x0001 /* IM_TSHUT_EINT */
469#define WM9081_IM_TSHUT_EINT_SHIFT 0 /* IM_TSHUT_EINT */
470#define WM9081_IM_TSHUT_EINT_WIDTH 1 /* IM_TSHUT_EINT */
471
472/*
473 * R28 (0x1C) - Interrupt Polarity
474 */
475#define WM9081_TSHUT_INV 0x0001 /* TSHUT_INV */
476#define WM9081_TSHUT_INV_MASK 0x0001 /* TSHUT_INV */
477#define WM9081_TSHUT_INV_SHIFT 0 /* TSHUT_INV */
478#define WM9081_TSHUT_INV_WIDTH 1 /* TSHUT_INV */
479
480/*
481 * R29 (0x1D) - Interrupt Control
482 */
483#define WM9081_IRQ_POL 0x8000 /* IRQ_POL */
484#define WM9081_IRQ_POL_MASK 0x8000 /* IRQ_POL */
485#define WM9081_IRQ_POL_SHIFT 15 /* IRQ_POL */
486#define WM9081_IRQ_POL_WIDTH 1 /* IRQ_POL */
487#define WM9081_IRQ_OP_CTRL 0x0001 /* IRQ_OP_CTRL */
488#define WM9081_IRQ_OP_CTRL_MASK 0x0001 /* IRQ_OP_CTRL */
489#define WM9081_IRQ_OP_CTRL_SHIFT 0 /* IRQ_OP_CTRL */
490#define WM9081_IRQ_OP_CTRL_WIDTH 1 /* IRQ_OP_CTRL */
491
492/*
493 * R30 (0x1E) - DAC Digital 1
494 */
495#define WM9081_DAC_VOL_MASK 0x00FF /* DAC_VOL - [7:0] */
496#define WM9081_DAC_VOL_SHIFT 0 /* DAC_VOL - [7:0] */
497#define WM9081_DAC_VOL_WIDTH 8 /* DAC_VOL - [7:0] */
498
499/*
500 * R31 (0x1F) - DAC Digital 2
501 */
502#define WM9081_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */
503#define WM9081_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */
504#define WM9081_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */
505#define WM9081_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
506#define WM9081_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */
507#define WM9081_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */
508#define WM9081_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */
509#define WM9081_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */
510#define WM9081_DAC_MUTE 0x0008 /* DAC_MUTE */
511#define WM9081_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
512#define WM9081_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
513#define WM9081_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
514#define WM9081_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
515#define WM9081_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
516#define WM9081_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
517
518/*
519 * R32 (0x20) - DRC 1
520 */
521#define WM9081_DRC_ENA 0x8000 /* DRC_ENA */
522#define WM9081_DRC_ENA_MASK 0x8000 /* DRC_ENA */
523#define WM9081_DRC_ENA_SHIFT 15 /* DRC_ENA */
524#define WM9081_DRC_ENA_WIDTH 1 /* DRC_ENA */
525#define WM9081_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */
526#define WM9081_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */
527#define WM9081_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */
528#define WM9081_DRC_FF_DLY 0x0020 /* DRC_FF_DLY */
529#define WM9081_DRC_FF_DLY_MASK 0x0020 /* DRC_FF_DLY */
530#define WM9081_DRC_FF_DLY_SHIFT 5 /* DRC_FF_DLY */
531#define WM9081_DRC_FF_DLY_WIDTH 1 /* DRC_FF_DLY */
532#define WM9081_DRC_QR 0x0004 /* DRC_QR */
533#define WM9081_DRC_QR_MASK 0x0004 /* DRC_QR */
534#define WM9081_DRC_QR_SHIFT 2 /* DRC_QR */
535#define WM9081_DRC_QR_WIDTH 1 /* DRC_QR */
536#define WM9081_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */
537#define WM9081_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */
538#define WM9081_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */
539#define WM9081_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
540
541/*
542 * R33 (0x21) - DRC 2
543 */
544#define WM9081_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */
545#define WM9081_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */
546#define WM9081_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */
547#define WM9081_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */
548#define WM9081_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */
549#define WM9081_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */
550#define WM9081_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */
551#define WM9081_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */
552#define WM9081_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */
553#define WM9081_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */
554#define WM9081_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */
555#define WM9081_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */
556#define WM9081_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
557#define WM9081_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
558#define WM9081_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
559#define WM9081_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
560#define WM9081_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
561#define WM9081_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
562
563/*
564 * R34 (0x22) - DRC 3
565 */
566#define WM9081_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
567#define WM9081_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
568#define WM9081_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
569#define WM9081_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
570#define WM9081_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
571#define WM9081_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
572
573/*
574 * R35 (0x23) - DRC 4
575 */
576#define WM9081_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
577#define WM9081_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
578#define WM9081_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
579#define WM9081_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
580#define WM9081_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
581#define WM9081_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
582
583/*
584 * R38 (0x26) - Write Sequencer 1
585 */
586#define WM9081_WSEQ_ENA 0x8000 /* WSEQ_ENA */
587#define WM9081_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */
588#define WM9081_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */
589#define WM9081_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
590#define WM9081_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
591#define WM9081_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
592#define WM9081_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
593#define WM9081_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
594#define WM9081_WSEQ_START 0x0100 /* WSEQ_START */
595#define WM9081_WSEQ_START_MASK 0x0100 /* WSEQ_START */
596#define WM9081_WSEQ_START_SHIFT 8 /* WSEQ_START */
597#define WM9081_WSEQ_START_WIDTH 1 /* WSEQ_START */
598#define WM9081_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
599#define WM9081_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
600#define WM9081_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
601
602/*
603 * R39 (0x27) - Write Sequencer 2
604 */
605#define WM9081_WSEQ_CURRENT_INDEX_MASK 0x07F0 /* WSEQ_CURRENT_INDEX - [10:4] */
606#define WM9081_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [10:4] */
607#define WM9081_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [10:4] */
608#define WM9081_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
609#define WM9081_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
610#define WM9081_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
611#define WM9081_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
612
613/*
614 * R40 (0x28) - MW Slave 1
615 */
616#define WM9081_SPI_CFG 0x0020 /* SPI_CFG */
617#define WM9081_SPI_CFG_MASK 0x0020 /* SPI_CFG */
618#define WM9081_SPI_CFG_SHIFT 5 /* SPI_CFG */
619#define WM9081_SPI_CFG_WIDTH 1 /* SPI_CFG */
620#define WM9081_SPI_4WIRE 0x0010 /* SPI_4WIRE */
621#define WM9081_SPI_4WIRE_MASK 0x0010 /* SPI_4WIRE */
622#define WM9081_SPI_4WIRE_SHIFT 4 /* SPI_4WIRE */
623#define WM9081_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
624#define WM9081_ARA_ENA 0x0008 /* ARA_ENA */
625#define WM9081_ARA_ENA_MASK 0x0008 /* ARA_ENA */
626#define WM9081_ARA_ENA_SHIFT 3 /* ARA_ENA */
627#define WM9081_ARA_ENA_WIDTH 1 /* ARA_ENA */
628#define WM9081_AUTO_INC 0x0002 /* AUTO_INC */
629#define WM9081_AUTO_INC_MASK 0x0002 /* AUTO_INC */
630#define WM9081_AUTO_INC_SHIFT 1 /* AUTO_INC */
631#define WM9081_AUTO_INC_WIDTH 1 /* AUTO_INC */
632
633/*
634 * R42 (0x2A) - EQ 1
635 */
636#define WM9081_EQ_B1_GAIN_MASK 0xF800 /* EQ_B1_GAIN - [15:11] */
637#define WM9081_EQ_B1_GAIN_SHIFT 11 /* EQ_B1_GAIN - [15:11] */
638#define WM9081_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [15:11] */
639#define WM9081_EQ_B2_GAIN_MASK 0x07C0 /* EQ_B2_GAIN - [10:6] */
640#define WM9081_EQ_B2_GAIN_SHIFT 6 /* EQ_B2_GAIN - [10:6] */
641#define WM9081_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [10:6] */
642#define WM9081_EQ_B4_GAIN_MASK 0x003E /* EQ_B4_GAIN - [5:1] */
643#define WM9081_EQ_B4_GAIN_SHIFT 1 /* EQ_B4_GAIN - [5:1] */
644#define WM9081_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [5:1] */
645#define WM9081_EQ_ENA 0x0001 /* EQ_ENA */
646#define WM9081_EQ_ENA_MASK 0x0001 /* EQ_ENA */
647#define WM9081_EQ_ENA_SHIFT 0 /* EQ_ENA */
648#define WM9081_EQ_ENA_WIDTH 1 /* EQ_ENA */
649
650/*
651 * R43 (0x2B) - EQ 2
652 */
653#define WM9081_EQ_B3_GAIN_MASK 0xF800 /* EQ_B3_GAIN - [15:11] */
654#define WM9081_EQ_B3_GAIN_SHIFT 11 /* EQ_B3_GAIN - [15:11] */
655#define WM9081_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [15:11] */
656#define WM9081_EQ_B5_GAIN_MASK 0x07C0 /* EQ_B5_GAIN - [10:6] */
657#define WM9081_EQ_B5_GAIN_SHIFT 6 /* EQ_B5_GAIN - [10:6] */
658#define WM9081_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [10:6] */
659
660/*
661 * R44 (0x2C) - EQ 3
662 */
663#define WM9081_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */
664#define WM9081_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */
665#define WM9081_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */
666
667/*
668 * R45 (0x2D) - EQ 4
669 */
670#define WM9081_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */
671#define WM9081_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */
672#define WM9081_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */
673
674/*
675 * R46 (0x2E) - EQ 5
676 */
677#define WM9081_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */
678#define WM9081_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */
679#define WM9081_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */
680
681/*
682 * R47 (0x2F) - EQ 6
683 */
684#define WM9081_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */
685#define WM9081_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */
686#define WM9081_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */
687
688/*
689 * R48 (0x30) - EQ 7
690 */
691#define WM9081_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */
692#define WM9081_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */
693#define WM9081_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */
694
695/*
696 * R49 (0x31) - EQ 8
697 */
698#define WM9081_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */
699#define WM9081_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */
700#define WM9081_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */
701
702/*
703 * R50 (0x32) - EQ 9
704 */
705#define WM9081_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */
706#define WM9081_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */
707#define WM9081_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */
708
709/*
710 * R51 (0x33) - EQ 10
711 */
712#define WM9081_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */
713#define WM9081_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */
714#define WM9081_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */
715
716/*
717 * R52 (0x34) - EQ 11
718 */
719#define WM9081_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */
720#define WM9081_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */
721#define WM9081_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */
722
723/*
724 * R53 (0x35) - EQ 12
725 */
726#define WM9081_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */
727#define WM9081_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */
728#define WM9081_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */
729
730/*
731 * R54 (0x36) - EQ 13
732 */
733#define WM9081_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */
734#define WM9081_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */
735#define WM9081_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */
736
737/*
738 * R55 (0x37) - EQ 14
739 */
740#define WM9081_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */
741#define WM9081_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */
742#define WM9081_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */
743
744/*
745 * R56 (0x38) - EQ 15
746 */
747#define WM9081_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */
748#define WM9081_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */
749#define WM9081_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */
750
751/*
752 * R57 (0x39) - EQ 16
753 */
754#define WM9081_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */
755#define WM9081_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */
756#define WM9081_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */
757
758/*
759 * R58 (0x3A) - EQ 17
760 */
761#define WM9081_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */
762#define WM9081_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */
763#define WM9081_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */
764
765/*
766 * R59 (0x3B) - EQ 18
767 */
768#define WM9081_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */
769#define WM9081_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */
770#define WM9081_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */
771
772/*
773 * R60 (0x3C) - EQ 19
774 */
775#define WM9081_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */
776#define WM9081_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */
777#define WM9081_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */
778
779/*
780 * R61 (0x3D) - EQ 20
781 */
782#define WM9081_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */
783#define WM9081_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */
784#define WM9081_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */
785
786
787#endif
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index c2d1a7a18fa3..fa88b463e71f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -282,14 +282,14 @@ struct snd_soc_dai wm9705_dai[] = {
282 .channels_min = 1, 282 .channels_min = 1,
283 .channels_max = 2, 283 .channels_max = 2,
284 .rates = WM9705_AC97_RATES, 284 .rates = WM9705_AC97_RATES,
285 .formats = SNDRV_PCM_FMTBIT_S16_LE, 285 .formats = SND_SOC_STD_AC97_FMTS,
286 }, 286 },
287 .capture = { 287 .capture = {
288 .stream_name = "HiFi Capture", 288 .stream_name = "HiFi Capture",
289 .channels_min = 1, 289 .channels_min = 1,
290 .channels_max = 2, 290 .channels_max = 2,
291 .rates = WM9705_AC97_RATES, 291 .rates = WM9705_AC97_RATES,
292 .formats = SNDRV_PCM_FMTBIT_S16_LE, 292 .formats = SND_SOC_STD_AC97_FMTS,
293 }, 293 },
294 .ops = &wm9705_dai_ops, 294 .ops = &wm9705_dai_ops,
295 }, 295 },
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 765cf1e7369e..1fd4e88f50cf 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -534,13 +534,13 @@ struct snd_soc_dai wm9712_dai[] = {
534 .channels_min = 1, 534 .channels_min = 1,
535 .channels_max = 2, 535 .channels_max = 2,
536 .rates = WM9712_AC97_RATES, 536 .rates = WM9712_AC97_RATES,
537 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 537 .formats = SND_SOC_STD_AC97_FMTS,},
538 .capture = { 538 .capture = {
539 .stream_name = "HiFi Capture", 539 .stream_name = "HiFi Capture",
540 .channels_min = 1, 540 .channels_min = 1,
541 .channels_max = 2, 541 .channels_max = 2,
542 .rates = WM9712_AC97_RATES, 542 .rates = WM9712_AC97_RATES,
543 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 543 .formats = SND_SOC_STD_AC97_FMTS,},
544 .ops = &wm9712_dai_ops_hifi, 544 .ops = &wm9712_dai_ops_hifi,
545}, 545},
546{ 546{
@@ -550,7 +550,7 @@ struct snd_soc_dai wm9712_dai[] = {
550 .channels_min = 1, 550 .channels_min = 1,
551 .channels_max = 1, 551 .channels_max = 1,
552 .rates = WM9712_AC97_RATES, 552 .rates = WM9712_AC97_RATES,
553 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 553 .formats = SND_SOC_STD_AC97_FMTS,},
554 .ops = &wm9712_dai_ops_aux, 554 .ops = &wm9712_dai_ops_aux,
555} 555}
556}; 556};
@@ -585,6 +585,8 @@ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
585 } 585 }
586 586
587 soc_ac97_ops.reset(codec->ac97); 587 soc_ac97_ops.reset(codec->ac97);
588 if (soc_ac97_ops.warm_reset)
589 soc_ac97_ops.warm_reset(codec->ac97);
588 if (ac97_read(codec, 0) != wm9712_reg[0]) 590 if (ac97_read(codec, 0) != wm9712_reg[0])
589 goto err; 591 goto err;
590 return 0; 592 return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 523bad077fa0..abed37acf787 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -189,6 +189,26 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
189SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), 189SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
190}; 190};
191 191
192static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
193 struct snd_kcontrol *kcontrol, int event)
194{
195 struct snd_soc_codec *codec = w->codec;
196 u16 status, rate;
197
198 BUG_ON(event != SND_SOC_DAPM_PRE_PMD);
199
200 /* Gracefully shut down the voice interface. */
201 status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000;
202 rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
203 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
204 schedule_timeout_interruptible(msecs_to_jiffies(1));
205 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
206 ac97_write(codec, AC97_EXTENDED_MID, status);
207
208 return 0;
209}
210
211
192/* We have to create a fake left and right HP mixers because 212/* We have to create a fake left and right HP mixers because
193 * the codec only has a single control that is shared by both channels. 213 * the codec only has a single control that is shared by both channels.
194 * This makes it impossible to determine the audio path using the current 214 * This makes it impossible to determine the audio path using the current
@@ -400,7 +420,8 @@ SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
400SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 420SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
401SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 421SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
402SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), 422SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
403SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1), 423SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1,
424 wm9713_voice_shutdown, SND_SOC_DAPM_PRE_PMD),
404SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1), 425SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
405SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0), 426SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0),
406SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0), 427SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0),
@@ -689,7 +710,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source)
689 Ndiv = target / source; 710 Ndiv = target / source;
690 if ((Ndiv < 5) || (Ndiv > 12)) 711 if ((Ndiv < 5) || (Ndiv > 12))
691 printk(KERN_WARNING 712 printk(KERN_WARNING
692 "WM9713 PLL N value %d out of recommended range!\n", 713 "WM9713 PLL N value %u out of recommended range!\n",
693 Ndiv); 714 Ndiv);
694 715
695 pll_div->n = Ndiv; 716 pll_div->n = Ndiv;
@@ -936,21 +957,6 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
936 return 0; 957 return 0;
937} 958}
938 959
939static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
940 struct snd_soc_dai *dai)
941{
942 struct snd_soc_codec *codec = dai->codec;
943 u16 status, rate;
944
945 /* Gracefully shut down the voice interface. */
946 status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
947 rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
948 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
949 schedule_timeout_interruptible(msecs_to_jiffies(1));
950 ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
951 ac97_write(codec, AC97_EXTENDED_MID, status);
952}
953
954static int ac97_hifi_prepare(struct snd_pcm_substream *substream, 960static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
955 struct snd_soc_dai *dai) 961 struct snd_soc_dai *dai)
956{ 962{
@@ -1019,7 +1025,6 @@ static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
1019 1025
1020static struct snd_soc_dai_ops wm9713_dai_ops_voice = { 1026static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
1021 .hw_params = wm9713_pcm_hw_params, 1027 .hw_params = wm9713_pcm_hw_params,
1022 .shutdown = wm9713_voiceshutdown,
1023 .set_clkdiv = wm9713_set_dai_clkdiv, 1028 .set_clkdiv = wm9713_set_dai_clkdiv,
1024 .set_pll = wm9713_set_dai_pll, 1029 .set_pll = wm9713_set_dai_pll,
1025 .set_fmt = wm9713_set_dai_fmt, 1030 .set_fmt = wm9713_set_dai_fmt,
@@ -1035,13 +1040,13 @@ struct snd_soc_dai wm9713_dai[] = {
1035 .channels_min = 1, 1040 .channels_min = 1,
1036 .channels_max = 2, 1041 .channels_max = 2,
1037 .rates = WM9713_RATES, 1042 .rates = WM9713_RATES,
1038 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1043 .formats = SND_SOC_STD_AC97_FMTS,},
1039 .capture = { 1044 .capture = {
1040 .stream_name = "HiFi Capture", 1045 .stream_name = "HiFi Capture",
1041 .channels_min = 1, 1046 .channels_min = 1,
1042 .channels_max = 2, 1047 .channels_max = 2,
1043 .rates = WM9713_RATES, 1048 .rates = WM9713_RATES,
1044 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1049 .formats = SND_SOC_STD_AC97_FMTS,},
1045 .ops = &wm9713_dai_ops_hifi, 1050 .ops = &wm9713_dai_ops_hifi,
1046 }, 1051 },
1047 { 1052 {
@@ -1051,7 +1056,7 @@ struct snd_soc_dai wm9713_dai[] = {
1051 .channels_min = 1, 1056 .channels_min = 1,
1052 .channels_max = 1, 1057 .channels_max = 1,
1053 .rates = WM9713_RATES, 1058 .rates = WM9713_RATES,
1054 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1059 .formats = SND_SOC_STD_AC97_FMTS,},
1055 .ops = &wm9713_dai_ops_aux, 1060 .ops = &wm9713_dai_ops_aux,
1056 }, 1061 },
1057 { 1062 {
@@ -1069,6 +1074,7 @@ struct snd_soc_dai wm9713_dai[] = {
1069 .rates = WM9713_PCM_RATES, 1074 .rates = WM9713_PCM_RATES,
1070 .formats = WM9713_PCM_FORMATS,}, 1075 .formats = WM9713_PCM_FORMATS,},
1071 .ops = &wm9713_dai_ops_voice, 1076 .ops = &wm9713_dai_ops_voice,
1077 .symmetric_rates = 1,
1072 }, 1078 },
1073}; 1079};
1074EXPORT_SYMBOL_GPL(wm9713_dai); 1080EXPORT_SYMBOL_GPL(wm9713_dai);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
new file mode 100644
index 000000000000..e8fc474ba5cf
--- /dev/null
+++ b/sound/soc/codecs/wm_hubs.c
@@ -0,0 +1,758 @@
1/*
2 * wm_hubs.c -- WM8993/4 common code
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 <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
30#include "wm8993.h"
31#include "wm_hubs.h"
32
33const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0);
34EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv);
35
36static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
37static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
38static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
39static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
40static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
41static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
42static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
43static const unsigned int spkboost_tlv[] = {
44 TLV_DB_RANGE_HEAD(7),
45 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
46 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
47};
48static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
49
50static const char *speaker_ref_text[] = {
51 "SPKVDD/2",
52 "VMID",
53};
54
55static const struct soc_enum speaker_ref =
56 SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text);
57
58static const char *speaker_mode_text[] = {
59 "Class D",
60 "Class AB",
61};
62
63static const struct soc_enum speaker_mode =
64 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
65
66static void wait_for_dc_servo(struct snd_soc_codec *codec)
67{
68 unsigned int reg;
69 int count = 0;
70
71 dev_dbg(codec->dev, "Waiting for DC servo...\n");
72 do {
73 count++;
74 msleep(1);
75 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
76 dev_dbg(codec->dev, "DC servo status: %x\n", reg);
77 } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
78 != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000);
79
80 if ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
81 != WM8993_DCS_CAL_COMPLETE_MASK)
82 dev_err(codec->dev, "Timed out waiting for DC Servo\n");
83}
84
85/*
86 * Update the DC servo calibration on gain changes
87 */
88static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
89 struct snd_ctl_elem_value *ucontrol)
90{
91 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
92 int ret;
93
94 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
95
96 /* Only need to do this if the outputs are active */
97 if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
98 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
99 snd_soc_update_bits(codec,
100 WM8993_DC_SERVO_0,
101 WM8993_DCS_TRIG_SINGLE_0 |
102 WM8993_DCS_TRIG_SINGLE_1,
103 WM8993_DCS_TRIG_SINGLE_0 |
104 WM8993_DCS_TRIG_SINGLE_1);
105
106 return ret;
107}
108
109static const struct snd_kcontrol_new analogue_snd_controls[] = {
110SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
111 inpga_tlv),
112SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
113SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
114
115SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
116 inpga_tlv),
117SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
118SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
119
120
121SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
122 inpga_tlv),
123SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
124SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
125
126SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
127 inpga_tlv),
128SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
129SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
130
131SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
132 inmix_sw_tlv),
133SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
134 inmix_sw_tlv),
135SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
136 inmix_tlv),
137SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
138SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
139 inmix_tlv),
140
141SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
142 inmix_sw_tlv),
143SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
144 inmix_sw_tlv),
145SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
146 inmix_tlv),
147SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
148SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
149 inmix_tlv),
150
151SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
152 outmix_tlv),
153SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
154 outmix_tlv),
155SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
156 outmix_tlv),
157SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
158 outmix_tlv),
159SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
160 outmix_tlv),
161SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
162 WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
163SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
164 WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
165SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
166 outmix_tlv),
167
168SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
169 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
170SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
171 WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
172SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
173 WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
174SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
175 WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
176SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
177 WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
178SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
179 WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
180SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
181 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
182SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
183 WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
184
185SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
186 WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
187SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
188 WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
189SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
190 WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
191
192SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
193SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
194
195SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
196 5, 1, 1, wm_hubs_spkmix_tlv),
197SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
198 4, 1, 1, wm_hubs_spkmix_tlv),
199SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
200 3, 1, 1, wm_hubs_spkmix_tlv),
201
202SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
203 5, 1, 1, wm_hubs_spkmix_tlv),
204SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
205 4, 1, 1, wm_hubs_spkmix_tlv),
206SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
207 3, 1, 1, wm_hubs_spkmix_tlv),
208
209SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
210 WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
211 0, 3, 1, spkmixout_tlv),
212SOC_DOUBLE_R_TLV("Speaker Volume",
213 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
214 0, 63, 0, outpga_tlv),
215SOC_DOUBLE_R("Speaker Switch",
216 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
217 6, 1, 0),
218SOC_DOUBLE_R("Speaker ZC Switch",
219 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
220 7, 1, 0),
221SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
222 spkboost_tlv),
223SOC_ENUM("Speaker Reference", speaker_ref),
224SOC_ENUM("Speaker Mode", speaker_mode),
225
226{
227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
228 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
229 SNDRV_CTL_ELEM_ACCESS_READWRITE,
230 .tlv.p = outpga_tlv,
231 .info = snd_soc_info_volsw_2r,
232 .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
233 .private_value = (unsigned long)&(struct soc_mixer_control) {
234 .reg = WM8993_LEFT_OUTPUT_VOLUME,
235 .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
236 .shift = 0, .max = 63
237 },
238},
239SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
240 WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
241SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
242 WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
243
244SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
245SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
246SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
247 line_tlv),
248
249SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
250SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
251SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
252 line_tlv),
253};
254
255static int hp_event(struct snd_soc_dapm_widget *w,
256 struct snd_kcontrol *kcontrol, int event)
257{
258 struct snd_soc_codec *codec = w->codec;
259 unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0);
260
261 switch (event) {
262 case SND_SOC_DAPM_POST_PMU:
263 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
264 WM8993_CP_ENA, WM8993_CP_ENA);
265
266 msleep(5);
267
268 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
269 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
270 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
271
272 reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
273 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
274
275 /* Start the DC servo */
276 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
277 WM8993_DCS_ENA_CHAN_0 |
278 WM8993_DCS_ENA_CHAN_1 |
279 WM8993_DCS_TRIG_STARTUP_1 |
280 WM8993_DCS_TRIG_STARTUP_0,
281 WM8993_DCS_ENA_CHAN_0 |
282 WM8993_DCS_ENA_CHAN_1 |
283 WM8993_DCS_TRIG_STARTUP_1 |
284 WM8993_DCS_TRIG_STARTUP_0);
285 wait_for_dc_servo(codec);
286 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
287 WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa);
288
289 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
290 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
291 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
292 break;
293
294 case SND_SOC_DAPM_PRE_PMD:
295 reg &= ~(WM8993_HPOUT1L_RMV_SHORT |
296 WM8993_HPOUT1L_DLY |
297 WM8993_HPOUT1L_OUTP |
298 WM8993_HPOUT1R_RMV_SHORT |
299 WM8993_HPOUT1R_DLY |
300 WM8993_HPOUT1R_OUTP);
301
302 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
303 WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
304 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
305 WM8993_DCS_ENA_CHAN_0 |
306 WM8993_DCS_ENA_CHAN_1, 0);
307
308 snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
309 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
310 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
311 0);
312
313 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
314 WM8993_CP_ENA, 0);
315 break;
316 }
317
318 return 0;
319}
320
321static int earpiece_event(struct snd_soc_dapm_widget *w,
322 struct snd_kcontrol *control, int event)
323{
324 struct snd_soc_codec *codec = w->codec;
325 u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
326
327 switch (event) {
328 case SND_SOC_DAPM_PRE_PMU:
329 reg |= WM8993_HPOUT2_IN_ENA;
330 snd_soc_write(codec, WM8993_ANTIPOP1, reg);
331 udelay(50);
332 break;
333
334 case SND_SOC_DAPM_POST_PMD:
335 snd_soc_write(codec, WM8993_ANTIPOP1, reg);
336 break;
337
338 default:
339 BUG();
340 break;
341 }
342
343 return 0;
344}
345
346static const struct snd_kcontrol_new in1l_pga[] = {
347SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
348SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
349};
350
351static const struct snd_kcontrol_new in1r_pga[] = {
352SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
353SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
354};
355
356static const struct snd_kcontrol_new in2l_pga[] = {
357SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
358SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
359};
360
361static const struct snd_kcontrol_new in2r_pga[] = {
362SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
363SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
364};
365
366static const struct snd_kcontrol_new mixinl[] = {
367SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
368SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
369};
370
371static const struct snd_kcontrol_new mixinr[] = {
372SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
373SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
374};
375
376static const struct snd_kcontrol_new left_output_mixer[] = {
377SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
378SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
379SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
380SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
381SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
382SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
383SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
384SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
385};
386
387static const struct snd_kcontrol_new right_output_mixer[] = {
388SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
389SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
390SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
391SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
392SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
393SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
394SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
395SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
396};
397
398static const struct snd_kcontrol_new earpiece_mixer[] = {
399SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
400SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
401SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
402};
403
404static const struct snd_kcontrol_new left_speaker_boost[] = {
405SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
406SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
407SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
408};
409
410static const struct snd_kcontrol_new right_speaker_boost[] = {
411SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
412SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
413SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
414};
415
416static const struct snd_kcontrol_new line1_mix[] = {
417SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
418SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
419SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
420};
421
422static const struct snd_kcontrol_new line1n_mix[] = {
423SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
424SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
425};
426
427static const struct snd_kcontrol_new line1p_mix[] = {
428SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
429};
430
431static const struct snd_kcontrol_new line2_mix[] = {
432SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
433SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
434SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
435};
436
437static const struct snd_kcontrol_new line2n_mix[] = {
438SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
439SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
440};
441
442static const struct snd_kcontrol_new line2p_mix[] = {
443SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
444};
445
446static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
447SND_SOC_DAPM_INPUT("IN1LN"),
448SND_SOC_DAPM_INPUT("IN1LP"),
449SND_SOC_DAPM_INPUT("IN2LN"),
450SND_SOC_DAPM_INPUT("IN2LP/VXRN"),
451SND_SOC_DAPM_INPUT("IN1RN"),
452SND_SOC_DAPM_INPUT("IN1RP"),
453SND_SOC_DAPM_INPUT("IN2RN"),
454SND_SOC_DAPM_INPUT("IN2RP/VXRP"),
455
456SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
457SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
458
459SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
460 in1l_pga, ARRAY_SIZE(in1l_pga)),
461SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
462 in1r_pga, ARRAY_SIZE(in1r_pga)),
463
464SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
465 in2l_pga, ARRAY_SIZE(in2l_pga)),
466SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
467 in2r_pga, ARRAY_SIZE(in2r_pga)),
468
469/* Dummy widgets to represent differential paths */
470SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
471
472SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
473 mixinl, ARRAY_SIZE(mixinl)),
474SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
475 mixinr, ARRAY_SIZE(mixinr)),
476
477SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
478SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
479
480SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
481SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
482
483SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
484 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
485SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
486 right_output_mixer, ARRAY_SIZE(right_output_mixer)),
487
488SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
489SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
490
491SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
492 NULL, 0,
493 hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
494
495SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
496 earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
497SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
498 NULL, 0, earpiece_event,
499 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
500
501SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
502 left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
503SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
504 right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
505
506SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
507 NULL, 0),
508SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
509 NULL, 0),
510
511SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
512 line1_mix, ARRAY_SIZE(line1_mix)),
513SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
514 line2_mix, ARRAY_SIZE(line2_mix)),
515
516SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
517 line1n_mix, ARRAY_SIZE(line1n_mix)),
518SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
519 line1p_mix, ARRAY_SIZE(line1p_mix)),
520SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
521 line2n_mix, ARRAY_SIZE(line2n_mix)),
522SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
523 line2p_mix, ARRAY_SIZE(line2p_mix)),
524
525SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
526 NULL, 0),
527SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
528 NULL, 0),
529SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
530 NULL, 0),
531SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
532 NULL, 0),
533
534SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
535SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
536SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
537SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
538SND_SOC_DAPM_OUTPUT("HPOUT1L"),
539SND_SOC_DAPM_OUTPUT("HPOUT1R"),
540SND_SOC_DAPM_OUTPUT("HPOUT2P"),
541SND_SOC_DAPM_OUTPUT("HPOUT2N"),
542SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
543SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
544SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
545SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
546};
547
548static const struct snd_soc_dapm_route analogue_routes[] = {
549 { "IN1L PGA", "IN1LP Switch", "IN1LP" },
550 { "IN1L PGA", "IN1LN Switch", "IN1LN" },
551
552 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
553 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
554
555 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" },
556 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
557
558 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" },
559 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
560
561 { "Direct Voice", NULL, "IN2LP/VXRN" },
562 { "Direct Voice", NULL, "IN2RP/VXRP" },
563
564 { "MIXINL", "IN1L Switch", "IN1L PGA" },
565 { "MIXINL", "IN2L Switch", "IN2L PGA" },
566 { "MIXINL", NULL, "Direct Voice" },
567 { "MIXINL", NULL, "IN1LP" },
568 { "MIXINL", NULL, "Left Output Mixer" },
569
570 { "MIXINR", "IN1R Switch", "IN1R PGA" },
571 { "MIXINR", "IN2R Switch", "IN2R PGA" },
572 { "MIXINR", NULL, "Direct Voice" },
573 { "MIXINR", NULL, "IN1RP" },
574 { "MIXINR", NULL, "Right Output Mixer" },
575
576 { "ADCL", NULL, "MIXINL" },
577 { "ADCR", NULL, "MIXINR" },
578
579 { "Left Output Mixer", "Left Input Switch", "MIXINL" },
580 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
581 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
582 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
583 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" },
584 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
585 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
586
587 { "Right Output Mixer", "Left Input Switch", "MIXINL" },
588 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
589 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
590 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
591 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" },
592 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
593 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
594
595 { "Left Output PGA", NULL, "Left Output Mixer" },
596 { "Left Output PGA", NULL, "TOCLK" },
597
598 { "Right Output PGA", NULL, "Right Output Mixer" },
599 { "Right Output PGA", NULL, "TOCLK" },
600
601 { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
602 { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
603 { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
604
605 { "Earpiece Driver", NULL, "Earpiece Mixer" },
606 { "HPOUT2N", NULL, "Earpiece Driver" },
607 { "HPOUT2P", NULL, "Earpiece Driver" },
608
609 { "SPKL", "Input Switch", "MIXINL" },
610 { "SPKL", "IN1LP Switch", "IN1LP" },
611 { "SPKL", "Output Switch", "Left Output Mixer" },
612 { "SPKL", NULL, "TOCLK" },
613
614 { "SPKR", "Input Switch", "MIXINR" },
615 { "SPKR", "IN1RP Switch", "IN1RP" },
616 { "SPKR", "Output Switch", "Right Output Mixer" },
617 { "SPKR", NULL, "TOCLK" },
618
619 { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
620 { "SPKL Boost", "SPKL Switch", "SPKL" },
621 { "SPKL Boost", "SPKR Switch", "SPKR" },
622
623 { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
624 { "SPKR Boost", "SPKR Switch", "SPKR" },
625 { "SPKR Boost", "SPKL Switch", "SPKL" },
626
627 { "SPKL Driver", NULL, "SPKL Boost" },
628 { "SPKL Driver", NULL, "CLK_SYS" },
629
630 { "SPKR Driver", NULL, "SPKR Boost" },
631 { "SPKR Driver", NULL, "CLK_SYS" },
632
633 { "SPKOUTLP", NULL, "SPKL Driver" },
634 { "SPKOUTLN", NULL, "SPKL Driver" },
635 { "SPKOUTRP", NULL, "SPKR Driver" },
636 { "SPKOUTRN", NULL, "SPKR Driver" },
637
638 { "Left Headphone Mux", "Mixer", "Left Output Mixer" },
639 { "Right Headphone Mux", "Mixer", "Right Output Mixer" },
640
641 { "Headphone PGA", NULL, "Left Headphone Mux" },
642 { "Headphone PGA", NULL, "Right Headphone Mux" },
643 { "Headphone PGA", NULL, "CLK_SYS" },
644
645 { "HPOUT1L", NULL, "Headphone PGA" },
646 { "HPOUT1R", NULL, "Headphone PGA" },
647
648 { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
649 { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
650 { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
651 { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
652};
653
654static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
655 { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
656 { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
657 { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
658
659 { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
660 { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
661};
662
663static const struct snd_soc_dapm_route lineout1_se_routes[] = {
664 { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
665 { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
666
667 { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
668
669 { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
670 { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
671};
672
673static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
674 { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
675 { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
676 { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
677
678 { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
679 { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
680};
681
682static const struct snd_soc_dapm_route lineout2_se_routes[] = {
683 { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
684 { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
685
686 { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
687
688 { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
689 { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
690};
691
692int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
693{
694 /* Latch volume update bits & default ZC on */
695 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
696 WM8993_IN1_VU, WM8993_IN1_VU);
697 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
698 WM8993_IN1_VU, WM8993_IN1_VU);
699 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
700 WM8993_IN2_VU, WM8993_IN2_VU);
701 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
702 WM8993_IN2_VU, WM8993_IN2_VU);
703
704 snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
705 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
706
707 snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
708 WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
709 snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
710 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
711 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
712
713 snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
714 WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
715 snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
716 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
717 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
718
719 snd_soc_add_controls(codec, analogue_snd_controls,
720 ARRAY_SIZE(analogue_snd_controls));
721
722 snd_soc_dapm_new_controls(codec, analogue_dapm_widgets,
723 ARRAY_SIZE(analogue_dapm_widgets));
724 return 0;
725}
726EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
727
728int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
729 int lineout1_diff, int lineout2_diff)
730{
731 snd_soc_dapm_add_routes(codec, analogue_routes,
732 ARRAY_SIZE(analogue_routes));
733
734 if (lineout1_diff)
735 snd_soc_dapm_add_routes(codec,
736 lineout1_diff_routes,
737 ARRAY_SIZE(lineout1_diff_routes));
738 else
739 snd_soc_dapm_add_routes(codec,
740 lineout1_se_routes,
741 ARRAY_SIZE(lineout1_se_routes));
742
743 if (lineout2_diff)
744 snd_soc_dapm_add_routes(codec,
745 lineout2_diff_routes,
746 ARRAY_SIZE(lineout2_diff_routes));
747 else
748 snd_soc_dapm_add_routes(codec,
749 lineout2_se_routes,
750 ARRAY_SIZE(lineout2_se_routes));
751
752 return 0;
753}
754EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
755
756MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
757MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
758MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
new file mode 100644
index 000000000000..ec09cb6a2939
--- /dev/null
+++ b/sound/soc/codecs/wm_hubs.h
@@ -0,0 +1,24 @@
1/*
2 * wm_hubs.h -- WM899x common code
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#ifndef _WM_HUBS_H
15#define _WM_HUBS_H
16
17struct snd_soc_codec;
18
19extern const unsigned int wm_hubs_spkmix_tlv[];
20
21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int);
23
24#endif