aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c138
-rw-r--r--sound/soc/blackfin/Kconfig23
-rw-r--r--sound/soc/blackfin/Makefile6
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c10
-rw-r--r--sound/soc/blackfin/bf5xx-ad1938.c142
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c16
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c16
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c330
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.h21
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c343
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h14
-rw-r--r--sound/soc/codecs/Kconfig28
-rw-r--r--sound/soc/codecs/Makefile18
-rw-r--r--sound/soc/codecs/ad1938.c668
-rw-r--r--sound/soc/codecs/ad1938.h100
-rw-r--r--sound/soc/codecs/ak4535.c16
-rw-r--r--sound/soc/codecs/cs4270.c27
-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.c3
-rw-r--r--sound/soc/codecs/stac9766.c4
-rw-r--r--sound/soc/codecs/twl4030.c105
-rw-r--r--sound/soc/codecs/twl4030.h2
-rw-r--r--sound/soc/codecs/uda1380.c313
-rw-r--r--sound/soc/codecs/uda1380.h8
-rw-r--r--sound/soc/codecs/wm8350.c40
-rw-r--r--sound/soc/codecs/wm8400.c26
-rw-r--r--sound/soc/codecs/wm8510.c1
-rw-r--r--sound/soc/codecs/wm8523.c755
-rw-r--r--sound/soc/codecs/wm8523.h160
-rw-r--r--sound/soc/codecs/wm8580.c55
-rw-r--r--sound/soc/codecs/wm8731.c74
-rw-r--r--sound/soc/codecs/wm8753.c35
-rw-r--r--sound/soc/codecs/wm8776.c781
-rw-r--r--sound/soc/codecs/wm8776.h51
-rw-r--r--sound/soc/codecs/wm8900.c30
-rw-r--r--sound/soc/codecs/wm8903.c27
-rw-r--r--sound/soc/codecs/wm8940.c17
-rw-r--r--sound/soc/codecs/wm8960.c33
-rw-r--r--sound/soc/codecs/wm8961.c1326
-rw-r--r--sound/soc/codecs/wm8961.h866
-rw-r--r--sound/soc/codecs/wm8988.c42
-rw-r--r--sound/soc/codecs/wm8993.c2206
-rw-r--r--sound/soc/codecs/wm8993.h2132
-rw-r--r--sound/soc/codecs/wm9081.c25
-rw-r--r--sound/soc/davinci/Kconfig13
-rw-r--r--sound/soc/davinci/Makefile3
-rw-r--r--sound/soc/davinci/davinci-evm.c102
-rw-r--r--sound/soc/davinci/davinci-i2s.c339
-rw-r--r--sound/soc/davinci/davinci-mcasp.c874
-rw-r--r--sound/soc/davinci/davinci-mcasp.h55
-rw-r--r--sound/soc/davinci/davinci-pcm.c6
-rw-r--r--sound/soc/davinci/davinci-pcm.h18
-rw-r--r--sound/soc/fsl/mpc5200_dma.c17
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c3
-rw-r--r--sound/soc/omap/Kconfig15
-rw-r--r--sound/soc/omap/Makefile4
-rw-r--r--sound/soc/omap/ams-delta.c646
-rw-r--r--sound/soc/omap/omap-pcm.c2
-rw-r--r--sound/soc/omap/sdp3430.c11
-rw-r--r--sound/soc/omap/zoom2.c314
-rw-r--r--sound/soc/pxa/magician.c54
-rw-r--r--sound/soc/pxa/palm27x.c204
-rw-r--r--sound/soc/pxa/pxa-ssp.c50
-rw-r--r--sound/soc/s3c24xx/Kconfig13
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c498
-rw-r--r--sound/soc/soc-core.c131
-rw-r--r--sound/soc/soc-dapm.c355
-rw-r--r--sound/soc/soc-jack.c24
-rw-r--r--sound/soc/txx9/txx9aclc.c10
74 files changed, 14787 insertions, 883 deletions
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 173a239a541c..130b12118d4f 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -56,30 +56,14 @@
56 56
57#define MCLK_RATE 12000000 57#define MCLK_RATE 12000000
58 58
59static struct clk *mclk; 59/*
60 60 * As shipped the board does not have inputs. However, it is relatively
61static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) 61 * straightforward to modify the board to hook them up so support is left
62{ 62 * in the driver.
63 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 63 */
64 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 64#undef ENABLE_MIC_INPUT
65 int ret;
66
67 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
68 MCLK_RATE, SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 clk_disable(mclk);
71 return ret;
72 }
73
74 return 0;
75}
76
77static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
78{
79 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
80 65
81 dev_dbg(rtd->socdev->dev, "shutdown"); 66static struct clk *mclk;
82}
83 67
84static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, 68static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
85 struct snd_pcm_hw_params *params) 69 struct snd_pcm_hw_params *params)
@@ -87,102 +71,17 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
87 struct snd_soc_pcm_runtime *rtd = substream->private_data; 71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
88 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 72 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
89 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 73 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
90 struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
91 struct ssc_device *ssc = ssc_p->ssc;
92 int ret; 74 int ret;
93 75
94 unsigned int rate;
95 int cmr_div, period;
96
97 if (ssc == NULL) {
98 printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
99 return -EINVAL;
100 }
101
102 /* set codec DAI configuration */ 76 /* set codec DAI configuration */
103 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 77 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
104 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 78 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
105 if (ret < 0) 79 if (ret < 0)
106 return ret; 80 return ret;
107 81
108 /* set cpu DAI configuration */ 82 /* set cpu DAI configuration */
109 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 83 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
110 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 84 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
111 if (ret < 0)
112 return ret;
113
114 /*
115 * The SSC clock dividers depend on the sample rate. The CMR.DIV
116 * field divides the system master clock MCK to drive the SSC TK
117 * signal which provides the codec BCLK. The TCMR.PERIOD and
118 * RCMR.PERIOD fields further divide the BCLK signal to drive
119 * the SSC TF and RF signals which provide the codec DACLRC and
120 * ADCLRC clocks.
121 *
122 * The dividers were determined through trial and error, where a
123 * CMR.DIV value is chosen such that the resulting BCLK value is
124 * divisible, or almost divisible, by (2 * sample rate), and then
125 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
126 */
127 rate = params_rate(params);
128
129 switch (rate) {
130 case 8000:
131 cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
132 period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
133 break;
134 case 11025:
135 cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
136 period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
137 break;
138 case 16000:
139 cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
140 period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
141 break;
142 case 22050:
143 cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
144 period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
145 break;
146 case 32000:
147 cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
148 period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
149 break;
150 case 44100:
151 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
152 period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
153 break;
154 case 48000:
155 cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
156 period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
157 break;
158 case 88200:
159 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
160 period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
161 break;
162 case 96000:
163 cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
164 period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
165 break;
166 default:
167 printk(KERN_WARNING "unsupported rate %d"
168 " on at91sam9g20ek board\n", rate);
169 return -EINVAL;
170 }
171
172 /* set the MCK divider for BCLK */
173 ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
174 if (ret < 0)
175 return ret;
176
177 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
178 /* set the BCLK divider for DACLRC */
179 ret = snd_soc_dai_set_clkdiv(cpu_dai,
180 ATMEL_SSC_TCMR_PERIOD, period);
181 } else {
182 /* set the BCLK divider for ADCLRC */
183 ret = snd_soc_dai_set_clkdiv(cpu_dai,
184 ATMEL_SSC_RCMR_PERIOD, period);
185 }
186 if (ret < 0) 85 if (ret < 0)
187 return ret; 86 return ret;
188 87
@@ -190,9 +89,7 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
190} 89}
191 90
192static struct snd_soc_ops at91sam9g20ek_ops = { 91static struct snd_soc_ops at91sam9g20ek_ops = {
193 .startup = at91sam9g20ek_startup,
194 .hw_params = at91sam9g20ek_hw_params, 92 .hw_params = at91sam9g20ek_hw_params,
195 .shutdown = at91sam9g20ek_shutdown,
196}; 93};
197 94
198static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, 95static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
@@ -241,10 +138,20 @@ static const struct snd_soc_dapm_route intercon[] = {
241 */ 138 */
242static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) 139static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
243{ 140{
141 struct snd_soc_dai *codec_dai = &codec->dai[0];
142 int ret;
143
244 printk(KERN_DEBUG 144 printk(KERN_DEBUG
245 "at91sam9g20ek_wm8731 " 145 "at91sam9g20ek_wm8731 "
246 ": at91sam9g20ek_wm8731_init() called\n"); 146 ": at91sam9g20ek_wm8731_init() called\n");
247 147
148 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
149 MCLK_RATE, SND_SOC_CLOCK_IN);
150 if (ret < 0) {
151 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
152 return ret;
153 }
154
248 /* Add specific widgets */ 155 /* Add specific widgets */
249 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, 156 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
250 ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); 157 ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
@@ -255,8 +162,13 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
255 snd_soc_dapm_nc_pin(codec, "RLINEIN"); 162 snd_soc_dapm_nc_pin(codec, "RLINEIN");
256 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 163 snd_soc_dapm_nc_pin(codec, "LLINEIN");
257 164
258 /* always connected */ 165#ifdef ENABLE_MIC_INPUT
259 snd_soc_dapm_enable_pin(codec, "Int Mic"); 166 snd_soc_dapm_enable_pin(codec, "Int Mic");
167#else
168 snd_soc_dapm_nc_pin(codec, "Int Mic");
169#endif
170
171 /* always connected */
260 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 172 snd_soc_dapm_enable_pin(codec, "Ext Spk");
261 173
262 snd_soc_dapm_sync(codec); 174 snd_soc_dapm_sync(codec);
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 811596f4c092..8a4de4de30f2 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -7,6 +7,15 @@ config SND_BF5XX_I2S
7 mode (supports single stereo In/Out). 7 mode (supports single stereo In/Out).
8 You will also need to select the audio interfaces to support below. 8 You will also need to select the audio interfaces to support below.
9 9
10config SND_BF5XX_TDM
11 tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip"
12 depends on (BLACKFIN && SND_SOC)
13 help
14 Say Y or M if you want to add support for codecs attached to
15 the Blackfin SPORT (synchronous serial ports) interface in TDM
16 mode.
17 You will also need to select the audio interfaces to support below.
18
10config SND_BF5XX_SOC_SSM2602 19config SND_BF5XX_SOC_SSM2602
11 tristate "SoC SSM2602 Audio support for BF52x ezkit" 20 tristate "SoC SSM2602 Audio support for BF52x ezkit"
12 depends on SND_BF5XX_I2S 21 depends on SND_BF5XX_I2S
@@ -69,6 +78,10 @@ config SND_BF5XX_SOC_I2S
69 tristate 78 tristate
70 select SND_BF5XX_SOC_SPORT 79 select SND_BF5XX_SOC_SPORT
71 80
81config SND_BF5XX_SOC_TDM
82 tristate
83 select SND_BF5XX_SOC_SPORT
84
72config SND_BF5XX_SOC_AC97 85config SND_BF5XX_SOC_AC97
73 tristate 86 tristate
74 select AC97_BUS 87 select AC97_BUS
@@ -83,9 +96,17 @@ config SND_BF5XX_SOC_AD1980
83 help 96 help
84 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. 97 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
85 98
99config SND_BF5XX_SOC_AD1938
100 tristate "SoC AD1938 Audio support for Blackfin"
101 depends on SND_BF5XX_TDM
102 select SND_BF5XX_SOC_TDM
103 select SND_SOC_AD1938
104 help
105 Say Y if you want to add support for AD1938 codec on Blackfin.
106
86config SND_BF5XX_SPORT_NUM 107config SND_BF5XX_SPORT_NUM
87 int "Set a SPORT for Sound chip" 108 int "Set a SPORT for Sound chip"
88 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) 109 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM)
89 range 0 3 if BF54x 110 range 0 3 if BF54x
90 range 0 1 if !BF54x 111 range 0 1 if !BF54x
91 default 0 112 default 0
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 97bb37a6359c..f4d760741fab 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -1,21 +1,27 @@
1# Blackfin Platform Support 1# Blackfin Platform Support
2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o 2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o 3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
4snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
4snd-soc-bf5xx-sport-objs := bf5xx-sport.o 5snd-soc-bf5xx-sport-objs := bf5xx-sport.o
5snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o 6snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
6snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o 7snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
8snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
7 9
8obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o 10obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
9obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o 11obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
12obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
10obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o 13obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
11obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o 14obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
12obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o 15obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
16obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
13 17
14# Blackfin Machine Support 18# Blackfin Machine Support
15snd-ad1980-objs := bf5xx-ad1980.o 19snd-ad1980-objs := bf5xx-ad1980.o
16snd-ssm2602-objs := bf5xx-ssm2602.o 20snd-ssm2602-objs := bf5xx-ssm2602.o
17snd-ad73311-objs := bf5xx-ad73311.o 21snd-ad73311-objs := bf5xx-ad73311.o
22snd-ad1938-objs := bf5xx-ad1938.o
18 23
19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 24obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 25obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
21obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o 26obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
27obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index b1ed423fabd5..2758b9017a7f 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -277,28 +277,24 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
277 if (!dai->active) 277 if (!dai->active)
278 return 0; 278 return 0;
279 279
280 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); 280 ret = sport_set_multichannel(sport, 16, 0x1F, 1);
281 if (ret) { 281 if (ret) {
282 pr_err("SPORT is busy!\n"); 282 pr_err("SPORT is busy!\n");
283 return -EBUSY; 283 return -EBUSY;
284 } 284 }
285 285
286 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); 286 ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1));
287 if (ret) { 287 if (ret) {
288 pr_err("SPORT is busy!\n"); 288 pr_err("SPORT is busy!\n");
289 return -EBUSY; 289 return -EBUSY;
290 } 290 }
291 291
292 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); 292 ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1));
293 if (ret) { 293 if (ret) {
294 pr_err("SPORT is busy!\n"); 294 pr_err("SPORT is busy!\n");
295 return -EBUSY; 295 return -EBUSY;
296 } 296 }
297 297
298 if (dai->capture.active)
299 sport_rx_start(sport);
300 if (dai->playback.active)
301 sport_tx_start(sport);
302 return 0; 298 return 0;
303} 299}
304 300
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
new file mode 100644
index 000000000000..08269e91810c
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad1938.c
@@ -0,0 +1,142 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Thur June 4 2009
6 * Description: Board driver for ad1938 sound chip
7 *
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/
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 as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see the file COPYING, or write
22 * to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/device.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/pcm_params.h>
34
35#include <asm/blackfin.h>
36#include <asm/cacheflush.h>
37#include <asm/irq.h>
38#include <asm/dma.h>
39#include <asm/portmux.h>
40
41#include "../codecs/ad1938.h"
42#include "bf5xx-sport.h"
43
44#include "bf5xx-tdm-pcm.h"
45#include "bf5xx-tdm.h"
46
47static struct snd_soc_card bf5xx_ad1938;
48
49static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
53
54 cpu_dai->private_data = sport_handle;
55 return 0;
56}
57
58static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
59 struct snd_pcm_hw_params *params)
60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 int ret = 0;
65 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
67 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
68 if (ret < 0)
69 return ret;
70
71 /* set codec DAI configuration */
72 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
73 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
74 if (ret < 0)
75 return ret;
76
77 /* set codec DAI slots, 8 channels, all channels are enabled */
78 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8);
79 if (ret < 0)
80 return ret;
81
82 return 0;
83}
84
85static struct snd_soc_ops bf5xx_ad1938_ops = {
86 .startup = bf5xx_ad1938_startup,
87 .hw_params = bf5xx_ad1938_hw_params,
88};
89
90static struct snd_soc_dai_link bf5xx_ad1938_dai = {
91 .name = "ad1938",
92 .stream_name = "AD1938",
93 .cpu_dai = &bf5xx_tdm_dai,
94 .codec_dai = &ad1938_dai,
95 .ops = &bf5xx_ad1938_ops,
96};
97
98static struct snd_soc_card bf5xx_ad1938 = {
99 .name = "bf5xx_ad1938",
100 .platform = &bf5xx_tdm_soc_platform,
101 .dai_link = &bf5xx_ad1938_dai,
102 .num_links = 1,
103};
104
105static struct snd_soc_device bf5xx_ad1938_snd_devdata = {
106 .card = &bf5xx_ad1938,
107 .codec_dev = &soc_codec_dev_ad1938,
108};
109
110static struct platform_device *bfxx_ad1938_snd_device;
111
112static int __init bf5xx_ad1938_init(void)
113{
114 int ret;
115
116 bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!bfxx_ad1938_snd_device)
118 return -ENOMEM;
119
120 platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata);
121 bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev;
122 ret = platform_device_add(bfxx_ad1938_snd_device);
123
124 if (ret)
125 platform_device_put(bfxx_ad1938_snd_device);
126
127 return ret;
128}
129
130static void __exit bf5xx_ad1938_exit(void)
131{
132 platform_device_unregister(bfxx_ad1938_snd_device);
133}
134
135module_init(bf5xx_ad1938_init);
136module_exit(bf5xx_ad1938_exit);
137
138/* Module information */
139MODULE_AUTHOR("Barry Song");
140MODULE_DESCRIPTION("ALSA SoC AD1938 board driver");
141MODULE_LICENSE("GPL");
142
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index edfbdc024e66..9825b71d0e28 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
203 .codec_dev = &soc_codec_dev_ad73311, 203 .codec_dev = &soc_codec_dev_ad73311,
204}; 204};
205 205
206static struct platform_device *bf52x_ad73311_snd_device; 206static struct platform_device *bf5xx_ad73311_snd_device;
207 207
208static int __init bf5xx_ad73311_init(void) 208static int __init bf5xx_ad73311_init(void)
209{ 209{
210 int ret; 210 int ret;
211 211
212 pr_debug("%s enter\n", __func__); 212 pr_debug("%s enter\n", __func__);
213 bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1); 213 bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
214 if (!bf52x_ad73311_snd_device) 214 if (!bf5xx_ad73311_snd_device)
215 return -ENOMEM; 215 return -ENOMEM;
216 216
217 platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); 217 platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
218 bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev; 218 bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
219 ret = platform_device_add(bf52x_ad73311_snd_device); 219 ret = platform_device_add(bf5xx_ad73311_snd_device);
220 220
221 if (ret) 221 if (ret)
222 platform_device_put(bf52x_ad73311_snd_device); 222 platform_device_put(bf5xx_ad73311_snd_device);
223 223
224 return ret; 224 return ret;
225} 225}
@@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void)
227static void __exit bf5xx_ad73311_exit(void) 227static void __exit bf5xx_ad73311_exit(void)
228{ 228{
229 pr_debug("%s enter\n", __func__); 229 pr_debug("%s enter\n", __func__);
230 platform_device_unregister(bf52x_ad73311_snd_device); 230 platform_device_unregister(bf5xx_ad73311_snd_device);
231} 231}
232 232
233module_init(bf5xx_ad73311_init); 233module_init(bf5xx_ad73311_init);
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index af06904bab0f..876abade27e1 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -259,22 +259,18 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
259 if (!dai->active) 259 if (!dai->active)
260 return 0; 260 return 0;
261 261
262 ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0); 262 ret = sport_config_rx(sport, RFSR | RCKFE, RSFSE|0x1f, 0, 0);
263 if (ret) { 263 if (ret) {
264 pr_err("SPORT is busy!\n"); 264 pr_err("SPORT is busy!\n");
265 return -EBUSY; 265 return -EBUSY;
266 } 266 }
267 267
268 ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0); 268 ret = sport_config_tx(sport, TFSR | TCKFE, TSFSE|0x1f, 0, 0);
269 if (ret) { 269 if (ret) {
270 pr_err("SPORT is busy!\n"); 270 pr_err("SPORT is busy!\n");
271 return -EBUSY; 271 return -EBUSY;
272 } 272 }
273 273
274 if (dai->capture.active)
275 sport_rx_start(sport);
276 if (dai->playback.active)
277 sport_tx_start(sport);
278 return 0; 274 return 0;
279} 275}
280 276
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index bc0cdded7116..3a00fa4dbe6d 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
148 .codec_data = &bf5xx_ssm2602_setup, 148 .codec_data = &bf5xx_ssm2602_setup,
149}; 149};
150 150
151static struct platform_device *bf52x_ssm2602_snd_device; 151static struct platform_device *bf5xx_ssm2602_snd_device;
152 152
153static int __init bf5xx_ssm2602_init(void) 153static int __init bf5xx_ssm2602_init(void)
154{ 154{
155 int ret; 155 int ret;
156 156
157 pr_debug("%s enter\n", __func__); 157 pr_debug("%s enter\n", __func__);
158 bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); 158 bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
159 if (!bf52x_ssm2602_snd_device) 159 if (!bf5xx_ssm2602_snd_device)
160 return -ENOMEM; 160 return -ENOMEM;
161 161
162 platform_set_drvdata(bf52x_ssm2602_snd_device, 162 platform_set_drvdata(bf5xx_ssm2602_snd_device,
163 &bf5xx_ssm2602_snd_devdata); 163 &bf5xx_ssm2602_snd_devdata);
164 bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev; 164 bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
165 ret = platform_device_add(bf52x_ssm2602_snd_device); 165 ret = platform_device_add(bf5xx_ssm2602_snd_device);
166 166
167 if (ret) 167 if (ret)
168 platform_device_put(bf52x_ssm2602_snd_device); 168 platform_device_put(bf5xx_ssm2602_snd_device);
169 169
170 return ret; 170 return ret;
171} 171}
@@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void)
173static void __exit bf5xx_ssm2602_exit(void) 173static void __exit bf5xx_ssm2602_exit(void)
174{ 174{
175 pr_debug("%s enter\n", __func__); 175 pr_debug("%s enter\n", __func__);
176 platform_device_unregister(bf52x_ssm2602_snd_device); 176 platform_device_unregister(bf5xx_ssm2602_snd_device);
177} 177}
178 178
179module_init(bf5xx_ssm2602_init); 179module_init(bf5xx_ssm2602_init);
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
new file mode 100644
index 000000000000..ccb5e823bd18
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -0,0 +1,330 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm-pcm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Tue June 06 2009
6 * Description: DMA driver for tdm codec
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/module.h>
30#include <linux/init.h>
31#include <linux/platform_device.h>
32#include <linux/slab.h>
33#include <linux/dma-mapping.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include <asm/dma.h>
41
42#include "bf5xx-tdm-pcm.h"
43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h"
45
46#define PCM_BUFFER_MAX 0x10000
47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32
50
51static void bf5xx_dma_irq(void *data)
52{
53 struct snd_pcm_substream *pcm = data;
54 snd_pcm_period_elapsed(pcm);
55}
56
57static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
58 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
59 SNDRV_PCM_INFO_RESUME),
60 .formats = SNDRV_PCM_FMTBIT_S32_LE,
61 .rates = SNDRV_PCM_RATE_48000,
62 .channels_min = 2,
63 .channels_max = 8,
64 .buffer_bytes_max = PCM_BUFFER_MAX,
65 .period_bytes_min = FRAGMENT_SIZE_MIN,
66 .period_bytes_max = PCM_BUFFER_MAX/2,
67 .periods_min = FRAGMENTS_MIN,
68 .periods_max = FRAGMENTS_MAX,
69};
70
71static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
72 struct snd_pcm_hw_params *params)
73{
74 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
75 snd_pcm_lib_malloc_pages(substream, size * 4);
76
77 return 0;
78}
79
80static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
81{
82 snd_pcm_lib_free_pages(substream);
83
84 return 0;
85}
86
87static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
88{
89 struct snd_pcm_runtime *runtime = substream->runtime;
90 struct sport_device *sport = runtime->private_data;
91 int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size);
92
93 fragsize_bytes /= runtime->channels;
94 /* inflate the fragsize to match the dma width of SPORT */
95 fragsize_bytes *= 8;
96
97 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
98 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
99 sport_config_tx_dma(sport, runtime->dma_area,
100 runtime->periods, fragsize_bytes);
101 } else {
102 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
103 sport_config_rx_dma(sport, runtime->dma_area,
104 runtime->periods, fragsize_bytes);
105 }
106
107 return 0;
108}
109
110static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
111{
112 struct snd_pcm_runtime *runtime = substream->runtime;
113 struct sport_device *sport = runtime->private_data;
114 int ret = 0;
115
116 switch (cmd) {
117 case SNDRV_PCM_TRIGGER_START:
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
119 sport_tx_start(sport);
120 else
121 sport_rx_start(sport);
122 break;
123 case SNDRV_PCM_TRIGGER_STOP:
124 case SNDRV_PCM_TRIGGER_SUSPEND:
125 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
127 sport_tx_stop(sport);
128 else
129 sport_rx_stop(sport);
130 break;
131 default:
132 ret = -EINVAL;
133 }
134
135 return ret;
136}
137
138static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
139{
140 struct snd_pcm_runtime *runtime = substream->runtime;
141 struct sport_device *sport = runtime->private_data;
142 unsigned int diff;
143 snd_pcm_uframes_t frames;
144
145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
146 diff = sport_curr_offset_tx(sport);
147 frames = diff / (8*4); /* 32 bytes per frame */
148 } else {
149 diff = sport_curr_offset_rx(sport);
150 frames = diff / (8*4);
151 }
152 return frames;
153}
154
155static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
156{
157 struct snd_pcm_runtime *runtime = substream->runtime;
158 int ret = 0;
159
160 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
161
162 ret = snd_pcm_hw_constraint_integer(runtime,
163 SNDRV_PCM_HW_PARAM_PERIODS);
164 if (ret < 0)
165 goto out;
166
167 if (sport_handle != NULL)
168 runtime->private_data = sport_handle;
169 else {
170 pr_err("sport_handle is NULL\n");
171 ret = -ENODEV;
172 }
173out:
174 return ret;
175}
176
177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
179{
180 unsigned int *src;
181 unsigned int *dst;
182 int i;
183
184 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
185 src = buf;
186 dst = (unsigned int *)substream->runtime->dma_area;
187
188 dst += pos * 8;
189 while (count--) {
190 for (i = 0; i < substream->runtime->channels; i++)
191 *(dst + i) = *src++;
192 dst += 8;
193 }
194 } else {
195 src = (unsigned int *)substream->runtime->dma_area;
196 dst = buf;
197
198 src += pos * 8;
199 while (count--) {
200 for (i = 0; i < substream->runtime->channels; i++)
201 *dst++ = *(src+i);
202 src += 8;
203 }
204 }
205
206 return 0;
207}
208
209static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
210 int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
211{
212 unsigned char *buf = substream->runtime->dma_area;
213 buf += pos * 8 * 4;
214 memset(buf, '\0', count * 8 * 4);
215
216 return 0;
217}
218
219
220struct snd_pcm_ops bf5xx_pcm_tdm_ops = {
221 .open = bf5xx_pcm_open,
222 .ioctl = snd_pcm_lib_ioctl,
223 .hw_params = bf5xx_pcm_hw_params,
224 .hw_free = bf5xx_pcm_hw_free,
225 .prepare = bf5xx_pcm_prepare,
226 .trigger = bf5xx_pcm_trigger,
227 .pointer = bf5xx_pcm_pointer,
228 .copy = bf5xx_pcm_copy,
229 .silence = bf5xx_pcm_silence,
230};
231
232static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
233{
234 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
235 struct snd_dma_buffer *buf = &substream->dma_buffer;
236 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
237
238 buf->dev.type = SNDRV_DMA_TYPE_DEV;
239 buf->dev.dev = pcm->card->dev;
240 buf->private_data = NULL;
241 buf->area = dma_alloc_coherent(pcm->card->dev, size * 4,
242 &buf->addr, GFP_KERNEL);
243 if (!buf->area) {
244 pr_err("Failed to allocate dma memory \
245 Please increase uncached DMA memory region\n");
246 return -ENOMEM;
247 }
248 buf->bytes = size;
249
250 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
251 sport_handle->tx_buf = buf->area;
252 else
253 sport_handle->rx_buf = buf->area;
254
255 return 0;
256}
257
258static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
259{
260 struct snd_pcm_substream *substream;
261 struct snd_dma_buffer *buf;
262 int stream;
263
264 for (stream = 0; stream < 2; stream++) {
265 substream = pcm->streams[stream].substream;
266 if (!substream)
267 continue;
268
269 buf = &substream->dma_buffer;
270 if (!buf->area)
271 continue;
272 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
273 buf->area = NULL;
274 }
275 if (sport_handle)
276 sport_done(sport_handle);
277}
278
279static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
280
281static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
282 struct snd_pcm *pcm)
283{
284 int ret = 0;
285
286 if (!card->dev->dma_mask)
287 card->dev->dma_mask = &bf5xx_pcm_dmamask;
288 if (!card->dev->coherent_dma_mask)
289 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
290
291 if (dai->playback.channels_min) {
292 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
293 SNDRV_PCM_STREAM_PLAYBACK);
294 if (ret)
295 goto out;
296 }
297
298 if (dai->capture.channels_min) {
299 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
300 SNDRV_PCM_STREAM_CAPTURE);
301 if (ret)
302 goto out;
303 }
304out:
305 return ret;
306}
307
308struct snd_soc_platform bf5xx_tdm_soc_platform = {
309 .name = "bf5xx-audio",
310 .pcm_ops = &bf5xx_pcm_tdm_ops,
311 .pcm_new = bf5xx_pcm_tdm_new,
312 .pcm_free = bf5xx_pcm_free_dma_buffers,
313};
314EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
315
316static int __init bfin_pcm_tdm_init(void)
317{
318 return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
319}
320module_init(bfin_pcm_tdm_init);
321
322static void __exit bfin_pcm_tdm_exit(void)
323{
324 snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
325}
326module_exit(bfin_pcm_tdm_exit);
327
328MODULE_AUTHOR("Barry Song");
329MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
330MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h
new file mode 100644
index 000000000000..ddc5047df88c
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h
@@ -0,0 +1,21 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2009 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_TDM_PCM_H
12#define _BF5XX_TDM_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18/* platform data */
19extern struct snd_soc_platform bf5xx_tdm_soc_platform;
20
21#endif
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
new file mode 100644
index 000000000000..3096badf09a5
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -0,0 +1,343 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Thurs June 04 2009
6 * Description: Blackfin I2S(TDM) CPU DAI driver
7 * Even though TDM mode can be as part of I2S DAI, but there
8 * are so much difference in configuration and data flow,
9 * it's very ugly to integrate I2S and TDM into a module
10 *
11 * Modified:
12 * Copyright 2009 Analog Devices Inc.
13 *
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see the file COPYING, or write
28 * to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32#include <linux/init.h>
33#include <linux/module.h>
34#include <linux/device.h>
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/initval.h>
39#include <sound/soc.h>
40
41#include <asm/irq.h>
42#include <asm/portmux.h>
43#include <linux/mutex.h>
44#include <linux/gpio.h>
45
46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h"
48
49struct bf5xx_tdm_port {
50 u16 tcr1;
51 u16 rcr1;
52 u16 tcr2;
53 u16 rcr2;
54 int configured;
55};
56
57static struct bf5xx_tdm_port bf5xx_tdm;
58static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
59
60static struct sport_param sport_params[2] = {
61 {
62 .dma_rx_chan = CH_SPORT0_RX,
63 .dma_tx_chan = CH_SPORT0_TX,
64 .err_irq = IRQ_SPORT0_ERROR,
65 .regs = (struct sport_register *)SPORT0_TCR1,
66 },
67 {
68 .dma_rx_chan = CH_SPORT1_RX,
69 .dma_tx_chan = CH_SPORT1_TX,
70 .err_irq = IRQ_SPORT1_ERROR,
71 .regs = (struct sport_register *)SPORT1_TCR1,
72 }
73};
74
75/*
76 * Setting the TFS pin selector for SPORT 0 based on whether the selected
77 * port id F or G. If the port is F then no conflict should exist for the
78 * TFS. When Port G is selected and EMAC then there is a conflict between
79 * the PHY interrupt line and TFS. Current settings prevent the conflict
80 * by ignoring the TFS pin when Port G is selected. This allows both
81 * ssm2602 using Port G and EMAC concurrently.
82 */
83#ifdef CONFIG_BF527_SPORT0_PORTF
84#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
85#else
86#define LOCAL_SPORT0_TFS (0)
87#endif
88
89static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
90 P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
91 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
92 P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
93
94static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
95 unsigned int fmt)
96{
97 int ret = 0;
98
99 /* interface format:support TDM,slave mode */
100 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
101 case SND_SOC_DAIFMT_DSP_A:
102 break;
103 default:
104 printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
105 ret = -EINVAL;
106 break;
107 }
108
109 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
110 case SND_SOC_DAIFMT_CBM_CFM:
111 break;
112 case SND_SOC_DAIFMT_CBS_CFS:
113 case SND_SOC_DAIFMT_CBM_CFS:
114 case SND_SOC_DAIFMT_CBS_CFM:
115 ret = -EINVAL;
116 break;
117 default:
118 printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
119 ret = -EINVAL;
120 break;
121 }
122
123 return ret;
124}
125
126static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream,
127 struct snd_pcm_hw_params *params,
128 struct snd_soc_dai *dai)
129{
130 int ret = 0;
131
132 bf5xx_tdm.tcr2 &= ~0x1f;
133 bf5xx_tdm.rcr2 &= ~0x1f;
134 switch (params_format(params)) {
135 case SNDRV_PCM_FORMAT_S32_LE:
136 bf5xx_tdm.tcr2 |= 31;
137 bf5xx_tdm.rcr2 |= 31;
138 sport_handle->wdsize = 4;
139 break;
140 /* at present, we only support 32bit transfer */
141 default:
142 pr_err("not supported PCM format yet\n");
143 return -EINVAL;
144 break;
145 }
146
147 if (!bf5xx_tdm.configured) {
148 /*
149 * TX and RX are not independent,they are enabled at the
150 * same time, even if only one side is running. So, we
151 * need to configure both of them at the time when the first
152 * stream is opened.
153 *
154 * CPU DAI:slave mode.
155 */
156 ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1,
157 bf5xx_tdm.rcr2, 0, 0);
158 if (ret) {
159 pr_err("SPORT is busy!\n");
160 return -EBUSY;
161 }
162
163 ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1,
164 bf5xx_tdm.tcr2, 0, 0);
165 if (ret) {
166 pr_err("SPORT is busy!\n");
167 return -EBUSY;
168 }
169
170 bf5xx_tdm.configured = 1;
171 }
172
173 return 0;
174}
175
176static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
177 struct snd_soc_dai *dai)
178{
179 /* No active stream, SPORT is allowed to be configured again. */
180 if (!dai->active)
181 bf5xx_tdm.configured = 0;
182}
183
184#ifdef CONFIG_PM
185static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
186{
187 struct sport_device *sport =
188 (struct sport_device *)dai->private_data;
189
190 if (!dai->active)
191 return 0;
192 if (dai->capture.active)
193 sport_rx_stop(sport);
194 if (dai->playback.active)
195 sport_tx_stop(sport);
196 return 0;
197}
198
199static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
200{
201 int ret;
202 struct sport_device *sport =
203 (struct sport_device *)dai->private_data;
204
205 if (!dai->active)
206 return 0;
207
208 ret = sport_set_multichannel(sport, 8, 0xFF, 1);
209 if (ret) {
210 pr_err("SPORT is busy!\n");
211 ret = -EBUSY;
212 }
213
214 ret = sport_config_rx(sport, IRFS, 0x1F, 0, 0);
215 if (ret) {
216 pr_err("SPORT is busy!\n");
217 ret = -EBUSY;
218 }
219
220 ret = sport_config_tx(sport, ITFS, 0x1F, 0, 0);
221 if (ret) {
222 pr_err("SPORT is busy!\n");
223 ret = -EBUSY;
224 }
225
226 return 0;
227}
228
229#else
230#define bf5xx_tdm_suspend NULL
231#define bf5xx_tdm_resume NULL
232#endif
233
234static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
235 .hw_params = bf5xx_tdm_hw_params,
236 .set_fmt = bf5xx_tdm_set_dai_fmt,
237 .shutdown = bf5xx_tdm_shutdown,
238};
239
240struct snd_soc_dai bf5xx_tdm_dai = {
241 .name = "bf5xx-tdm",
242 .id = 0,
243 .suspend = bf5xx_tdm_suspend,
244 .resume = bf5xx_tdm_resume,
245 .playback = {
246 .channels_min = 2,
247 .channels_max = 8,
248 .rates = SNDRV_PCM_RATE_48000,
249 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
250 .capture = {
251 .channels_min = 2,
252 .channels_max = 8,
253 .rates = SNDRV_PCM_RATE_48000,
254 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
255 .ops = &bf5xx_tdm_dai_ops,
256};
257EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
258
259static int __devinit bfin_tdm_probe(struct platform_device *pdev)
260{
261 int ret = 0;
262
263 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
264 pr_err("Requesting Peripherals failed\n");
265 return -EFAULT;
266 }
267
268 /* request DMA for SPORT */
269 sport_handle = sport_init(&sport_params[sport_num], 4, \
270 8 * sizeof(u32), NULL);
271 if (!sport_handle) {
272 peripheral_free_list(&sport_req[sport_num][0]);
273 return -ENODEV;
274 }
275
276 /* SPORT works in TDM mode */
277 ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1);
278 if (ret) {
279 pr_err("SPORT is busy!\n");
280 ret = -EBUSY;
281 goto sport_config_err;
282 }
283
284 ret = sport_config_rx(sport_handle, IRFS, 0x1F, 0, 0);
285 if (ret) {
286 pr_err("SPORT is busy!\n");
287 ret = -EBUSY;
288 goto sport_config_err;
289 }
290
291 ret = sport_config_tx(sport_handle, ITFS, 0x1F, 0, 0);
292 if (ret) {
293 pr_err("SPORT is busy!\n");
294 ret = -EBUSY;
295 goto sport_config_err;
296 }
297
298 ret = snd_soc_register_dai(&bf5xx_tdm_dai);
299 if (ret) {
300 pr_err("Failed to register DAI: %d\n", ret);
301 goto sport_config_err;
302 }
303 return 0;
304
305sport_config_err:
306 peripheral_free_list(&sport_req[sport_num][0]);
307 return ret;
308}
309
310static int __devexit bfin_tdm_remove(struct platform_device *pdev)
311{
312 peripheral_free_list(&sport_req[sport_num][0]);
313 snd_soc_unregister_dai(&bf5xx_tdm_dai);
314
315 return 0;
316}
317
318static struct platform_driver bfin_tdm_driver = {
319 .probe = bfin_tdm_probe,
320 .remove = __devexit_p(bfin_tdm_remove),
321 .driver = {
322 .name = "bfin-tdm",
323 .owner = THIS_MODULE,
324 },
325};
326
327static int __init bfin_tdm_init(void)
328{
329 return platform_driver_register(&bfin_tdm_driver);
330}
331module_init(bfin_tdm_init);
332
333static void __exit bfin_tdm_exit(void)
334{
335 platform_driver_unregister(&bfin_tdm_driver);
336}
337module_exit(bfin_tdm_exit);
338
339/* Module information */
340MODULE_AUTHOR("Barry Song");
341MODULE_DESCRIPTION("TDM driver for ADI Blackfin");
342MODULE_LICENSE("GPL");
343
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
new file mode 100644
index 000000000000..618ec3d90cd4
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -0,0 +1,14 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm.h
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 _BF5XX_TDM_H
10#define _BF5XX_TDM_H
11
12extern struct snd_soc_dai bf5xx_tdm_dai;
13
14#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bbc97fd76648..31a6d2111ed0 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -12,11 +12,13 @@ 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_AD1938 if SPI_MASTER
15 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 16 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
16 select SND_SOC_AD73311 if I2C 17 select SND_SOC_AD73311 if I2C
17 select SND_SOC_AK4104 if SPI_MASTER 18 select SND_SOC_AK4104 if SPI_MASTER
18 select SND_SOC_AK4535 if I2C 19 select SND_SOC_AK4535 if I2C
19 select SND_SOC_CS4270 if I2C 20 select SND_SOC_CS4270 if I2C
21 select SND_SOC_MAX9877 if I2C
20 select SND_SOC_PCM3008 22 select SND_SOC_PCM3008
21 select SND_SOC_SPDIF 23 select SND_SOC_SPDIF
22 select SND_SOC_SSM2602 if I2C 24 select SND_SOC_SSM2602 if I2C
@@ -30,18 +32,22 @@ config SND_SOC_ALL_CODECS
30 select SND_SOC_WM8350 if MFD_WM8350 32 select SND_SOC_WM8350 if MFD_WM8350
31 select SND_SOC_WM8400 if MFD_WM8400 33 select SND_SOC_WM8400 if MFD_WM8400
32 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 34 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
35 select SND_SOC_WM8523 if I2C
33 select SND_SOC_WM8580 if I2C 36 select SND_SOC_WM8580 if I2C
34 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 37 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
35 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 38 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 39 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
37 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 40 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
41 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
38 select SND_SOC_WM8900 if I2C 42 select SND_SOC_WM8900 if I2C
39 select SND_SOC_WM8903 if I2C 43 select SND_SOC_WM8903 if I2C
40 select SND_SOC_WM8940 if I2C 44 select SND_SOC_WM8940 if I2C
41 select SND_SOC_WM8960 if I2C 45 select SND_SOC_WM8960 if I2C
46 select SND_SOC_WM8961 if I2C
42 select SND_SOC_WM8971 if I2C 47 select SND_SOC_WM8971 if I2C
43 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI 48 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
44 select SND_SOC_WM8990 if I2C 49 select SND_SOC_WM8990 if I2C
50 select SND_SOC_WM8993 if I2C
45 select SND_SOC_WM9081 if I2C 51 select SND_SOC_WM9081 if I2C
46 select SND_SOC_WM9705 if SND_SOC_AC97_BUS 52 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
47 select SND_SOC_WM9712 if SND_SOC_AC97_BUS 53 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
@@ -62,6 +68,9 @@ config SND_SOC_AC97_CODEC
62 tristate 68 tristate
63 select SND_AC97_CODEC 69 select SND_AC97_CODEC
64 70
71config SND_SOC_AD1938
72 tristate
73
65config SND_SOC_AD1980 74config SND_SOC_AD1980
66 tristate 75 tristate
67 76
@@ -86,6 +95,9 @@ config SND_SOC_CS4270_VD33_ERRATA
86 bool 95 bool
87 depends on SND_SOC_CS4270 96 depends on SND_SOC_CS4270
88 97
98config SND_SOC_CX20442
99 tristate
100
89config SND_SOC_L3 101config SND_SOC_L3
90 tristate 102 tristate
91 103
@@ -129,6 +141,9 @@ config SND_SOC_WM8400
129config SND_SOC_WM8510 141config SND_SOC_WM8510
130 tristate 142 tristate
131 143
144config SND_SOC_WM8523
145 tristate
146
132config SND_SOC_WM8580 147config SND_SOC_WM8580
133 tristate 148 tristate
134 149
@@ -144,6 +159,9 @@ config SND_SOC_WM8750
144config SND_SOC_WM8753 159config SND_SOC_WM8753
145 tristate 160 tristate
146 161
162config SND_SOC_WM8776
163 tristate
164
147config SND_SOC_WM8900 165config SND_SOC_WM8900
148 tristate 166 tristate
149 167
@@ -156,6 +174,9 @@ config SND_SOC_WM8940
156config SND_SOC_WM8960 174config SND_SOC_WM8960
157 tristate 175 tristate
158 176
177config SND_SOC_WM8961
178 tristate
179
159config SND_SOC_WM8971 180config SND_SOC_WM8971
160 tristate 181 tristate
161 182
@@ -165,6 +186,9 @@ config SND_SOC_WM8988
165config SND_SOC_WM8990 186config SND_SOC_WM8990
166 tristate 187 tristate
167 188
189config SND_SOC_WM8993
190 tristate
191
168config SND_SOC_WM9081 192config SND_SOC_WM9081
169 tristate 193 tristate
170 194
@@ -176,3 +200,7 @@ config SND_SOC_WM9712
176 200
177config SND_SOC_WM9713 201config SND_SOC_WM9713
178 tristate 202 tristate
203
204# Amp
205config SND_SOC_MAX9877
206 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8b7530546f4d..78dce5d3fa22 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,9 +1,11 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1938-objs := ad1938.o
2snd-soc-ad1980-objs := ad1980.o 3snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o 4snd-soc-ad73311-objs := ad73311.o
4snd-soc-ak4104-objs := ak4104.o 5snd-soc-ak4104-objs := ak4104.o
5snd-soc-ak4535-objs := ak4535.o 6snd-soc-ak4535-objs := ak4535.o
6snd-soc-cs4270-objs := cs4270.o 7snd-soc-cs4270-objs := cs4270.o
8snd-soc-cx20442-objs := cx20442.o
7snd-soc-l3-objs := l3.o 9snd-soc-l3-objs := l3.o
8snd-soc-pcm3008-objs := pcm3008.o 10snd-soc-pcm3008-objs := pcm3008.o
9snd-soc-spdif-objs := spdif_transciever.o 11snd-soc-spdif-objs := spdif_transciever.o
@@ -18,29 +20,38 @@ snd-soc-uda1380-objs := uda1380.o
18snd-soc-wm8350-objs := wm8350.o 20snd-soc-wm8350-objs := wm8350.o
19snd-soc-wm8400-objs := wm8400.o 21snd-soc-wm8400-objs := wm8400.o
20snd-soc-wm8510-objs := wm8510.o 22snd-soc-wm8510-objs := wm8510.o
23snd-soc-wm8523-objs := wm8523.o
21snd-soc-wm8580-objs := wm8580.o 24snd-soc-wm8580-objs := wm8580.o
22snd-soc-wm8728-objs := wm8728.o 25snd-soc-wm8728-objs := wm8728.o
23snd-soc-wm8731-objs := wm8731.o 26snd-soc-wm8731-objs := wm8731.o
24snd-soc-wm8750-objs := wm8750.o 27snd-soc-wm8750-objs := wm8750.o
25snd-soc-wm8753-objs := wm8753.o 28snd-soc-wm8753-objs := wm8753.o
29snd-soc-wm8776-objs := wm8776.o
26snd-soc-wm8900-objs := wm8900.o 30snd-soc-wm8900-objs := wm8900.o
27snd-soc-wm8903-objs := wm8903.o 31snd-soc-wm8903-objs := wm8903.o
28snd-soc-wm8940-objs := wm8940.o 32snd-soc-wm8940-objs := wm8940.o
29snd-soc-wm8960-objs := wm8960.o 33snd-soc-wm8960-objs := wm8960.o
34snd-soc-wm8961-objs := wm8961.o
30snd-soc-wm8971-objs := wm8971.o 35snd-soc-wm8971-objs := wm8971.o
31snd-soc-wm8988-objs := wm8988.o 36snd-soc-wm8988-objs := wm8988.o
32snd-soc-wm8990-objs := wm8990.o 37snd-soc-wm8990-objs := wm8990.o
38snd-soc-wm8993-objs := wm8993.o
33snd-soc-wm9081-objs := wm9081.o 39snd-soc-wm9081-objs := wm9081.o
34snd-soc-wm9705-objs := wm9705.o 40snd-soc-wm9705-objs := wm9705.o
35snd-soc-wm9712-objs := wm9712.o 41snd-soc-wm9712-objs := wm9712.o
36snd-soc-wm9713-objs := wm9713.o 42snd-soc-wm9713-objs := wm9713.o
37 43
44# Amp
45snd-soc-max9877-objs := max9877.o
46
38obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 47obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
48obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o
39obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 49obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
40obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 50obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
41obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 51obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
42obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 52obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
43obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 53obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
54obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
44obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 55obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
45obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 56obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
46obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 57obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
@@ -55,19 +66,26 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
55obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 66obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
56obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 67obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
57obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 68obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
69obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
58obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 70obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
59obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 71obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
60obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 72obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
61obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 73obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
62obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 74obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
75obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
63obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o 76obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
64obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 77obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
65obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 78obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
66obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o 79obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
67obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o 80obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
81obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
68obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o 82obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
69obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 83obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
84obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
70obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o 85obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
71obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o 86obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
72obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 87obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
73obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 88obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
89
90# Amp
91obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
new file mode 100644
index 000000000000..aafda743fc8f
--- /dev/null
+++ b/sound/soc/codecs/ad1938.c
@@ -0,0 +1,668 @@
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};
103
104static const struct snd_soc_dapm_route audio_paths[] = {
105 { "DAC", NULL, "ADC_PWR" },
106 { "ADC", NULL, "ADC_PWR" },
107};
108
109/*
110 * DAI ops entries
111 */
112
113static int ad1938_mute(struct snd_soc_dai *dai, int mute)
114{
115 struct snd_soc_codec *codec = dai->codec;
116 int reg;
117
118 reg = codec->read(codec, AD1938_DAC_CTRL2);
119 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
120 (~AD1938_DAC_MASTER_MUTE);
121 codec->write(codec, AD1938_DAC_CTRL2, reg);
122
123 return 0;
124}
125
126static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd)
127{
128 int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
129 reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg |
130 AD1938_PLL_POWERDOWN;
131 codec->write(codec, AD1938_PLL_CLK_CTRL0, reg);
132
133 return 0;
134}
135
136static int ad1938_set_tdm_slot(struct snd_soc_dai *dai,
137 unsigned int mask, int slots)
138{
139 struct snd_soc_codec *codec = dai->codec;
140 int dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
141 int adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
142
143 dac_reg &= ~AD1938_DAC_CHAN_MASK;
144 adc_reg &= ~AD1938_ADC_CHAN_MASK;
145
146 switch (slots) {
147 case 2:
148 dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
149 adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
150 break;
151 case 4:
152 dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
153 adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
154 break;
155 case 8:
156 dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
157 adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
158 break;
159 case 16:
160 dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
161 adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
162 break;
163 default:
164 return -EINVAL;
165 }
166
167 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
168 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
169
170 return 0;
171}
172
173static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
174 unsigned int fmt)
175{
176 struct snd_soc_codec *codec = codec_dai->codec;
177 int adc_reg, dac_reg;
178
179 adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
180 dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
181
182 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
183 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
184 */
185 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
186 case SND_SOC_DAIFMT_I2S:
187 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
188 adc_reg |= AD1938_ADC_SERFMT_TDM;
189 break;
190 case SND_SOC_DAIFMT_DSP_A:
191 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
192 adc_reg |= AD1938_ADC_SERFMT_AUX;
193 break;
194 default:
195 return -EINVAL;
196 }
197
198 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
199 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
200 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
201 adc_reg &= ~AD1938_ADC_BCLK_INV;
202 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
203 dac_reg &= ~AD1938_DAC_BCLK_INV;
204 break;
205 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
206 adc_reg |= AD1938_ADC_LEFT_HIGH;
207 adc_reg &= ~AD1938_ADC_BCLK_INV;
208 dac_reg |= AD1938_DAC_LEFT_HIGH;
209 dac_reg &= ~AD1938_DAC_BCLK_INV;
210 break;
211 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
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
218 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
219 adc_reg |= AD1938_ADC_LEFT_HIGH;
220 adc_reg |= AD1938_ADC_BCLK_INV;
221 dac_reg |= AD1938_DAC_LEFT_HIGH;
222 dac_reg |= AD1938_DAC_BCLK_INV;
223 break;
224 default:
225 return -EINVAL;
226 }
227
228 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
229 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
230 adc_reg |= AD1938_ADC_LCR_MASTER;
231 adc_reg |= AD1938_ADC_BCLK_MASTER;
232 dac_reg |= AD1938_DAC_LCR_MASTER;
233 dac_reg |= AD1938_DAC_BCLK_MASTER;
234 break;
235 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
236 adc_reg |= AD1938_ADC_LCR_MASTER;
237 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
238 dac_reg |= AD1938_DAC_LCR_MASTER;
239 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
240 break;
241 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
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_CFS: /* codec clk & frm slave */
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 default:
254 return -EINVAL;
255 }
256
257 codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
258 codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
259
260 return 0;
261}
262
263static int ad1938_hw_params(struct snd_pcm_substream *substream,
264 struct snd_pcm_hw_params *params,
265 struct snd_soc_dai *dai)
266{
267 int word_len = 0, reg = 0;
268
269 struct snd_soc_pcm_runtime *rtd = substream->private_data;
270 struct snd_soc_device *socdev = rtd->socdev;
271 struct snd_soc_codec *codec = socdev->card->codec;
272
273 /* bit size */
274 switch (params_format(params)) {
275 case SNDRV_PCM_FORMAT_S16_LE:
276 word_len = 3;
277 break;
278 case SNDRV_PCM_FORMAT_S20_3LE:
279 word_len = 1;
280 break;
281 case SNDRV_PCM_FORMAT_S24_LE:
282 case SNDRV_PCM_FORMAT_S32_LE:
283 word_len = 0;
284 break;
285 }
286
287 reg = codec->read(codec, AD1938_DAC_CTRL2);
288 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
289 codec->write(codec, AD1938_DAC_CTRL2, reg);
290
291 reg = codec->read(codec, AD1938_ADC_CTRL1);
292 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
293 codec->write(codec, AD1938_ADC_CTRL1, reg);
294
295 return 0;
296}
297
298static int ad1938_set_bias_level(struct snd_soc_codec *codec,
299 enum snd_soc_bias_level level)
300{
301 switch (level) {
302 case SND_SOC_BIAS_ON:
303 ad1938_pll_powerctrl(codec, 1);
304 break;
305 case SND_SOC_BIAS_PREPARE:
306 break;
307 case SND_SOC_BIAS_STANDBY:
308 case SND_SOC_BIAS_OFF:
309 ad1938_pll_powerctrl(codec, 0);
310 break;
311 }
312 codec->bias_level = level;
313 return 0;
314}
315
316/*
317 * interface to read/write ad1938 register
318 */
319
320#define AD1938_SPI_ADDR 0x4
321#define AD1938_SPI_READ 0x1
322#define AD1938_SPI_BUFLEN 3
323
324/*
325 * write to the ad1938 register space
326 */
327
328static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
329 unsigned int value)
330{
331 u8 *reg_cache = codec->reg_cache;
332 int ret = 0;
333
334 if (value != reg_cache[reg]) {
335 uint8_t buf[AD1938_SPI_BUFLEN];
336 struct spi_transfer t = {
337 .tx_buf = buf,
338 .len = AD1938_SPI_BUFLEN,
339 };
340 struct spi_message m;
341
342 buf[0] = AD1938_SPI_ADDR << 1;
343 buf[1] = reg;
344 buf[2] = value;
345 spi_message_init(&m);
346 spi_message_add_tail(&t, &m);
347 ret = spi_sync(codec->control_data, &m);
348 if (ret == 0)
349 reg_cache[reg] = value;
350 }
351
352 return ret;
353}
354
355/*
356 * read from the ad1938 register space cache
357 */
358
359static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
360 unsigned int reg)
361{
362 u8 *reg_cache = codec->reg_cache;
363
364 if (reg >= codec->reg_cache_size)
365 return -EINVAL;
366
367 return reg_cache[reg];
368}
369
370/*
371 * read from the ad1938 register space
372 */
373
374static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
375 unsigned int reg)
376{
377 char w_buf[AD1938_SPI_BUFLEN];
378 char r_buf[AD1938_SPI_BUFLEN];
379 int ret;
380
381 struct spi_transfer t = {
382 .tx_buf = w_buf,
383 .rx_buf = r_buf,
384 .len = AD1938_SPI_BUFLEN,
385 };
386 struct spi_message m;
387
388 w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
389 w_buf[1] = reg;
390 w_buf[2] = 0;
391
392 spi_message_init(&m);
393 spi_message_add_tail(&t, &m);
394 ret = spi_sync(codec->control_data, &m);
395 if (ret == 0)
396 return r_buf[2];
397 else
398 return -EIO;
399}
400
401static int ad1938_fill_cache(struct snd_soc_codec *codec)
402{
403 int i;
404 u8 *reg_cache = codec->reg_cache;
405 struct spi_device *spi = codec->control_data;
406
407 for (i = 0; i < codec->reg_cache_size; i++) {
408 int ret = ad1938_read_reg(codec, i);
409 if (ret == -EIO) {
410 dev_err(&spi->dev, "AD1938 SPI read failure\n");
411 return ret;
412 }
413 reg_cache[i] = ret;
414 }
415
416 return 0;
417}
418
419static int __devinit ad1938_spi_probe(struct spi_device *spi)
420{
421 struct snd_soc_codec *codec;
422 struct ad1938_priv *ad1938;
423
424 ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
425 if (ad1938 == NULL)
426 return -ENOMEM;
427
428 codec = &ad1938->codec;
429 codec->control_data = spi;
430 codec->dev = &spi->dev;
431
432 dev_set_drvdata(&spi->dev, ad1938);
433
434 return ad1938_register(ad1938);
435}
436
437static int __devexit ad1938_spi_remove(struct spi_device *spi)
438{
439 struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
440
441 ad1938_unregister(ad1938);
442 return 0;
443}
444
445static struct spi_driver ad1938_spi_driver = {
446 .driver = {
447 .name = "ad1938-spi",
448 .bus = &spi_bus_type,
449 .owner = THIS_MODULE,
450 },
451 .probe = ad1938_spi_probe,
452 .remove = __devexit_p(ad1938_spi_remove),
453};
454
455static struct snd_soc_dai_ops ad1938_dai_ops = {
456 .hw_params = ad1938_hw_params,
457 .digital_mute = ad1938_mute,
458 .set_tdm_slot = ad1938_set_tdm_slot,
459 .set_fmt = ad1938_set_dai_fmt,
460};
461
462/* codec DAI instance */
463struct snd_soc_dai ad1938_dai = {
464 .name = "AD1938",
465 .playback = {
466 .stream_name = "Playback",
467 .channels_min = 2,
468 .channels_max = 8,
469 .rates = SNDRV_PCM_RATE_48000,
470 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
471 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
472 },
473 .capture = {
474 .stream_name = "Capture",
475 .channels_min = 2,
476 .channels_max = 4,
477 .rates = SNDRV_PCM_RATE_48000,
478 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
479 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
480 },
481 .ops = &ad1938_dai_ops,
482};
483EXPORT_SYMBOL_GPL(ad1938_dai);
484
485static int ad1938_register(struct ad1938_priv *ad1938)
486{
487 int ret;
488 struct snd_soc_codec *codec = &ad1938->codec;
489
490 if (ad1938_codec) {
491 dev_err(codec->dev, "Another ad1938 is registered\n");
492 return -EINVAL;
493 }
494
495 mutex_init(&codec->mutex);
496 INIT_LIST_HEAD(&codec->dapm_widgets);
497 INIT_LIST_HEAD(&codec->dapm_paths);
498 codec->private_data = ad1938;
499 codec->reg_cache = ad1938->reg_cache;
500 codec->reg_cache_size = AD1938_NUM_REGS;
501 codec->name = "AD1938";
502 codec->owner = THIS_MODULE;
503 codec->dai = &ad1938_dai;
504 codec->num_dai = 1;
505 codec->write = ad1938_write_reg;
506 codec->read = ad1938_read_reg_cache;
507 INIT_LIST_HEAD(&codec->dapm_widgets);
508 INIT_LIST_HEAD(&codec->dapm_paths);
509
510 ad1938_dai.dev = codec->dev;
511 ad1938_codec = codec;
512
513 /* default setting for ad1938 */
514
515 /* unmute dac channels */
516 codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
517 /* de-emphasis: 48kHz, powedown dac */
518 codec->write(codec, AD1938_DAC_CTRL2, 0x1A);
519 /* powerdown dac, dac in tdm mode */
520 codec->write(codec, AD1938_DAC_CTRL0, 0x41);
521 /* high-pass filter enable */
522 codec->write(codec, AD1938_ADC_CTRL0, 0x3);
523 /* sata delay=1, adc aux mode */
524 codec->write(codec, AD1938_ADC_CTRL1, 0x43);
525 /* pll input: mclki/xi */
526 codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
527 codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
528
529 ad1938_fill_cache(codec);
530
531 ret = snd_soc_register_codec(codec);
532 if (ret != 0) {
533 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
534 return ret;
535 }
536
537 ret = snd_soc_register_dai(&ad1938_dai);
538 if (ret != 0) {
539 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
540 snd_soc_unregister_codec(codec);
541 return ret;
542 }
543
544 return 0;
545}
546
547static void ad1938_unregister(struct ad1938_priv *ad1938)
548{
549 ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF);
550 snd_soc_unregister_dai(&ad1938_dai);
551 snd_soc_unregister_codec(&ad1938->codec);
552 kfree(ad1938);
553 ad1938_codec = NULL;
554}
555
556static int ad1938_probe(struct platform_device *pdev)
557{
558 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
559 struct snd_soc_codec *codec;
560 int ret = 0;
561
562 if (ad1938_codec == NULL) {
563 dev_err(&pdev->dev, "Codec device not registered\n");
564 return -ENODEV;
565 }
566
567 socdev->card->codec = ad1938_codec;
568 codec = ad1938_codec;
569
570 /* register pcms */
571 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
572 if (ret < 0) {
573 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
574 goto pcm_err;
575 }
576
577 snd_soc_add_controls(codec, ad1938_snd_controls,
578 ARRAY_SIZE(ad1938_snd_controls));
579 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
580 ARRAY_SIZE(ad1938_dapm_widgets));
581 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
582 snd_soc_dapm_new_widgets(codec);
583
584 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
585
586 ret = snd_soc_init_card(socdev);
587 if (ret < 0) {
588 dev_err(codec->dev, "failed to register card: %d\n", ret);
589 goto card_err;
590 }
591
592 return ret;
593
594card_err:
595 snd_soc_free_pcms(socdev);
596 snd_soc_dapm_free(socdev);
597pcm_err:
598 return ret;
599}
600
601/* power down chip */
602static int ad1938_remove(struct platform_device *pdev)
603{
604 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
605
606 snd_soc_free_pcms(socdev);
607 snd_soc_dapm_free(socdev);
608
609 return 0;
610}
611
612#ifdef CONFIG_PM
613static int ad1938_suspend(struct platform_device *pdev,
614 pm_message_t state)
615{
616 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
617 struct snd_soc_codec *codec = socdev->card->codec;
618
619 ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF);
620 return 0;
621}
622
623static int ad1938_resume(struct platform_device *pdev)
624{
625 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
626 struct snd_soc_codec *codec = socdev->card->codec;
627
628 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
629 ad1938_set_bias_level(codec, SND_SOC_BIAS_ON);
630
631 return 0;
632}
633#else
634#define ad1938_suspend NULL
635#define ad1938_resume NULL
636#endif
637
638struct snd_soc_codec_device soc_codec_dev_ad1938 = {
639 .probe = ad1938_probe,
640 .remove = ad1938_remove,
641 .suspend = ad1938_suspend,
642 .resume = ad1938_resume,
643};
644EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
645
646static int __init ad1938_init(void)
647{
648 int ret;
649
650 ret = spi_register_driver(&ad1938_spi_driver);
651 if (ret != 0) {
652 printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
653 ret);
654 }
655
656 return ret;
657}
658module_init(ad1938_init);
659
660static void __exit ad1938_exit(void)
661{
662 spi_unregister_driver(&ad1938_spi_driver);
663}
664module_exit(ad1938_exit);
665
666MODULE_DESCRIPTION("ASoC ad1938 driver");
667MODULE_AUTHOR("Barry Song ");
668MODULE_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/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 a32b8226c8a4..ca1e24a8f12a 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -806,15 +806,30 @@ static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
806{ 806{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client); 807 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
808 struct snd_soc_codec *codec = &cs4270->codec; 808 struct snd_soc_codec *codec = &cs4270->codec;
809 int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
810 809
811 return snd_soc_write(codec, CS4270_PWRCTL, reg); 810 return snd_soc_suspend_device(codec->dev);
812} 811}
813 812
814static int cs4270_i2c_resume(struct i2c_client *client) 813static int cs4270_i2c_resume(struct i2c_client *client)
815{ 814{
816 struct cs4270_private *cs4270 = i2c_get_clientdata(client); 815 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
817 struct snd_soc_codec *codec = &cs4270->codec; 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;
818 int reg; 833 int reg;
819 834
820 /* In case the device was put to hard reset during sleep, we need to 835 /* In case the device was put to hard reset during sleep, we need to
@@ -825,7 +840,7 @@ static int cs4270_i2c_resume(struct i2c_client *client)
825 for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { 840 for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
826 u8 val = snd_soc_read(codec, reg); 841 u8 val = snd_soc_read(codec, reg);
827 842
828 if (i2c_smbus_write_byte_data(client, reg, val)) { 843 if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
829 dev_err(codec->dev, "i2c write failed\n"); 844 dev_err(codec->dev, "i2c write failed\n");
830 return -EIO; 845 return -EIO;
831 } 846 }
@@ -840,6 +855,8 @@ static int cs4270_i2c_resume(struct i2c_client *client)
840#else 855#else
841#define cs4270_i2c_suspend NULL 856#define cs4270_i2c_suspend NULL
842#define cs4270_i2c_resume NULL 857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL
843#endif /* CONFIG_PM */ 860#endif /* CONFIG_PM */
844 861
845/* 862/*
@@ -868,7 +885,9 @@ static struct i2c_driver cs4270_i2c_driver = {
868 */ 885 */
869struct snd_soc_codec_device soc_codec_device_cs4270 = { 886struct snd_soc_codec_device soc_codec_device_cs4270 = {
870 .probe = cs4270_probe, 887 .probe = cs4270_probe,
871 .remove = cs4270_remove 888 .remove = cs4270_remove,
889 .suspend = cs4270_soc_suspend,
890 .resume = cs4270_soc_resume,
872}; 891};
873EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); 892EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
874 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
index 218b33adad90..a63191141052 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -21,6 +21,8 @@
21 21
22#include "spdif_transciever.h" 22#include "spdif_transciever.h"
23 23
24MODULE_LICENSE("GPL");
25
24#define STUB_RATES SNDRV_PCM_RATE_8000_96000 26#define STUB_RATES SNDRV_PCM_RATE_8000_96000
25#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE 27#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
26 28
@@ -34,6 +36,7 @@ struct snd_soc_dai dit_stub_dai = {
34 .formats = STUB_FORMATS, 36 .formats = STUB_FORMATS,
35 }, 37 },
36}; 38};
39EXPORT_SYMBOL_GPL(dit_stub_dai);
37 40
38static int spdif_dit_probe(struct platform_device *pdev) 41static int spdif_dit_probe(struct platform_device *pdev)
39{ 42{
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 8ad4b7b3e3ba..befc6488c39a 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -149,7 +149,7 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
149 stac9766_ac97_write(codec, AC97_INT_PAGING, 1); 149 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
150 return 0; 150 return 0;
151 } 151 }
152 if (reg / 2 > ARRAY_SIZE(stac9766_reg)) 152 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
153 return -EIO; 153 return -EIO;
154 154
155 soc_ac97_ops.write(codec->ac97, reg, val); 155 soc_ac97_ops.write(codec->ac97, reg, val);
@@ -168,7 +168,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
168 stac9766_ac97_write(codec, AC97_INT_PAGING, 1); 168 stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
169 return val; 169 return val;
170 } 170 }
171 if (reg / 2 > ARRAY_SIZE(stac9766_reg)) 171 if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
172 return -EIO; 172 return -EIO;
173 173
174 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || 174 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 4dbb853eef5a..818fb37bd7f7 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -620,6 +620,9 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
620 620
621static void headset_ramp(struct snd_soc_codec *codec, int ramp) 621static void headset_ramp(struct snd_soc_codec *codec, int ramp)
622{ 622{
623 struct snd_soc_device *socdev = codec->socdev;
624 struct twl4030_setup_data *setup = socdev->codec_data;
625
623 unsigned char hs_gain, hs_pop; 626 unsigned char hs_gain, hs_pop;
624 struct twl4030_priv *twl4030 = codec->private_data; 627 struct twl4030_priv *twl4030 = codec->private_data;
625 /* Base values for ramp delay calculation: 2^19 - 2^26 */ 628 /* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -629,6 +632,17 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
629 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); 632 hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
630 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); 633 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
631 634
635 /* Enable external mute control, this dramatically reduces
636 * the pop-noise */
637 if (setup && setup->hs_extmute) {
638 if (setup->set_hs_extmute) {
639 setup->set_hs_extmute(1);
640 } else {
641 hs_pop |= TWL4030_EXTMUTE;
642 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
643 }
644 }
645
632 if (ramp) { 646 if (ramp) {
633 /* Headset ramp-up according to the TRM */ 647 /* Headset ramp-up according to the TRM */
634 hs_pop |= TWL4030_VMID_EN; 648 hs_pop |= TWL4030_VMID_EN;
@@ -636,6 +650,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
636 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain); 650 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
637 hs_pop |= TWL4030_RAMP_EN; 651 hs_pop |= TWL4030_RAMP_EN;
638 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 652 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
653 /* Wait ramp delay time + 1, so the VMID can settle */
654 mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
655 twl4030->sysclk) + 1);
639 } else { 656 } else {
640 /* Headset ramp-down _not_ according to 657 /* Headset ramp-down _not_ according to
641 * the TRM, but in a way that it is working */ 658 * the TRM, but in a way that it is working */
@@ -652,6 +669,16 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
652 hs_pop &= ~TWL4030_VMID_EN; 669 hs_pop &= ~TWL4030_VMID_EN;
653 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 670 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
654 } 671 }
672
673 /* Disable external mute */
674 if (setup && setup->hs_extmute) {
675 if (setup->set_hs_extmute) {
676 setup->set_hs_extmute(0);
677 } else {
678 hs_pop &= ~TWL4030_EXTMUTE;
679 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
680 }
681 }
655} 682}
656 683
657static int headsetlpga_event(struct snd_soc_dapm_widget *w, 684static int headsetlpga_event(struct snd_soc_dapm_widget *w,
@@ -712,7 +739,19 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
712 739
713 reg = twl4030_read_reg_cache(w->codec, m->reg); 740 reg = twl4030_read_reg_cache(w->codec, m->reg);
714 741
715 if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { 742 /*
743 * bypass_state[0:3] - analog HiFi bypass
744 * bypass_state[4] - analog voice bypass
745 * bypass_state[5] - digital voice bypass
746 * bypass_state[6:7] - digital HiFi bypass
747 */
748 if (m->reg == TWL4030_REG_VSTPGA) {
749 /* Voice digital bypass */
750 if (reg)
751 twl4030->bypass_state |= (1 << 5);
752 else
753 twl4030->bypass_state &= ~(1 << 5);
754 } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
716 /* Analog bypass */ 755 /* Analog bypass */
717 if (reg & (1 << m->shift)) 756 if (reg & (1 << m->shift))
718 twl4030->bypass_state |= 757 twl4030->bypass_state |=
@@ -726,12 +765,6 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
726 twl4030->bypass_state |= (1 << 4); 765 twl4030->bypass_state |= (1 << 4);
727 else 766 else
728 twl4030->bypass_state &= ~(1 << 4); 767 twl4030->bypass_state &= ~(1 << 4);
729 } else if (m->reg == TWL4030_REG_VSTPGA) {
730 /* Voice digital bypass */
731 if (reg)
732 twl4030->bypass_state |= (1 << 5);
733 else
734 twl4030->bypass_state &= ~(1 << 5);
735 } else { 768 } else {
736 /* Digital bypass */ 769 /* Digital bypass */
737 if (reg & (0x7 << m->shift)) 770 if (reg & (0x7 << m->shift))
@@ -924,7 +957,7 @@ static const struct soc_enum twl4030_op_modes_enum =
924 ARRAY_SIZE(twl4030_op_modes_texts), 957 ARRAY_SIZE(twl4030_op_modes_texts),
925 twl4030_op_modes_texts); 958 twl4030_op_modes_texts);
926 959
927int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, 960static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
928 struct snd_ctl_elem_value *ucontrol) 961 struct snd_ctl_elem_value *ucontrol)
929{ 962{
930 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 963 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -1005,6 +1038,16 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
1005 */ 1038 */
1006static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); 1039static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
1007 1040
1041/* AVADC clock priority */
1042static const char *twl4030_avadc_clk_priority_texts[] = {
1043 "Voice high priority", "HiFi high priority"
1044};
1045
1046static const struct soc_enum twl4030_avadc_clk_priority_enum =
1047 SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
1048 ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
1049 twl4030_avadc_clk_priority_texts);
1050
1008static const char *twl4030_rampdelay_texts[] = { 1051static const char *twl4030_rampdelay_texts[] = {
1009 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", 1052 "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
1010 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", 1053 "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
@@ -1106,6 +1149,8 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1106 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 1149 SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
1107 0, 3, 5, 0, input_gain_tlv), 1150 0, 3, 5, 0, input_gain_tlv),
1108 1151
1152 SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum),
1153
1109 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), 1154 SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
1110 1155
1111 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum), 1156 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
@@ -1240,14 +1285,14 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1240 /* HandsfreeL/R */ 1285 /* HandsfreeL/R */
1241 SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0, 1286 SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
1242 &twl4030_dapm_handsfreel_control), 1287 &twl4030_dapm_handsfreel_control),
1243 SND_SOC_DAPM_SWITCH("HandsfreeL Switch", SND_SOC_NOPM, 0, 0, 1288 SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0,
1244 &twl4030_dapm_handsfreelmute_control), 1289 &twl4030_dapm_handsfreelmute_control),
1245 SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM, 1290 SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
1246 0, 0, NULL, 0, handsfreelpga_event, 1291 0, 0, NULL, 0, handsfreelpga_event,
1247 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1292 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1248 SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0, 1293 SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
1249 &twl4030_dapm_handsfreer_control), 1294 &twl4030_dapm_handsfreer_control),
1250 SND_SOC_DAPM_SWITCH("HandsfreeR Switch", SND_SOC_NOPM, 0, 0, 1295 SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0,
1251 &twl4030_dapm_handsfreermute_control), 1296 &twl4030_dapm_handsfreermute_control),
1252 SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM, 1297 SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
1253 0, 0, NULL, 0, handsfreerpga_event, 1298 0, 0, NULL, 0, handsfreerpga_event,
@@ -1359,15 +1404,15 @@ static const struct snd_soc_dapm_route intercon[] = {
1359 {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, 1404 {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
1360 {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, 1405 {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
1361 {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, 1406 {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
1362 {"HandsfreeL Switch", "Switch", "HandsfreeL Mux"}, 1407 {"HandsfreeL", "Switch", "HandsfreeL Mux"},
1363 {"HandsfreeL PGA", NULL, "HandsfreeL Switch"}, 1408 {"HandsfreeL PGA", NULL, "HandsfreeL"},
1364 /* HandsfreeR */ 1409 /* HandsfreeR */
1365 {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, 1410 {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
1366 {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, 1411 {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
1367 {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, 1412 {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
1368 {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, 1413 {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
1369 {"HandsfreeR Switch", "Switch", "HandsfreeR Mux"}, 1414 {"HandsfreeR", "Switch", "HandsfreeR Mux"},
1370 {"HandsfreeR PGA", NULL, "HandsfreeR Switch"}, 1415 {"HandsfreeR PGA", NULL, "HandsfreeR"},
1371 /* Vibra */ 1416 /* Vibra */
1372 {"Vibra Mux", "AudioL1", "DAC Left1"}, 1417 {"Vibra Mux", "AudioL1", "DAC Left1"},
1373 {"Vibra Mux", "AudioR1", "DAC Right1"}, 1418 {"Vibra Mux", "AudioR1", "DAC Right1"},
@@ -1609,8 +1654,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1609 1654
1610 /* If the substream has 4 channel, do the necessary setup */ 1655 /* If the substream has 4 channel, do the necessary setup */
1611 if (params_channels(params) == 4) { 1656 if (params_channels(params) == 4) {
1612 u8 format, mode;
1613
1614 format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); 1657 format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1615 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); 1658 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
1616 1659
@@ -1806,6 +1849,19 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1806 return 0; 1849 return 0;
1807} 1850}
1808 1851
1852static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
1853{
1854 struct snd_soc_codec *codec = dai->codec;
1855 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1856
1857 if (tristate)
1858 reg |= TWL4030_AIF_TRI_EN;
1859 else
1860 reg &= ~TWL4030_AIF_TRI_EN;
1861
1862 return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg);
1863}
1864
1809/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R 1865/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
1810 * (VTXL, VTXR) for uplink has to be enabled/disabled. */ 1866 * (VTXL, VTXR) for uplink has to be enabled/disabled. */
1811static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, 1867static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
@@ -1948,7 +2004,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
1948 2004
1949 /* set master/slave audio interface */ 2005 /* set master/slave audio interface */
1950 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 2006 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1951 case SND_SOC_DAIFMT_CBS_CFM: 2007 case SND_SOC_DAIFMT_CBM_CFM:
1952 format &= ~(TWL4030_VIF_SLAVE_EN); 2008 format &= ~(TWL4030_VIF_SLAVE_EN);
1953 break; 2009 break;
1954 case SND_SOC_DAIFMT_CBS_CFS: 2010 case SND_SOC_DAIFMT_CBS_CFS:
@@ -1980,6 +2036,19 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
1980 return 0; 2036 return 0;
1981} 2037}
1982 2038
2039static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
2040{
2041 struct snd_soc_codec *codec = dai->codec;
2042 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
2043
2044 if (tristate)
2045 reg |= TWL4030_VIF_TRI_EN;
2046 else
2047 reg &= ~TWL4030_VIF_TRI_EN;
2048
2049 return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg);
2050}
2051
1983#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 2052#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
1984#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 2053#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1985 2054
@@ -1989,6 +2058,7 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
1989 .hw_params = twl4030_hw_params, 2058 .hw_params = twl4030_hw_params,
1990 .set_sysclk = twl4030_set_dai_sysclk, 2059 .set_sysclk = twl4030_set_dai_sysclk,
1991 .set_fmt = twl4030_set_dai_fmt, 2060 .set_fmt = twl4030_set_dai_fmt,
2061 .set_tristate = twl4030_set_tristate,
1992}; 2062};
1993 2063
1994static struct snd_soc_dai_ops twl4030_dai_voice_ops = { 2064static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
@@ -1997,6 +2067,7 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
1997 .hw_params = twl4030_voice_hw_params, 2067 .hw_params = twl4030_voice_hw_params,
1998 .set_sysclk = twl4030_voice_set_dai_sysclk, 2068 .set_sysclk = twl4030_voice_set_dai_sysclk,
1999 .set_fmt = twl4030_voice_set_dai_fmt, 2069 .set_fmt = twl4030_voice_set_dai_fmt,
2070 .set_tristate = twl4030_voice_set_tristate,
2000}; 2071};
2001 2072
2002struct snd_soc_dai twl4030_dai[] = { 2073struct snd_soc_dai twl4030_dai[] = {
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index fe5f395d9e4f..2b4bfa23f985 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -274,6 +274,8 @@ extern struct snd_soc_codec_device soc_codec_dev_twl4030;
274struct twl4030_setup_data { 274struct twl4030_setup_data {
275 unsigned int ramp_delay_value; 275 unsigned int ramp_delay_value;
276 unsigned int sysclk; 276 unsigned int sysclk;
277 unsigned int hs_extmute:1;
278 void (*set_hs_extmute)(int mute);
277}; 279};
278 280
279#endif /* End of __TWL4030_AUDIO_H__ */ 281#endif /* End of __TWL4030_AUDIO_H__ */
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 e7348d341b76..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
@@ -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/wm8400.c b/sound/soc/codecs/wm8400.c
index 502eefac1ecd..b9ef4d915221 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -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);
@@ -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 c8b8dba85890..261d4cb75964 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -577,6 +577,7 @@ struct snd_soc_dai wm8510_dai = {
577 .rates = WM8510_RATES, 577 .rates = WM8510_RATES,
578 .formats = WM8510_FORMATS,}, 578 .formats = WM8510_FORMATS,},
579 .ops = &wm8510_dai_ops, 579 .ops = &wm8510_dai_ops,
580 .symmetric_rates = 1,
580}; 581};
581EXPORT_SYMBOL_GPL(wm8510_dai); 582EXPORT_SYMBOL_GPL(wm8510_dai);
582 583
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
new file mode 100644
index 000000000000..3b499ae7ce6c
--- /dev/null
+++ b/sound/soc/codecs/wm8523.c
@@ -0,0 +1,755 @@
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(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_write(struct snd_soc_codec *codec, unsigned int reg,
77 unsigned int value)
78{
79 struct wm8523_priv *wm8523 = codec->private_data;
80 u8 data[3];
81
82 BUG_ON(reg > WM8523_MAX_REGISTER);
83
84 data[0] = reg;
85 data[1] = (value >> 8) & 0x00ff;
86 data[2] = value & 0x00ff;
87
88 if (!wm8523_volatile(reg))
89 wm8523->reg_cache[reg] = value;
90 if (codec->hw_write(codec->control_data, data, 3) == 3)
91 return 0;
92 else
93 return -EIO;
94}
95
96static int wm8523_reset(struct snd_soc_codec *codec)
97{
98 return wm8523_write(codec, WM8523_DEVICE_ID, 0);
99}
100
101static unsigned int wm8523_read_hw(struct snd_soc_codec *codec, u8 reg)
102{
103 struct i2c_msg xfer[2];
104 u16 data;
105 int ret;
106 struct i2c_client *i2c = codec->control_data;
107
108 /* Write register */
109 xfer[0].addr = i2c->addr;
110 xfer[0].flags = 0;
111 xfer[0].len = 1;
112 xfer[0].buf = &reg;
113
114 /* Read data */
115 xfer[1].addr = i2c->addr;
116 xfer[1].flags = I2C_M_RD;
117 xfer[1].len = 2;
118 xfer[1].buf = (u8 *)&data;
119
120 ret = i2c_transfer(i2c->adapter, xfer, 2);
121 if (ret != 2) {
122 dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
123 return 0;
124 }
125
126 return (data >> 8) | ((data & 0xff) << 8);
127}
128
129
130static unsigned int wm8523_read(struct snd_soc_codec *codec,
131 unsigned int reg)
132{
133 u16 *reg_cache = codec->reg_cache;
134
135 BUG_ON(reg > WM8523_MAX_REGISTER);
136
137 if (wm8523_volatile(reg))
138 return wm8523_read_hw(codec, reg);
139 else
140 return reg_cache[reg];
141}
142
143static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
144
145static const char *wm8523_zd_count_text[] = {
146 "1024",
147 "2048",
148};
149
150static const struct soc_enum wm8523_zc_count =
151 SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
152
153static const struct snd_kcontrol_new wm8523_snd_controls[] = {
154SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
155 0, 448, 0, dac_tlv),
156SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
157SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
158SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
159SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
160SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
161SOC_ENUM("Zero Detect Count", wm8523_zc_count),
162};
163
164static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
165SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
166SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
167SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
168};
169
170static const struct snd_soc_dapm_route intercon[] = {
171 { "LINEVOUTL", NULL, "DAC" },
172 { "LINEVOUTR", NULL, "DAC" },
173};
174
175static int wm8523_add_widgets(struct snd_soc_codec *codec)
176{
177 snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets,
178 ARRAY_SIZE(wm8523_dapm_widgets));
179
180 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
181
182 snd_soc_dapm_new_widgets(codec);
183 return 0;
184}
185
186static struct {
187 int value;
188 int ratio;
189} lrclk_ratios[WM8523_NUM_RATES] = {
190 { 1, 128 },
191 { 2, 192 },
192 { 3, 256 },
193 { 4, 384 },
194 { 5, 512 },
195 { 6, 768 },
196 { 7, 1152 },
197};
198
199static int wm8523_startup(struct snd_pcm_substream *substream,
200 struct snd_soc_dai *dai)
201{
202 struct snd_soc_codec *codec = dai->codec;
203 struct wm8523_priv *wm8523 = codec->private_data;
204
205 /* The set of sample rates that can be supported depends on the
206 * MCLK supplied to the CODEC - enforce this.
207 */
208 if (!wm8523->sysclk) {
209 dev_err(codec->dev,
210 "No MCLK configured, call set_sysclk() on init\n");
211 return -EINVAL;
212 }
213
214 return 0;
215 snd_pcm_hw_constraint_list(substream->runtime, 0,
216 SNDRV_PCM_HW_PARAM_RATE,
217 &wm8523->rate_constraint);
218
219 return 0;
220}
221
222static int wm8523_hw_params(struct snd_pcm_substream *substream,
223 struct snd_pcm_hw_params *params,
224 struct snd_soc_dai *dai)
225{
226 struct snd_soc_pcm_runtime *rtd = substream->private_data;
227 struct snd_soc_device *socdev = rtd->socdev;
228 struct snd_soc_codec *codec = socdev->card->codec;
229 struct wm8523_priv *wm8523 = codec->private_data;
230 int i;
231 u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1);
232 u16 aifctrl2 = wm8523_read(codec, WM8523_AIF_CTRL2);
233
234 /* Find a supported LRCLK ratio */
235 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
236 if (wm8523->sysclk / params_rate(params) ==
237 lrclk_ratios[i].ratio)
238 break;
239 }
240
241 /* Should never happen, should be handled by constraints */
242 if (i == ARRAY_SIZE(lrclk_ratios)) {
243 dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
244 wm8523->sysclk / params_rate(params));
245 return -EINVAL;
246 }
247
248 aifctrl2 &= ~WM8523_SR_MASK;
249 aifctrl2 |= lrclk_ratios[i].value;
250
251 aifctrl1 &= ~WM8523_WL_MASK;
252 switch (params_format(params)) {
253 case SNDRV_PCM_FORMAT_S16_LE:
254 break;
255 case SNDRV_PCM_FORMAT_S20_3LE:
256 aifctrl1 |= 0x8;
257 break;
258 case SNDRV_PCM_FORMAT_S24_LE:
259 aifctrl1 |= 0x10;
260 break;
261 case SNDRV_PCM_FORMAT_S32_LE:
262 aifctrl1 |= 0x18;
263 break;
264 }
265
266 wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1);
267 wm8523_write(codec, WM8523_AIF_CTRL2, aifctrl2);
268
269 return 0;
270}
271
272static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
273 int clk_id, unsigned int freq, int dir)
274{
275 struct snd_soc_codec *codec = codec_dai->codec;
276 struct wm8523_priv *wm8523 = codec->private_data;
277 unsigned int val;
278 int i;
279
280 wm8523->sysclk = freq;
281
282 wm8523->rate_constraint.count = 0;
283 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
284 val = freq / lrclk_ratios[i].ratio;
285 /* Check that it's a standard rate since core can't
286 * cope with others and having the odd rates confuses
287 * constraint matching.
288 */
289 switch (val) {
290 case 8000:
291 case 11025:
292 case 16000:
293 case 22050:
294 case 32000:
295 case 44100:
296 case 48000:
297 case 64000:
298 case 88200:
299 case 96000:
300 case 176400:
301 case 192000:
302 dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
303 val);
304 wm8523->rate_constraint_list[i] = val;
305 wm8523->rate_constraint.count++;
306 break;
307 default:
308 dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
309 val);
310 }
311 }
312
313 /* Need at least one supported rate... */
314 if (wm8523->rate_constraint.count == 0)
315 return -EINVAL;
316
317 return 0;
318}
319
320
321static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
322 unsigned int fmt)
323{
324 struct snd_soc_codec *codec = codec_dai->codec;
325 u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1);
326
327 aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
328 WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
329
330 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
331 case SND_SOC_DAIFMT_CBM_CFM:
332 aifctrl1 |= WM8523_AIF_MSTR;
333 break;
334 case SND_SOC_DAIFMT_CBS_CFS:
335 break;
336 default:
337 return -EINVAL;
338 }
339
340 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
341 case SND_SOC_DAIFMT_I2S:
342 aifctrl1 |= 0x0002;
343 break;
344 case SND_SOC_DAIFMT_RIGHT_J:
345 break;
346 case SND_SOC_DAIFMT_LEFT_J:
347 aifctrl1 |= 0x0001;
348 break;
349 case SND_SOC_DAIFMT_DSP_A:
350 aifctrl1 |= 0x0003;
351 break;
352 case SND_SOC_DAIFMT_DSP_B:
353 aifctrl1 |= 0x0023;
354 break;
355 default:
356 return -EINVAL;
357 }
358
359 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
360 case SND_SOC_DAIFMT_NB_NF:
361 break;
362 case SND_SOC_DAIFMT_IB_IF:
363 aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
364 break;
365 case SND_SOC_DAIFMT_IB_NF:
366 aifctrl1 |= WM8523_BCLK_INV;
367 break;
368 case SND_SOC_DAIFMT_NB_IF:
369 aifctrl1 |= WM8523_LRCLK_INV;
370 break;
371 default:
372 return -EINVAL;
373 }
374
375 wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1);
376
377 return 0;
378}
379
380static int wm8523_set_bias_level(struct snd_soc_codec *codec,
381 enum snd_soc_bias_level level)
382{
383 struct wm8523_priv *wm8523 = codec->private_data;
384 int ret, i;
385
386 switch (level) {
387 case SND_SOC_BIAS_ON:
388 break;
389
390 case SND_SOC_BIAS_PREPARE:
391 /* Full power on */
392 snd_soc_update_bits(codec, WM8523_PSCTRL1,
393 WM8523_SYS_ENA_MASK, 3);
394 break;
395
396 case SND_SOC_BIAS_STANDBY:
397 if (codec->bias_level == SND_SOC_BIAS_OFF) {
398 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
399 wm8523->supplies);
400 if (ret != 0) {
401 dev_err(codec->dev,
402 "Failed to enable supplies: %d\n",
403 ret);
404 return ret;
405 }
406
407 /* Initial power up */
408 snd_soc_update_bits(codec, WM8523_PSCTRL1,
409 WM8523_SYS_ENA_MASK, 1);
410
411 /* Sync back default/cached values */
412 for (i = WM8523_AIF_CTRL1;
413 i < WM8523_MAX_REGISTER; i++)
414 wm8523_write(codec, i, wm8523->reg_cache[i]);
415
416
417 msleep(100);
418 }
419
420 /* Power up to mute */
421 snd_soc_update_bits(codec, WM8523_PSCTRL1,
422 WM8523_SYS_ENA_MASK, 2);
423
424 break;
425
426 case SND_SOC_BIAS_OFF:
427 /* The chip runs through the power down sequence for us. */
428 snd_soc_update_bits(codec, WM8523_PSCTRL1,
429 WM8523_SYS_ENA_MASK, 0);
430 msleep(100);
431
432 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
433 wm8523->supplies);
434 break;
435 }
436 codec->bias_level = level;
437 return 0;
438}
439
440#define WM8523_RATES SNDRV_PCM_RATE_8000_192000
441
442#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
443 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
444
445static struct snd_soc_dai_ops wm8523_dai_ops = {
446 .startup = wm8523_startup,
447 .hw_params = wm8523_hw_params,
448 .set_sysclk = wm8523_set_dai_sysclk,
449 .set_fmt = wm8523_set_dai_fmt,
450};
451
452struct snd_soc_dai wm8523_dai = {
453 .name = "WM8523",
454 .playback = {
455 .stream_name = "Playback",
456 .channels_min = 2, /* Mono modes not yet supported */
457 .channels_max = 2,
458 .rates = WM8523_RATES,
459 .formats = WM8523_FORMATS,
460 },
461 .ops = &wm8523_dai_ops,
462};
463EXPORT_SYMBOL_GPL(wm8523_dai);
464
465#ifdef CONFIG_PM
466static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
467{
468 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
469 struct snd_soc_codec *codec = socdev->card->codec;
470
471 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
472 return 0;
473}
474
475static int wm8523_resume(struct platform_device *pdev)
476{
477 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
478 struct snd_soc_codec *codec = socdev->card->codec;
479
480 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
481
482 return 0;
483}
484#else
485#define wm8523_suspend NULL
486#define wm8523_resume NULL
487#endif
488
489static int wm8523_probe(struct platform_device *pdev)
490{
491 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
492 struct snd_soc_codec *codec;
493 int ret = 0;
494
495 if (wm8523_codec == NULL) {
496 dev_err(&pdev->dev, "Codec device not registered\n");
497 return -ENODEV;
498 }
499
500 socdev->card->codec = wm8523_codec;
501 codec = wm8523_codec;
502
503 /* register pcms */
504 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
505 if (ret < 0) {
506 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
507 goto pcm_err;
508 }
509
510 snd_soc_add_controls(codec, wm8523_snd_controls,
511 ARRAY_SIZE(wm8523_snd_controls));
512 wm8523_add_widgets(codec);
513 ret = snd_soc_init_card(socdev);
514 if (ret < 0) {
515 dev_err(codec->dev, "failed to register card: %d\n", ret);
516 goto card_err;
517 }
518
519 return ret;
520
521card_err:
522 snd_soc_free_pcms(socdev);
523 snd_soc_dapm_free(socdev);
524pcm_err:
525 return ret;
526}
527
528static int wm8523_remove(struct platform_device *pdev)
529{
530 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
531
532 snd_soc_free_pcms(socdev);
533 snd_soc_dapm_free(socdev);
534
535 return 0;
536}
537
538struct snd_soc_codec_device soc_codec_dev_wm8523 = {
539 .probe = wm8523_probe,
540 .remove = wm8523_remove,
541 .suspend = wm8523_suspend,
542 .resume = wm8523_resume,
543};
544EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
545
546static int wm8523_register(struct wm8523_priv *wm8523)
547{
548 int ret;
549 struct snd_soc_codec *codec = &wm8523->codec;
550 int i;
551
552 if (wm8523_codec) {
553 dev_err(codec->dev, "Another WM8523 is registered\n");
554 return -EINVAL;
555 }
556
557 mutex_init(&codec->mutex);
558 INIT_LIST_HEAD(&codec->dapm_widgets);
559 INIT_LIST_HEAD(&codec->dapm_paths);
560
561 codec->private_data = wm8523;
562 codec->name = "WM8523";
563 codec->owner = THIS_MODULE;
564 codec->read = wm8523_read;
565 codec->write = wm8523_write;
566 codec->bias_level = SND_SOC_BIAS_OFF;
567 codec->set_bias_level = wm8523_set_bias_level;
568 codec->dai = &wm8523_dai;
569 codec->num_dai = 1;
570 codec->reg_cache_size = WM8523_REGISTER_COUNT;
571 codec->reg_cache = &wm8523->reg_cache;
572
573 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
574 wm8523->rate_constraint.count =
575 ARRAY_SIZE(wm8523->rate_constraint_list);
576
577 memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
578
579 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
580 wm8523->supplies[i].supply = wm8523_supply_names[i];
581
582 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
583 wm8523->supplies);
584 if (ret != 0) {
585 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
586 goto err;
587 }
588
589 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
590 wm8523->supplies);
591 if (ret != 0) {
592 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
593 goto err_get;
594 }
595
596 ret = wm8523_read(codec, WM8523_DEVICE_ID);
597 if (ret < 0) {
598 dev_err(codec->dev, "Failed to read ID register\n");
599 goto err_enable;
600 }
601 if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
602 dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
603 ret = -EINVAL;
604 goto err_enable;
605 }
606
607 ret = wm8523_read(codec, WM8523_REVISION);
608 if (ret < 0) {
609 dev_err(codec->dev, "Failed to read revision register\n");
610 goto err_enable;
611 }
612 dev_info(codec->dev, "revision %c\n",
613 (ret & WM8523_CHIP_REV_MASK) + 'A');
614
615 ret = wm8523_reset(codec);
616 if (ret < 0) {
617 dev_err(codec->dev, "Failed to issue reset\n");
618 goto err_enable;
619 }
620
621 wm8523_dai.dev = codec->dev;
622
623 /* Change some default settings - latch VU and enable ZC */
624 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
625 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
626
627 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
628
629 /* Bias level configuration will have done an extra enable */
630 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
631
632 wm8523_codec = codec;
633
634 ret = snd_soc_register_codec(codec);
635 if (ret != 0) {
636 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
637 return ret;
638 }
639
640 ret = snd_soc_register_dai(&wm8523_dai);
641 if (ret != 0) {
642 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
643 snd_soc_unregister_codec(codec);
644 return ret;
645 }
646
647 return 0;
648
649err_enable:
650 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
651err_get:
652 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
653err:
654 kfree(wm8523);
655 return ret;
656}
657
658static void wm8523_unregister(struct wm8523_priv *wm8523)
659{
660 wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
661 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
662 snd_soc_unregister_dai(&wm8523_dai);
663 snd_soc_unregister_codec(&wm8523->codec);
664 kfree(wm8523);
665 wm8523_codec = NULL;
666}
667
668#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
669static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
670 const struct i2c_device_id *id)
671{
672 struct wm8523_priv *wm8523;
673 struct snd_soc_codec *codec;
674
675 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
676 if (wm8523 == NULL)
677 return -ENOMEM;
678
679 codec = &wm8523->codec;
680 codec->hw_write = (hw_write_t)i2c_master_send;
681
682 i2c_set_clientdata(i2c, wm8523);
683 codec->control_data = i2c;
684
685 codec->dev = &i2c->dev;
686
687 return wm8523_register(wm8523);
688}
689
690static __devexit int wm8523_i2c_remove(struct i2c_client *client)
691{
692 struct wm8523_priv *wm8523 = i2c_get_clientdata(client);
693 wm8523_unregister(wm8523);
694 return 0;
695}
696
697#ifdef CONFIG_PM
698static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
699{
700 return snd_soc_suspend_device(&i2c->dev);
701}
702
703static int wm8523_i2c_resume(struct i2c_client *i2c)
704{
705 return snd_soc_resume_device(&i2c->dev);
706}
707#else
708#define wm8523_i2c_suspend NULL
709#define wm8523_i2c_resume NULL
710#endif
711
712static const struct i2c_device_id wm8523_i2c_id[] = {
713 { "wm8523", 0 },
714 { }
715};
716MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
717
718static struct i2c_driver wm8523_i2c_driver = {
719 .driver = {
720 .name = "WM8523",
721 .owner = THIS_MODULE,
722 },
723 .probe = wm8523_i2c_probe,
724 .remove = __devexit_p(wm8523_i2c_remove),
725 .suspend = wm8523_i2c_suspend,
726 .resume = wm8523_i2c_resume,
727 .id_table = wm8523_i2c_id,
728};
729#endif
730
731static int __init wm8523_modinit(void)
732{
733 int ret;
734#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
735 ret = i2c_add_driver(&wm8523_i2c_driver);
736 if (ret != 0) {
737 printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
738 ret);
739 }
740#endif
741 return 0;
742}
743module_init(wm8523_modinit);
744
745static void __exit wm8523_exit(void)
746{
747#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
748 i2c_del_driver(&wm8523_i2c_driver);
749#endif
750}
751module_exit(wm8523_exit);
752
753MODULE_DESCRIPTION("ASoC WM8523 driver");
754MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
755MODULE_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 86c4b24db817..97b9ed95d289 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,15 +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/* 208/*
200 * read wm8580 register cache 209 * read wm8580 register cache
201 */ 210 */
@@ -922,11 +931,28 @@ static int wm8580_register(struct wm8580_priv *wm8580)
922 931
923 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); 932 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
924 933
934 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
935 wm8580->supplies[i].supply = wm8580_supply_names[i];
936
937 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
938 wm8580->supplies);
939 if (ret != 0) {
940 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
941 goto err;
942 }
943
944 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
945 wm8580->supplies);
946 if (ret != 0) {
947 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
948 goto err_regulator_get;
949 }
950
925 /* Get the codec into a known state */ 951 /* Get the codec into a known state */
926 ret = wm8580_write(codec, WM8580_RESET, 0); 952 ret = wm8580_write(codec, WM8580_RESET, 0);
927 if (ret != 0) { 953 if (ret != 0) {
928 dev_err(codec->dev, "Failed to reset codec: %d\n", ret); 954 dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
929 goto err; 955 goto err_regulator_enable;
930 } 956 }
931 957
932 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) 958 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
@@ -939,7 +965,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
939 ret = snd_soc_register_codec(codec); 965 ret = snd_soc_register_codec(codec);
940 if (ret != 0) { 966 if (ret != 0) {
941 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 967 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
942 goto err; 968 goto err_regulator_enable;
943 } 969 }
944 970
945 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 971 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
@@ -952,6 +978,10 @@ static int wm8580_register(struct wm8580_priv *wm8580)
952 978
953err_codec: 979err_codec:
954 snd_soc_unregister_codec(codec); 980 snd_soc_unregister_codec(codec);
981err_regulator_enable:
982 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
983err_regulator_get:
984 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
955err: 985err:
956 kfree(wm8580); 986 kfree(wm8580);
957 return ret; 987 return ret;
@@ -962,6 +992,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580)
962 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); 992 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
963 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 993 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
964 snd_soc_unregister_codec(&wm8580->codec); 994 snd_soc_unregister_codec(&wm8580->codec);
995 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
996 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
965 kfree(wm8580); 997 kfree(wm8580);
966 wm8580_codec = NULL; 998 wm8580_codec = NULL;
967} 999}
@@ -995,6 +1027,21 @@ static int wm8580_i2c_remove(struct i2c_client *client)
995 return 0; 1027 return 0;
996} 1028}
997 1029
1030#ifdef CONFIG_PM
1031static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1032{
1033 return snd_soc_suspend_device(&client->dev);
1034}
1035
1036static int wm8580_i2c_resume(struct i2c_client *client)
1037{
1038 return snd_soc_resume_device(&client->dev);
1039}
1040#else
1041#define wm8580_i2c_suspend NULL
1042#define wm8580_i2c_resume NULL
1043#endif
1044
998static const struct i2c_device_id wm8580_i2c_id[] = { 1045static const struct i2c_device_id wm8580_i2c_id[] = {
999 { "wm8580", 0 }, 1046 { "wm8580", 0 },
1000 { } 1047 { }
@@ -1008,6 +1055,8 @@ static struct i2c_driver wm8580_i2c_driver = {
1008 }, 1055 },
1009 .probe = wm8580_i2c_probe, 1056 .probe = wm8580_i2c_probe,
1010 .remove = wm8580_i2c_remove, 1057 .remove = wm8580_i2c_remove,
1058 .suspend = wm8580_i2c_suspend,
1059 .resume = wm8580_i2c_resume,
1011 .id_table = wm8580_i2c_id, 1060 .id_table = wm8580_i2c_id,
1012}; 1061};
1013#endif 1062#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7a205876ef4f..156002852078 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
@@ -113,20 +114,26 @@ static const struct soc_enum wm8731_enum[] = {
113 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), 114 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
114}; 115};
115 116
117static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
118static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
119static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
120
116static const struct snd_kcontrol_new wm8731_snd_controls[] = { 121static const struct snd_kcontrol_new wm8731_snd_controls[] = {
117 122
118SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, 123SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
119 0, 127, 0), 124 0, 127, 0, out_tlv),
120SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 125SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
121 7, 1, 0), 126 7, 1, 0),
122 127
123SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0), 128SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
129 in_tlv),
124SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), 130SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
125 131
126SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), 132SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
127SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1), 133SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
128 134
129SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1), 135SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
136 sidetone_tlv),
130 137
131SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), 138SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
132SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), 139SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
@@ -457,9 +464,11 @@ struct snd_soc_dai wm8731_dai = {
457 .rates = WM8731_RATES, 464 .rates = WM8731_RATES,
458 .formats = WM8731_FORMATS,}, 465 .formats = WM8731_FORMATS,},
459 .ops = &wm8731_dai_ops, 466 .ops = &wm8731_dai_ops,
467 .symmetric_rates = 1,
460}; 468};
461EXPORT_SYMBOL_GPL(wm8731_dai); 469EXPORT_SYMBOL_GPL(wm8731_dai);
462 470
471#ifdef CONFIG_PM
463static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) 472static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
464{ 473{
465 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 474 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -488,6 +497,10 @@ static int wm8731_resume(struct platform_device *pdev)
488 wm8731_set_bias_level(codec, codec->suspend_bias_level); 497 wm8731_set_bias_level(codec, codec->suspend_bias_level);
489 return 0; 498 return 0;
490} 499}
500#else
501#define wm8731_suspend NULL
502#define wm8731_resume NULL
503#endif
491 504
492static int wm8731_probe(struct platform_device *pdev) 505static int wm8731_probe(struct platform_device *pdev)
493{ 506{
@@ -555,7 +568,8 @@ static int wm8731_register(struct wm8731_priv *wm8731)
555 568
556 if (wm8731_codec) { 569 if (wm8731_codec) {
557 dev_err(codec->dev, "Another WM8731 is registered\n"); 570 dev_err(codec->dev, "Another WM8731 is registered\n");
558 return -EINVAL; 571 ret = -EINVAL;
572 goto err;
559 } 573 }
560 574
561 mutex_init(&codec->mutex); 575 mutex_init(&codec->mutex);
@@ -578,8 +592,8 @@ static int wm8731_register(struct wm8731_priv *wm8731)
578 592
579 ret = wm8731_reset(codec); 593 ret = wm8731_reset(codec);
580 if (ret < 0) { 594 if (ret < 0) {
581 dev_err(codec->dev, "Failed to issue reset\n"); 595 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
582 return ret; 596 goto err;
583 } 597 }
584 598
585 wm8731_dai.dev = codec->dev; 599 wm8731_dai.dev = codec->dev;
@@ -605,17 +619,23 @@ static int wm8731_register(struct wm8731_priv *wm8731)
605 ret = snd_soc_register_codec(codec); 619 ret = snd_soc_register_codec(codec);
606 if (ret != 0) { 620 if (ret != 0) {
607 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 621 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
608 return ret; 622 goto err;
609 } 623 }
610 624
611 ret = snd_soc_register_dai(&wm8731_dai); 625 ret = snd_soc_register_dai(&wm8731_dai);
612 if (ret != 0) { 626 if (ret != 0) {
613 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 627 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
614 snd_soc_unregister_codec(codec); 628 snd_soc_unregister_codec(codec);
615 return ret; 629 goto err_codec;
616 } 630 }
617 631
618 return 0; 632 return 0;
633
634err_codec:
635 snd_soc_unregister_codec(codec);
636err:
637 kfree(wm8731);
638 return ret;
619} 639}
620 640
621static void wm8731_unregister(struct wm8731_priv *wm8731) 641static void wm8731_unregister(struct wm8731_priv *wm8731)
@@ -680,6 +700,21 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
680 return 0; 700 return 0;
681} 701}
682 702
703#ifdef CONFIG_PM
704static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
705{
706 return snd_soc_suspend_device(&spi->dev);
707}
708
709static int wm8731_spi_resume(struct spi_device *spi)
710{
711 return snd_soc_resume_device(&spi->dev);
712}
713#else
714#define wm8731_spi_suspend NULL
715#define wm8731_spi_resume NULL
716#endif
717
683static struct spi_driver wm8731_spi_driver = { 718static struct spi_driver wm8731_spi_driver = {
684 .driver = { 719 .driver = {
685 .name = "wm8731", 720 .name = "wm8731",
@@ -687,6 +722,8 @@ static struct spi_driver wm8731_spi_driver = {
687 .owner = THIS_MODULE, 722 .owner = THIS_MODULE,
688 }, 723 },
689 .probe = wm8731_spi_probe, 724 .probe = wm8731_spi_probe,
725 .suspend = wm8731_spi_suspend,
726 .resume = wm8731_spi_resume,
690 .remove = __devexit_p(wm8731_spi_remove), 727 .remove = __devexit_p(wm8731_spi_remove),
691}; 728};
692#endif /* CONFIG_SPI_MASTER */ 729#endif /* CONFIG_SPI_MASTER */
@@ -720,6 +757,21 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
720 return 0; 757 return 0;
721} 758}
722 759
760#ifdef CONFIG_PM
761static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
762{
763 return snd_soc_suspend_device(&i2c->dev);
764}
765
766static int wm8731_i2c_resume(struct i2c_client *i2c)
767{
768 return snd_soc_resume_device(&i2c->dev);
769}
770#else
771#define wm8731_i2c_suspend NULL
772#define wm8731_i2c_resume NULL
773#endif
774
723static const struct i2c_device_id wm8731_i2c_id[] = { 775static const struct i2c_device_id wm8731_i2c_id[] = {
724 { "wm8731", 0 }, 776 { "wm8731", 0 },
725 { } 777 { }
@@ -733,6 +785,8 @@ static struct i2c_driver wm8731_i2c_driver = {
733 }, 785 },
734 .probe = wm8731_i2c_probe, 786 .probe = wm8731_i2c_probe,
735 .remove = __devexit_p(wm8731_i2c_remove), 787 .remove = __devexit_p(wm8731_i2c_remove),
788 .suspend = wm8731_i2c_suspend,
789 .resume = wm8731_i2c_resume,
736 .id_table = wm8731_i2c_id, 790 .id_table = wm8731_i2c_id,
737}; 791};
738#endif 792#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 49c4b2898aff..d80d414cfbbd 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -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
@@ -1834,6 +1851,22 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
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..ee12bf824a40
--- /dev/null
+++ b/sound/soc/codecs/wm8776.c
@@ -0,0 +1,781 @@
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
55/*
56 * read wm8776 register cache
57 */
58static inline unsigned int wm8776_read_reg_cache(struct snd_soc_codec *codec,
59 unsigned int reg)
60{
61 u16 *cache = codec->reg_cache;
62 if (reg >= WM8776_CACHEREGNUM)
63 return -1;
64 return cache[reg];
65}
66
67/*
68 * write wm8776 register cache
69 */
70static inline void wm8776_write_reg_cache(struct snd_soc_codec *codec,
71 u16 reg, unsigned int value)
72{
73 u16 *cache = codec->reg_cache;
74 if (reg >= WM8776_CACHEREGNUM)
75 return;
76 cache[reg] = value;
77}
78
79/*
80 * write to the WM8776 register space
81 */
82static int wm8776_write(struct snd_soc_codec *codec, unsigned int reg,
83 unsigned int value)
84{
85 u8 data[2];
86
87 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
88 data[1] = value & 0x00ff;
89
90 wm8776_write_reg_cache(codec, reg, value);
91 if (codec->hw_write(codec->control_data, data, 2) == 2)
92 return 0;
93 else
94 return -EIO;
95}
96
97static int wm8776_reset(struct snd_soc_codec *codec)
98{
99 return wm8776_write(codec, WM8776_RESET, 0);
100}
101
102static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1);
103static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
104static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);
105
106static const struct snd_kcontrol_new wm8776_snd_controls[] = {
107SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL,
108 0, 127, 0, hp_tlv),
109SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL,
110 0, 255, 0, dac_tlv),
111SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0),
112
113SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0),
114
115SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL,
116 0, 255, 0, adc_tlv),
117SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1),
118SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0),
119SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1),
120};
121
122static const struct snd_kcontrol_new inmix_controls[] = {
123SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0),
124SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0),
125SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0),
126SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0),
127SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0),
128};
129
130static const struct snd_kcontrol_new outmix_controls[] = {
131SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0),
132SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0),
133SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0),
134};
135
136static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
137SND_SOC_DAPM_INPUT("AUX"),
138SND_SOC_DAPM_INPUT("AUX"),
139
140SND_SOC_DAPM_INPUT("AIN1"),
141SND_SOC_DAPM_INPUT("AIN2"),
142SND_SOC_DAPM_INPUT("AIN3"),
143SND_SOC_DAPM_INPUT("AIN4"),
144SND_SOC_DAPM_INPUT("AIN5"),
145
146SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1,
147 inmix_controls, ARRAY_SIZE(inmix_controls)),
148
149SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1),
150SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1),
151
152SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
153 outmix_controls, ARRAY_SIZE(outmix_controls)),
154
155SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0),
156
157SND_SOC_DAPM_OUTPUT("VOUT"),
158
159SND_SOC_DAPM_OUTPUT("HPOUTL"),
160SND_SOC_DAPM_OUTPUT("HPOUTR"),
161};
162
163static const struct snd_soc_dapm_route routes[] = {
164 { "Input Mixer", "AIN1 Switch", "AIN1" },
165 { "Input Mixer", "AIN2 Switch", "AIN2" },
166 { "Input Mixer", "AIN3 Switch", "AIN3" },
167 { "Input Mixer", "AIN4 Switch", "AIN4" },
168 { "Input Mixer", "AIN5 Switch", "AIN5" },
169
170 { "ADC", NULL, "Input Mixer" },
171
172 { "Output Mixer", "DAC Switch", "DAC" },
173 { "Output Mixer", "AUX Switch", "AUX" },
174 { "Output Mixer", "Bypass Switch", "Input Mixer" },
175
176 { "VOUT", NULL, "Output Mixer" },
177
178 { "Headphone PGA", NULL, "Output Mixer" },
179
180 { "HPOUTL", NULL, "Headphone PGA" },
181 { "HPOUTR", NULL, "Headphone PGA" },
182};
183
184static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
185{
186 struct snd_soc_codec *codec = dai->codec;
187 int reg, iface, master;
188
189 switch (dai->id) {
190 case WM8776_DAI_DAC:
191 reg = WM8776_DACIFCTRL;
192 master = 0x80;
193 break;
194 case WM8776_DAI_ADC:
195 reg = WM8776_ADCIFCTRL;
196 master = 0x100;
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 iface = 0;
203
204 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
205 case SND_SOC_DAIFMT_CBM_CFM:
206 break;
207 case SND_SOC_DAIFMT_CBS_CFS:
208 master = 0;
209 break;
210 default:
211 return -EINVAL;
212 }
213
214 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
215 case SND_SOC_DAIFMT_I2S:
216 iface |= 0x0002;
217 break;
218 case SND_SOC_DAIFMT_RIGHT_J:
219 break;
220 case SND_SOC_DAIFMT_LEFT_J:
221 iface |= 0x0001;
222 break;
223 /* FIXME: CHECK A/B */
224 case SND_SOC_DAIFMT_DSP_A:
225 iface |= 0x0003;
226 break;
227 case SND_SOC_DAIFMT_DSP_B:
228 iface |= 0x0007;
229 break;
230 default:
231 return -EINVAL;
232 }
233
234 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
235 case SND_SOC_DAIFMT_NB_NF:
236 break;
237 case SND_SOC_DAIFMT_IB_IF:
238 iface |= 0x00c;
239 break;
240 case SND_SOC_DAIFMT_IB_NF:
241 iface |= 0x008;
242 break;
243 case SND_SOC_DAIFMT_NB_IF:
244 iface |= 0x004;
245 break;
246 default:
247 return -EINVAL;
248 }
249
250 /* Finally, write out the values */
251 snd_soc_update_bits(codec, reg, 0xf, iface);
252 snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master);
253
254 return 0;
255}
256
257static int mclk_ratios[] = {
258 128,
259 192,
260 256,
261 384,
262 512,
263 768,
264};
265
266static int wm8776_hw_params(struct snd_pcm_substream *substream,
267 struct snd_pcm_hw_params *params,
268 struct snd_soc_dai *dai)
269{
270 struct snd_soc_codec *codec = dai->codec;
271 struct wm8776_priv *wm8776 = codec->private_data;
272 int iface_reg, iface;
273 int ratio_shift, master;
274 int i;
275
276 iface = 0;
277
278 switch (dai->id) {
279 case WM8776_DAI_DAC:
280 iface_reg = WM8776_DACIFCTRL;
281 master = 0x80;
282 ratio_shift = 4;
283 break;
284 case WM8776_DAI_ADC:
285 iface_reg = WM8776_ADCIFCTRL;
286 master = 0x100;
287 ratio_shift = 0;
288 break;
289 default:
290 return -EINVAL;
291 }
292
293
294 /* Set word length */
295 switch (params_format(params)) {
296 case SNDRV_PCM_FORMAT_S16_LE:
297 break;
298 case SNDRV_PCM_FORMAT_S20_3LE:
299 iface |= 0x10;
300 break;
301 case SNDRV_PCM_FORMAT_S24_LE:
302 iface |= 0x20;
303 break;
304 case SNDRV_PCM_FORMAT_S32_LE:
305 iface |= 0x30;
306 break;
307 }
308
309 /* Only need to set MCLK/LRCLK ratio if we're master */
310 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
311 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
312 if (wm8776->sysclk[dai->id] / params_rate(params)
313 == mclk_ratios[i])
314 break;
315 }
316
317 if (i == ARRAY_SIZE(mclk_ratios)) {
318 dev_err(codec->dev,
319 "Unable to configure MCLK ratio %d/%d\n",
320 wm8776->sysclk[dai->id], params_rate(params));
321 return -EINVAL;
322 }
323
324 dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
325
326 snd_soc_update_bits(codec, WM8776_MSTRCTRL,
327 0x7 << ratio_shift, i << ratio_shift);
328 } else {
329 dev_dbg(codec->dev, "DAI in slave mode\n");
330 }
331
332 snd_soc_update_bits(codec, iface_reg, 0x30, iface);
333
334 return 0;
335}
336
337static int wm8776_mute(struct snd_soc_dai *dai, int mute)
338{
339 struct snd_soc_codec *codec = dai->codec;
340
341 return snd_soc_write(codec, WM8776_DACMUTE, !!mute);
342}
343
344static int wm8776_set_sysclk(struct snd_soc_dai *dai,
345 int clk_id, unsigned int freq, int dir)
346{
347 struct snd_soc_codec *codec = dai->codec;
348 struct wm8776_priv *wm8776 = codec->private_data;
349
350 BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
351
352 wm8776->sysclk[dai->id] = freq;
353
354 return 0;
355}
356
357static int wm8776_set_bias_level(struct snd_soc_codec *codec,
358 enum snd_soc_bias_level level)
359{
360 switch (level) {
361 case SND_SOC_BIAS_ON:
362 break;
363 case SND_SOC_BIAS_PREPARE:
364 break;
365 case SND_SOC_BIAS_STANDBY:
366 if (codec->bias_level == SND_SOC_BIAS_OFF) {
367 /* Disable the global powerdown; DAPM does the rest */
368 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
369 }
370
371 break;
372 case SND_SOC_BIAS_OFF:
373 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1);
374 break;
375 }
376
377 codec->bias_level = level;
378 return 0;
379}
380
381#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
382 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
383 SNDRV_PCM_RATE_96000)
384
385
386#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
387 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
388
389static struct snd_soc_dai_ops wm8776_dac_ops = {
390 .digital_mute = wm8776_mute,
391 .hw_params = wm8776_hw_params,
392 .set_fmt = wm8776_set_fmt,
393 .set_sysclk = wm8776_set_sysclk,
394};
395
396static struct snd_soc_dai_ops wm8776_adc_ops = {
397 .hw_params = wm8776_hw_params,
398 .set_fmt = wm8776_set_fmt,
399 .set_sysclk = wm8776_set_sysclk,
400};
401
402struct snd_soc_dai wm8776_dai[] = {
403 {
404 .name = "WM8776 Playback",
405 .id = WM8776_DAI_DAC,
406 .playback = {
407 .stream_name = "Playback",
408 .channels_min = 2,
409 .channels_max = 2,
410 .rates = WM8776_RATES,
411 .formats = WM8776_FORMATS,
412 },
413 .ops = &wm8776_dac_ops,
414 },
415 {
416 .name = "WM8776 Capture",
417 .id = WM8776_DAI_ADC,
418 .capture = {
419 .stream_name = "Capture",
420 .channels_min = 2,
421 .channels_max = 2,
422 .rates = WM8776_RATES,
423 .formats = WM8776_FORMATS,
424 },
425 .ops = &wm8776_adc_ops,
426 },
427};
428EXPORT_SYMBOL_GPL(wm8776_dai);
429
430#ifdef CONFIG_PM
431static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
432{
433 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
434 struct snd_soc_codec *codec = socdev->card->codec;
435
436 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
437
438 return 0;
439}
440
441static int wm8776_resume(struct platform_device *pdev)
442{
443 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
444 struct snd_soc_codec *codec = socdev->card->codec;
445 int i;
446 u8 data[2];
447 u16 *cache = codec->reg_cache;
448
449 /* Sync reg_cache with the hardware */
450 for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
451 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
452 data[1] = cache[i] & 0x00ff;
453 codec->hw_write(codec->control_data, data, 2);
454 }
455
456 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
457
458 return 0;
459}
460#else
461#define wm8776_suspend NULL
462#define wm8776_resume NULL
463#endif
464
465static int wm8776_probe(struct platform_device *pdev)
466{
467 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
468 struct snd_soc_codec *codec;
469 int ret = 0;
470
471 if (wm8776_codec == NULL) {
472 dev_err(&pdev->dev, "Codec device not registered\n");
473 return -ENODEV;
474 }
475
476 socdev->card->codec = wm8776_codec;
477 codec = wm8776_codec;
478
479 /* register pcms */
480 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
481 if (ret < 0) {
482 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
483 goto pcm_err;
484 }
485
486 snd_soc_add_controls(codec, wm8776_snd_controls,
487 ARRAY_SIZE(wm8776_snd_controls));
488 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
489 ARRAY_SIZE(wm8776_dapm_widgets));
490 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
491
492 ret = snd_soc_init_card(socdev);
493 if (ret < 0) {
494 dev_err(codec->dev, "failed to register card: %d\n", ret);
495 goto card_err;
496 }
497
498 return ret;
499
500card_err:
501 snd_soc_free_pcms(socdev);
502 snd_soc_dapm_free(socdev);
503pcm_err:
504 return ret;
505}
506
507/* power down chip */
508static int wm8776_remove(struct platform_device *pdev)
509{
510 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
511
512 snd_soc_free_pcms(socdev);
513 snd_soc_dapm_free(socdev);
514
515 return 0;
516}
517
518struct snd_soc_codec_device soc_codec_dev_wm8776 = {
519 .probe = wm8776_probe,
520 .remove = wm8776_remove,
521 .suspend = wm8776_suspend,
522 .resume = wm8776_resume,
523};
524EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
525
526static int wm8776_register(struct wm8776_priv *wm8776)
527{
528 int ret, i;
529 struct snd_soc_codec *codec = &wm8776->codec;
530
531 if (wm8776_codec) {
532 dev_err(codec->dev, "Another WM8776 is registered\n");
533 ret = -EINVAL;
534 goto err;
535 }
536
537 mutex_init(&codec->mutex);
538 INIT_LIST_HEAD(&codec->dapm_widgets);
539 INIT_LIST_HEAD(&codec->dapm_paths);
540
541 codec->private_data = wm8776;
542 codec->name = "WM8776";
543 codec->owner = THIS_MODULE;
544 codec->read = wm8776_read_reg_cache;
545 codec->write = wm8776_write;
546 codec->bias_level = SND_SOC_BIAS_OFF;
547 codec->set_bias_level = wm8776_set_bias_level;
548 codec->dai = wm8776_dai;
549 codec->num_dai = ARRAY_SIZE(wm8776_dai);
550 codec->reg_cache_size = WM8776_CACHEREGNUM;
551 codec->reg_cache = &wm8776->reg_cache;
552
553 memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
554
555 for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
556 wm8776_dai[i].dev = codec->dev;
557
558 ret = wm8776_reset(codec);
559 if (ret < 0) {
560 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
561 goto err;
562 }
563
564 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
565
566 /* Latch the update bits; right channel only since we always
567 * update both. */
568 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
569 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
570
571 wm8776_codec = codec;
572
573 ret = snd_soc_register_codec(codec);
574 if (ret != 0) {
575 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
576 goto err;
577 }
578
579 ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
580 if (ret != 0) {
581 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
582 goto err_codec;
583 }
584
585 return 0;
586
587err_codec:
588 snd_soc_unregister_codec(codec);
589err:
590 kfree(wm8776);
591 return ret;
592}
593
594static void wm8776_unregister(struct wm8776_priv *wm8776)
595{
596 wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
597 snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
598 snd_soc_unregister_codec(&wm8776->codec);
599 kfree(wm8776);
600 wm8776_codec = NULL;
601}
602
603#if defined(CONFIG_SPI_MASTER)
604static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
605{
606 struct spi_transfer t;
607 struct spi_message m;
608 u8 msg[2];
609
610 if (len <= 0)
611 return 0;
612
613 msg[0] = data[0];
614 msg[1] = data[1];
615
616 spi_message_init(&m);
617 memset(&t, 0, (sizeof t));
618
619 t.tx_buf = &msg[0];
620 t.len = len;
621
622 spi_message_add_tail(&t, &m);
623 spi_sync(spi, &m);
624
625 return len;
626}
627
628static int __devinit wm8776_spi_probe(struct spi_device *spi)
629{
630 struct snd_soc_codec *codec;
631 struct wm8776_priv *wm8776;
632
633 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
634 if (wm8776 == NULL)
635 return -ENOMEM;
636
637 codec = &wm8776->codec;
638 codec->control_data = spi;
639 codec->hw_write = (hw_write_t)wm8776_spi_write;
640 codec->dev = &spi->dev;
641
642 dev_set_drvdata(&spi->dev, wm8776);
643
644 return wm8776_register(wm8776);
645}
646
647static int __devexit wm8776_spi_remove(struct spi_device *spi)
648{
649 struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
650
651 wm8776_unregister(wm8776);
652
653 return 0;
654}
655
656#ifdef CONFIG_PM
657static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
658{
659 return snd_soc_suspend_device(&spi->dev);
660}
661
662static int wm8776_spi_resume(struct spi_device *spi)
663{
664 return snd_soc_resume_device(&spi->dev);
665}
666#else
667#define wm8776_spi_suspend NULL
668#define wm8776_spi_resume NULL
669#endif
670
671static struct spi_driver wm8776_spi_driver = {
672 .driver = {
673 .name = "wm8776",
674 .bus = &spi_bus_type,
675 .owner = THIS_MODULE,
676 },
677 .probe = wm8776_spi_probe,
678 .suspend = wm8776_spi_suspend,
679 .resume = wm8776_spi_resume,
680 .remove = __devexit_p(wm8776_spi_remove),
681};
682#endif /* CONFIG_SPI_MASTER */
683
684#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
685static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
686 const struct i2c_device_id *id)
687{
688 struct wm8776_priv *wm8776;
689 struct snd_soc_codec *codec;
690
691 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
692 if (wm8776 == NULL)
693 return -ENOMEM;
694
695 codec = &wm8776->codec;
696 codec->hw_write = (hw_write_t)i2c_master_send;
697
698 i2c_set_clientdata(i2c, wm8776);
699 codec->control_data = i2c;
700
701 codec->dev = &i2c->dev;
702
703 return wm8776_register(wm8776);
704}
705
706static __devexit int wm8776_i2c_remove(struct i2c_client *client)
707{
708 struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
709 wm8776_unregister(wm8776);
710 return 0;
711}
712
713#ifdef CONFIG_PM
714static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
715{
716 return snd_soc_suspend_device(&i2c->dev);
717}
718
719static int wm8776_i2c_resume(struct i2c_client *i2c)
720{
721 return snd_soc_resume_device(&i2c->dev);
722}
723#else
724#define wm8776_i2c_suspend NULL
725#define wm8776_i2c_resume NULL
726#endif
727
728static const struct i2c_device_id wm8776_i2c_id[] = {
729 { "wm8776", 0 },
730 { }
731};
732MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
733
734static struct i2c_driver wm8776_i2c_driver = {
735 .driver = {
736 .name = "wm8776",
737 .owner = THIS_MODULE,
738 },
739 .probe = wm8776_i2c_probe,
740 .remove = __devexit_p(wm8776_i2c_remove),
741 .suspend = wm8776_i2c_suspend,
742 .resume = wm8776_i2c_resume,
743 .id_table = wm8776_i2c_id,
744};
745#endif
746
747static int __init wm8776_modinit(void)
748{
749 int ret;
750#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
751 ret = i2c_add_driver(&wm8776_i2c_driver);
752 if (ret != 0) {
753 printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n",
754 ret);
755 }
756#endif
757#if defined(CONFIG_SPI_MASTER)
758 ret = spi_register_driver(&wm8776_spi_driver);
759 if (ret != 0) {
760 printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n",
761 ret);
762 }
763#endif
764 return 0;
765}
766module_init(wm8776_modinit);
767
768static void __exit wm8776_exit(void)
769{
770#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
771 i2c_del_driver(&wm8776_i2c_driver);
772#endif
773#if defined(CONFIG_SPI_MASTER)
774 spi_unregister_driver(&wm8776_spi_driver);
775#endif
776}
777module_exit(wm8776_exit);
778
779MODULE_DESCRIPTION("ASoC WM8776 driver");
780MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
781MODULE_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 3c78945244b8..ac308993ac5a 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
@@ -439,7 +440,6 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
439SOC_ENUM("DAC Mute Rate", dac_mute_rate), 440SOC_ENUM("DAC Mute Rate", dac_mute_rate),
440SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), 441SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
441SOC_ENUM("DAC Deemphasis", dac_deemphasis), 442SOC_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, 443SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
444 12, 1, 0), 444 12, 1, 0),
445 445
@@ -743,6 +743,17 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
743 743
744 wm8900_write(codec, WM8900_REG_AUDIO1, reg); 744 wm8900_write(codec, WM8900_REG_AUDIO1, reg);
745 745
746 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
747 reg = wm8900_read(codec, WM8900_REG_DACCTRL);
748
749 if (params_rate(params) <= 24000)
750 reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
751 else
752 reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
753
754 wm8900_write(codec, WM8900_REG_DACCTRL, reg);
755 }
756
746 return 0; 757 return 0;
747} 758}
748 759
@@ -1388,6 +1399,21 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1388 return 0; 1399 return 0;
1389} 1400}
1390 1401
1402#ifdef CONFIG_PM
1403static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1404{
1405 return snd_soc_suspend_device(&client->dev);
1406}
1407
1408static int wm8900_i2c_resume(struct i2c_client *client)
1409{
1410 return snd_soc_resume_device(&client->dev);
1411}
1412#else
1413#define wm8900_i2c_suspend NULL
1414#define wm8900_i2c_resume NULL
1415#endif
1416
1391static const struct i2c_device_id wm8900_i2c_id[] = { 1417static const struct i2c_device_id wm8900_i2c_id[] = {
1392 { "wm8900", 0 }, 1418 { "wm8900", 0 },
1393 { } 1419 { }
@@ -1401,6 +1427,8 @@ static struct i2c_driver wm8900_i2c_driver = {
1401 }, 1427 },
1402 .probe = wm8900_i2c_probe, 1428 .probe = wm8900_i2c_probe,
1403 .remove = __devexit_p(wm8900_i2c_remove), 1429 .remove = __devexit_p(wm8900_i2c_remove),
1430 .suspend = wm8900_i2c_suspend,
1431 .resume = wm8900_i2c_resume,
1404 .id_table = wm8900_i2c_id, 1432 .id_table = wm8900_i2c_id,
1405}; 1433};
1406 1434
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index e8d2e3e14c45..c9baeae3e275 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -715,8 +715,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
715SOC_ENUM("DAC Mute Mode", mute_mode), 715SOC_ENUM("DAC Mute Mode", mute_mode),
716SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), 716SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
717SOC_ENUM("DAC De-emphasis", dac_deemphasis), 717SOC_ENUM("DAC De-emphasis", dac_deemphasis),
718SOC_SINGLE("DAC Sloping Stopband Filter Switch",
719 WM8903_DAC_DIGITAL_1, 11, 1, 0),
720SOC_ENUM("DAC Companding Mode", dac_companding), 718SOC_ENUM("DAC Companding Mode", dac_companding),
721SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), 719SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
722 720
@@ -1373,12 +1371,19 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1373 u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); 1371 u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3);
1374 u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); 1372 u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0);
1375 u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); 1373 u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1);
1374 u16 dac_digital1 = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
1376 1375
1377 if (substream == wm8903->slave_substream) { 1376 if (substream == wm8903->slave_substream) {
1378 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 1377 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
1379 return 0; 1378 return 0;
1380 } 1379 }
1381 1380
1381 /* Enable sloping stopband filter for low sample rates */
1382 if (fs <= 24000)
1383 dac_digital1 |= WM8903_DAC_SB_FILT;
1384 else
1385 dac_digital1 &= ~WM8903_DAC_SB_FILT;
1386
1382 /* Configure sample rate logic for DSP - choose nearest rate */ 1387 /* Configure sample rate logic for DSP - choose nearest rate */
1383 dsp_config = 0; 1388 dsp_config = 0;
1384 best_val = abs(sample_rates[dsp_config].rate - fs); 1389 best_val = abs(sample_rates[dsp_config].rate - fs);
@@ -1503,6 +1508,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1503 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); 1508 wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
1504 wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); 1509 wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
1505 wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); 1510 wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
1511 wm8903_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
1506 1512
1507 return 0; 1513 return 0;
1508} 1514}
@@ -1721,6 +1727,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1721 return 0; 1727 return 0;
1722} 1728}
1723 1729
1730#ifdef CONFIG_PM
1731static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1732{
1733 return snd_soc_suspend_device(&client->dev);
1734}
1735
1736static int wm8903_i2c_resume(struct i2c_client *client)
1737{
1738 return snd_soc_resume_device(&client->dev);
1739}
1740#else
1741#define wm8903_i2c_suspend NULL
1742#define wm8903_i2c_resume NULL
1743#endif
1744
1724/* i2c codec control layer */ 1745/* i2c codec control layer */
1725static const struct i2c_device_id wm8903_i2c_id[] = { 1746static const struct i2c_device_id wm8903_i2c_id[] = {
1726 { "wm8903", 0 }, 1747 { "wm8903", 0 },
@@ -1735,6 +1756,8 @@ static struct i2c_driver wm8903_i2c_driver = {
1735 }, 1756 },
1736 .probe = wm8903_i2c_probe, 1757 .probe = wm8903_i2c_probe,
1737 .remove = __devexit_p(wm8903_i2c_remove), 1758 .remove = __devexit_p(wm8903_i2c_remove),
1759 .suspend = wm8903_i2c_suspend,
1760 .resume = wm8903_i2c_resume,
1738 .id_table = wm8903_i2c_id, 1761 .id_table = wm8903_i2c_id,
1739}; 1762};
1740 1763
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index b8e17d6bc1f7..b69210a77423 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -916,6 +916,21 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client)
916 return 0; 916 return 0;
917} 917}
918 918
919#ifdef CONFIG_PM
920static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
921{
922 return snd_soc_suspend_device(&client->dev);
923}
924
925static int wm8940_i2c_resume(struct i2c_client *client)
926{
927 return snd_soc_resume_device(&client->dev);
928}
929#else
930#define wm8940_i2c_suspend NULL
931#define wm8940_i2c_resume NULL
932#endif
933
919static const struct i2c_device_id wm8940_i2c_id[] = { 934static const struct i2c_device_id wm8940_i2c_id[] = {
920 { "wm8940", 0 }, 935 { "wm8940", 0 },
921 { } 936 { }
@@ -929,6 +944,8 @@ static struct i2c_driver wm8940_i2c_driver = {
929 }, 944 },
930 .probe = wm8940_i2c_probe, 945 .probe = wm8940_i2c_probe,
931 .remove = __devexit_p(wm8940_i2c_remove), 946 .remove = __devexit_p(wm8940_i2c_remove),
947 .suspend = wm8940_i2c_suspend,
948 .resume = wm8940_i2c_resume,
932 .id_table = wm8940_i2c_id, 949 .id_table = wm8940_i2c_id,
933}; 950};
934 951
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index e224d8add170..d1769e6c0c44 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -810,7 +810,8 @@ static int wm8960_register(struct wm8960_priv *wm8960)
810 810
811 if (wm8960_codec) { 811 if (wm8960_codec) {
812 dev_err(codec->dev, "Another WM8960 is registered\n"); 812 dev_err(codec->dev, "Another WM8960 is registered\n");
813 return -EINVAL; 813 ret = -EINVAL;
814 goto err;
814 } 815 }
815 816
816 if (!pdata) { 817 if (!pdata) {
@@ -843,7 +844,7 @@ static int wm8960_register(struct wm8960_priv *wm8960)
843 ret = wm8960_reset(codec); 844 ret = wm8960_reset(codec);
844 if (ret < 0) { 845 if (ret < 0) {
845 dev_err(codec->dev, "Failed to issue reset\n"); 846 dev_err(codec->dev, "Failed to issue reset\n");
846 return ret; 847 goto err;
847 } 848 }
848 849
849 wm8960_dai.dev = codec->dev; 850 wm8960_dai.dev = codec->dev;
@@ -877,17 +878,22 @@ static int wm8960_register(struct wm8960_priv *wm8960)
877 ret = snd_soc_register_codec(codec); 878 ret = snd_soc_register_codec(codec);
878 if (ret != 0) { 879 if (ret != 0) {
879 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 880 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
880 return ret; 881 goto err;
881 } 882 }
882 883
883 ret = snd_soc_register_dai(&wm8960_dai); 884 ret = snd_soc_register_dai(&wm8960_dai);
884 if (ret != 0) { 885 if (ret != 0) {
885 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 886 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
886 snd_soc_unregister_codec(codec); 887 goto err_codec;
887 return ret;
888 } 888 }
889 889
890 return 0; 890 return 0;
891
892err_codec:
893 snd_soc_unregister_codec(codec);
894err:
895 kfree(wm8960);
896 return ret;
891} 897}
892 898
893static void wm8960_unregister(struct wm8960_priv *wm8960) 899static void wm8960_unregister(struct wm8960_priv *wm8960)
@@ -927,6 +933,21 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client)
927 return 0; 933 return 0;
928} 934}
929 935
936#ifdef CONFIG_PM
937static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
938{
939 return snd_soc_suspend_device(&client->dev);
940}
941
942static int wm8960_i2c_resume(struct i2c_client *client)
943{
944 return snd_soc_resume_device(&client->dev);
945}
946#else
947#define wm8960_i2c_suspend NULL
948#define wm8960_i2c_resume NULL
949#endif
950
930static const struct i2c_device_id wm8960_i2c_id[] = { 951static const struct i2c_device_id wm8960_i2c_id[] = {
931 { "wm8960", 0 }, 952 { "wm8960", 0 },
932 { } 953 { }
@@ -940,6 +961,8 @@ static struct i2c_driver wm8960_i2c_driver = {
940 }, 961 },
941 .probe = wm8960_i2c_probe, 962 .probe = wm8960_i2c_probe,
942 .remove = __devexit_p(wm8960_i2c_remove), 963 .remove = __devexit_p(wm8960_i2c_remove),
964 .suspend = wm8960_i2c_suspend,
965 .resume = wm8960_i2c_resume,
943 .id_table = wm8960_i2c_id, 966 .id_table = wm8960_i2c_id,
944}; 967};
945 968
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
new file mode 100644
index 000000000000..bd1af92a122f
--- /dev/null
+++ b/sound/soc/codecs/wm8961.c
@@ -0,0 +1,1326 @@
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_reg_is_volatile(int reg)
296{
297 switch (reg) {
298 case WM8961_WRITE_SEQUENCER_7:
299 case WM8961_DC_SERVO_1:
300 return 1;
301
302 default:
303 return 0;
304 }
305}
306
307static unsigned int wm8961_read_reg_cache(struct snd_soc_codec *codec,
308 unsigned int reg)
309{
310 u16 *cache = codec->reg_cache;
311 BUG_ON(reg > WM8961_MAX_REGISTER);
312 return cache[reg];
313}
314
315static unsigned int wm8961_read_hw(struct snd_soc_codec *codec, u8 reg)
316{
317 struct i2c_msg xfer[2];
318 u16 data;
319 int ret;
320 struct i2c_client *client = codec->control_data;
321
322 BUG_ON(reg > WM8961_MAX_REGISTER);
323
324 /* Write register */
325 xfer[0].addr = client->addr;
326 xfer[0].flags = 0;
327 xfer[0].len = 1;
328 xfer[0].buf = &reg;
329
330 /* Read data */
331 xfer[1].addr = client->addr;
332 xfer[1].flags = I2C_M_RD;
333 xfer[1].len = 2;
334 xfer[1].buf = (u8 *)&data;
335
336 ret = i2c_transfer(client->adapter, xfer, 2);
337 if (ret != 2) {
338 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
339 return 0;
340 }
341
342 return (data >> 8) | ((data & 0xff) << 8);
343}
344
345static unsigned int wm8961_read(struct snd_soc_codec *codec, unsigned int reg)
346{
347 if (wm8961_reg_is_volatile(reg))
348 return wm8961_read_hw(codec, reg);
349 else
350 return wm8961_read_reg_cache(codec, reg);
351}
352
353static int wm8961_write(struct snd_soc_codec *codec, unsigned int reg,
354 unsigned int value)
355{
356 u16 *cache = codec->reg_cache;
357 u8 data[3];
358
359 BUG_ON(reg > WM8961_MAX_REGISTER);
360
361 if (!wm8961_reg_is_volatile(reg))
362 cache[reg] = value;
363
364 data[0] = reg;
365 data[1] = value >> 8;
366 data[2] = value & 0x00ff;
367
368 if (codec->hw_write(codec->control_data, data, 3) == 3)
369 return 0;
370 else
371 return -EIO;
372}
373
374static int wm8961_reset(struct snd_soc_codec *codec)
375{
376 return wm8961_write(codec, WM8961_SOFTWARE_RESET, 0);
377}
378
379/*
380 * The headphone output supports special anti-pop sequences giving
381 * silent power up and power down.
382 */
383static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
384 struct snd_kcontrol *kcontrol, int event)
385{
386 struct snd_soc_codec *codec = w->codec;
387 u16 hp_reg = wm8961_read(codec, WM8961_ANALOGUE_HP_0);
388 u16 cp_reg = wm8961_read(codec, WM8961_CHARGE_PUMP_1);
389 u16 pwr_reg = wm8961_read(codec, WM8961_PWR_MGMT_2);
390 u16 dcs_reg = wm8961_read(codec, WM8961_DC_SERVO_1);
391 int timeout = 500;
392
393 if (event & SND_SOC_DAPM_POST_PMU) {
394 /* Make sure the output is shorted */
395 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
396 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
397
398 /* Enable the charge pump */
399 cp_reg |= WM8961_CP_ENA;
400 wm8961_write(codec, WM8961_CHARGE_PUMP_1, cp_reg);
401 mdelay(5);
402
403 /* Enable the PGA */
404 pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA;
405 wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
406
407 /* Enable the amplifier */
408 hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA;
409 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
410
411 /* Second stage enable */
412 hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY;
413 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
414
415 /* Enable the DC servo & trigger startup */
416 dcs_reg |=
417 WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR |
418 WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL;
419 dev_dbg(codec->dev, "Enabling DC servo\n");
420
421 wm8961_write(codec, WM8961_DC_SERVO_1, dcs_reg);
422 do {
423 msleep(1);
424 dcs_reg = wm8961_read(codec, WM8961_DC_SERVO_1);
425 } while (--timeout &&
426 dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
427 WM8961_DCS_TRIG_STARTUP_HPL));
428 if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
429 WM8961_DCS_TRIG_STARTUP_HPL))
430 dev_err(codec->dev, "DC servo timed out\n");
431 else
432 dev_dbg(codec->dev, "DC servo startup complete\n");
433
434 /* Enable the output stage */
435 hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP;
436 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
437
438 /* Remove the short on the output stage */
439 hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT;
440 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
441 }
442
443 if (event & SND_SOC_DAPM_PRE_PMD) {
444 /* Short the output */
445 hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
446 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
447
448 /* Disable the output stage */
449 hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP);
450 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
451
452 /* Disable DC offset cancellation */
453 dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR |
454 WM8961_DCS_ENA_CHAN_HPL);
455 wm8961_write(codec, WM8961_DC_SERVO_1, dcs_reg);
456
457 /* Finish up */
458 hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA |
459 WM8961_HPL_ENA_DLY | WM8961_HPL_ENA);
460 wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
461
462 /* Disable the PGA */
463 pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA);
464 wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
465
466 /* Disable the charge pump */
467 dev_dbg(codec->dev, "Disabling charge pump\n");
468 wm8961_write(codec, WM8961_CHARGE_PUMP_1,
469 cp_reg & ~WM8961_CP_ENA);
470 }
471
472 return 0;
473}
474
475static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
476 struct snd_kcontrol *kcontrol, int event)
477{
478 struct snd_soc_codec *codec = w->codec;
479 u16 pwr_reg = wm8961_read(codec, WM8961_PWR_MGMT_2);
480 u16 spk_reg = wm8961_read(codec, WM8961_CLASS_D_CONTROL_1);
481
482 if (event & SND_SOC_DAPM_POST_PMU) {
483 /* Enable the PGA */
484 pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA;
485 wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
486
487 /* Enable the amplifier */
488 spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA;
489 wm8961_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
490 }
491
492 if (event & SND_SOC_DAPM_PRE_PMD) {
493 /* Enable the amplifier */
494 spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
495 wm8961_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
496
497 /* Enable the PGA */
498 pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
499 wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
500 }
501
502 return 0;
503}
504
505static const char *adc_hpf_text[] = {
506 "Hi-fi", "Voice 1", "Voice 2", "Voice 3",
507};
508
509static const struct soc_enum adc_hpf =
510 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text);
511
512static const char *dac_deemph_text[] = {
513 "None", "32kHz", "44.1kHz", "48kHz",
514};
515
516static const struct soc_enum dac_deemph =
517 SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text);
518
519static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
520static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
521static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
522static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
523static unsigned int boost_tlv[] = {
524 TLV_DB_RANGE_HEAD(4),
525 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
526 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0),
527 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0),
528 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0),
529};
530static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0);
531
532static const struct snd_kcontrol_new wm8961_snd_controls[] = {
533SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
534 0, 127, 0, out_tlv),
535SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2,
536 6, 3, 7, 0, hp_sec_tlv),
537SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
538 7, 1, 0),
539
540SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
541 0, 127, 0, out_tlv),
542SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
543 7, 1, 0),
544SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0),
545
546SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0),
547SOC_ENUM("DAC Deemphasis", dac_deemph),
548SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0),
549
550SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0,
551 WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv),
552
553SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0),
554SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
555
556SOC_DOUBLE_R_TLV("Capture Volume",
557 WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME,
558 1, 119, 0, adc_tlv),
559SOC_DOUBLE_R_TLV("Capture Boost Volume",
560 WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH,
561 4, 3, 0, boost_tlv),
562SOC_DOUBLE_R_TLV("Capture PGA Volume",
563 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
564 0, 62, 0, pga_tlv),
565SOC_DOUBLE_R("Capture PGA ZC Switch",
566 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
567 6, 1, 1),
568SOC_DOUBLE_R("Capture PGA Switch",
569 WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
570 7, 1, 1),
571};
572
573static const char *sidetone_text[] = {
574 "None", "Left", "Right"
575};
576
577static const struct soc_enum dacl_sidetone =
578 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text);
579
580static const struct soc_enum dacr_sidetone =
581 SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text);
582
583static const struct snd_kcontrol_new dacl_mux =
584 SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone);
585
586static const struct snd_kcontrol_new dacr_mux =
587 SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone);
588
589static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = {
590SND_SOC_DAPM_INPUT("LINPUT"),
591SND_SOC_DAPM_INPUT("RINPUT"),
592
593SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0),
594
595SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0),
596SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
597
598SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
599SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
600
601SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
602
603SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
604SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
605
606SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0),
607SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0),
608
609/* Handle as a mono path for DCS */
610SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM,
611 4, 0, NULL, 0, wm8961_hp_event,
612 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
613SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM,
614 4, 0, NULL, 0, wm8961_spk_event,
615 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
616
617SND_SOC_DAPM_OUTPUT("HP_L"),
618SND_SOC_DAPM_OUTPUT("HP_R"),
619SND_SOC_DAPM_OUTPUT("SPK_LN"),
620SND_SOC_DAPM_OUTPUT("SPK_LP"),
621SND_SOC_DAPM_OUTPUT("SPK_RN"),
622SND_SOC_DAPM_OUTPUT("SPK_RP"),
623};
624
625
626static const struct snd_soc_dapm_route audio_paths[] = {
627 { "DACL", NULL, "CLK_DSP" },
628 { "DACL", NULL, "DACL Sidetone" },
629 { "DACR", NULL, "CLK_DSP" },
630 { "DACR", NULL, "DACR Sidetone" },
631
632 { "DACL Sidetone", "Left", "ADCL" },
633 { "DACL Sidetone", "Right", "ADCR" },
634
635 { "DACR Sidetone", "Left", "ADCL" },
636 { "DACR Sidetone", "Right", "ADCR" },
637
638 { "HP_L", NULL, "Headphone Output" },
639 { "HP_R", NULL, "Headphone Output" },
640 { "Headphone Output", NULL, "DACL" },
641 { "Headphone Output", NULL, "DACR" },
642
643 { "SPK_LN", NULL, "Speaker Output" },
644 { "SPK_LP", NULL, "Speaker Output" },
645 { "SPK_RN", NULL, "Speaker Output" },
646 { "SPK_RP", NULL, "Speaker Output" },
647
648 { "Speaker Output", NULL, "DACL" },
649 { "Speaker Output", NULL, "DACR" },
650
651 { "ADCL", NULL, "Left Input" },
652 { "ADCL", NULL, "CLK_DSP" },
653 { "ADCR", NULL, "Right Input" },
654 { "ADCR", NULL, "CLK_DSP" },
655
656 { "Left Input", NULL, "LINPUT" },
657 { "Right Input", NULL, "RINPUT" },
658
659};
660
661/* Values for CLK_SYS_RATE */
662static struct {
663 int ratio;
664 u16 val;
665} wm8961_clk_sys_ratio[] = {
666 { 64, 0 },
667 { 128, 1 },
668 { 192, 2 },
669 { 256, 3 },
670 { 384, 4 },
671 { 512, 5 },
672 { 768, 6 },
673 { 1024, 7 },
674 { 1408, 8 },
675 { 1536, 9 },
676};
677
678/* Values for SAMPLE_RATE */
679static struct {
680 int rate;
681 u16 val;
682} wm8961_srate[] = {
683 { 48000, 0 },
684 { 44100, 0 },
685 { 32000, 1 },
686 { 22050, 2 },
687 { 24000, 2 },
688 { 16000, 3 },
689 { 11250, 4 },
690 { 12000, 4 },
691 { 8000, 5 },
692};
693
694static int wm8961_hw_params(struct snd_pcm_substream *substream,
695 struct snd_pcm_hw_params *params,
696 struct snd_soc_dai *dai)
697{
698 struct snd_soc_codec *codec = dai->codec;
699 struct wm8961_priv *wm8961 = codec->private_data;
700 int i, best, target, fs;
701 u16 reg;
702
703 fs = params_rate(params);
704
705 if (!wm8961->sysclk) {
706 dev_err(codec->dev, "MCLK has not been specified\n");
707 return -EINVAL;
708 }
709
710 /* Find the closest sample rate for the filters */
711 best = 0;
712 for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) {
713 if (abs(wm8961_srate[i].rate - fs) <
714 abs(wm8961_srate[best].rate - fs))
715 best = i;
716 }
717 reg = wm8961_read(codec, WM8961_ADDITIONAL_CONTROL_3);
718 reg &= ~WM8961_SAMPLE_RATE_MASK;
719 reg |= wm8961_srate[best].val;
720 wm8961_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg);
721 dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n",
722 wm8961_srate[best].rate, fs);
723
724 /* Select a CLK_SYS/fs ratio equal to or higher than required */
725 target = wm8961->sysclk / fs;
726
727 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) {
728 dev_err(codec->dev,
729 "SYSCLK must be at least 64*fs for DAC\n");
730 return -EINVAL;
731 }
732 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) {
733 dev_err(codec->dev,
734 "SYSCLK must be at least 256*fs for ADC\n");
735 return -EINVAL;
736 }
737
738 for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) {
739 if (wm8961_clk_sys_ratio[i].ratio >= target)
740 break;
741 }
742 if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) {
743 dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n");
744 return -EINVAL;
745 }
746 dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n",
747 wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs,
748 wm8961->sysclk / fs);
749
750 reg = wm8961_read(codec, WM8961_CLOCKING_4);
751 reg &= ~WM8961_CLK_SYS_RATE_MASK;
752 reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT;
753 wm8961_write(codec, WM8961_CLOCKING_4, reg);
754
755 reg = wm8961_read(codec, WM8961_AUDIO_INTERFACE_0);
756 reg &= ~WM8961_WL_MASK;
757 switch (params_format(params)) {
758 case SNDRV_PCM_FORMAT_S16_LE:
759 break;
760 case SNDRV_PCM_FORMAT_S20_3LE:
761 reg |= 1 << WM8961_WL_SHIFT;
762 break;
763 case SNDRV_PCM_FORMAT_S24_LE:
764 reg |= 2 << WM8961_WL_SHIFT;
765 break;
766 case SNDRV_PCM_FORMAT_S32_LE:
767 reg |= 3 << WM8961_WL_SHIFT;
768 break;
769 default:
770 return -EINVAL;
771 }
772 wm8961_write(codec, WM8961_AUDIO_INTERFACE_0, reg);
773
774 /* Sloping stop-band filter is recommended for <= 24kHz */
775 reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_2);
776 if (fs <= 24000)
777 reg |= WM8961_DACSLOPE;
778 else
779 reg &= WM8961_DACSLOPE;
780 wm8961_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
781
782 return 0;
783}
784
785static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
786 unsigned int freq,
787 int dir)
788{
789 struct snd_soc_codec *codec = dai->codec;
790 struct wm8961_priv *wm8961 = codec->private_data;
791 u16 reg = wm8961_read(codec, WM8961_CLOCKING1);
792
793 if (freq > 33000000) {
794 dev_err(codec->dev, "MCLK must be <33MHz\n");
795 return -EINVAL;
796 }
797
798 if (freq > 16500000) {
799 dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq);
800 reg |= WM8961_MCLKDIV;
801 freq /= 2;
802 } else {
803 dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
804 reg &= WM8961_MCLKDIV;
805 }
806
807 wm8961_write(codec, WM8961_CLOCKING1, reg);
808
809 wm8961->sysclk = freq;
810
811 return 0;
812}
813
814static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
815{
816 struct snd_soc_codec *codec = dai->codec;
817 u16 aif = wm8961_read(codec, WM8961_AUDIO_INTERFACE_0);
818
819 aif &= ~(WM8961_BCLKINV | WM8961_LRP |
820 WM8961_MS | WM8961_FORMAT_MASK);
821
822 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
823 case SND_SOC_DAIFMT_CBM_CFM:
824 aif |= WM8961_MS;
825 break;
826 case SND_SOC_DAIFMT_CBS_CFS:
827 break;
828 default:
829 return -EINVAL;
830 }
831
832 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
833 case SND_SOC_DAIFMT_RIGHT_J:
834 break;
835
836 case SND_SOC_DAIFMT_LEFT_J:
837 aif |= 1;
838 break;
839
840 case SND_SOC_DAIFMT_I2S:
841 aif |= 2;
842 break;
843
844 case SND_SOC_DAIFMT_DSP_B:
845 aif |= WM8961_LRP;
846 case SND_SOC_DAIFMT_DSP_A:
847 aif |= 3;
848 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
849 case SND_SOC_DAIFMT_NB_NF:
850 case SND_SOC_DAIFMT_IB_NF:
851 break;
852 default:
853 return -EINVAL;
854 }
855 break;
856
857 default:
858 return -EINVAL;
859 }
860
861 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
862 case SND_SOC_DAIFMT_NB_NF:
863 break;
864 case SND_SOC_DAIFMT_NB_IF:
865 aif |= WM8961_LRP;
866 break;
867 case SND_SOC_DAIFMT_IB_NF:
868 aif |= WM8961_BCLKINV;
869 break;
870 case SND_SOC_DAIFMT_IB_IF:
871 aif |= WM8961_BCLKINV | WM8961_LRP;
872 break;
873 default:
874 return -EINVAL;
875 }
876
877 return wm8961_write(codec, WM8961_AUDIO_INTERFACE_0, aif);
878}
879
880static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate)
881{
882 struct snd_soc_codec *codec = dai->codec;
883 u16 reg = wm8961_read(codec, WM8961_ADDITIONAL_CONTROL_2);
884
885 if (tristate)
886 reg |= WM8961_TRIS;
887 else
888 reg &= ~WM8961_TRIS;
889
890 return wm8961_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg);
891}
892
893static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute)
894{
895 struct snd_soc_codec *codec = dai->codec;
896 u16 reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_1);
897
898 if (mute)
899 reg |= WM8961_DACMU;
900 else
901 reg &= ~WM8961_DACMU;
902
903 msleep(17);
904
905 return wm8961_write(codec, WM8961_ADC_DAC_CONTROL_1, reg);
906}
907
908static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
909{
910 struct snd_soc_codec *codec = dai->codec;
911 u16 reg;
912
913 switch (div_id) {
914 case WM8961_BCLK:
915 reg = wm8961_read(codec, WM8961_CLOCKING2);
916 reg &= ~WM8961_BCLKDIV_MASK;
917 reg |= div;
918 wm8961_write(codec, WM8961_CLOCKING2, reg);
919 break;
920
921 case WM8961_LRCLK:
922 reg = wm8961_read(codec, WM8961_AUDIO_INTERFACE_2);
923 reg &= ~WM8961_LRCLK_RATE_MASK;
924 reg |= div;
925 wm8961_write(codec, WM8961_AUDIO_INTERFACE_2, reg);
926 break;
927
928 default:
929 return -EINVAL;
930 }
931
932 return 0;
933}
934
935static int wm8961_set_bias_level(struct snd_soc_codec *codec,
936 enum snd_soc_bias_level level)
937{
938 u16 reg;
939
940 /* This is all slightly unusual since we have no bypass paths
941 * and the output amplifier structure means we can just slam
942 * the biases straight up rather than having to ramp them
943 * slowly.
944 */
945 switch (level) {
946 case SND_SOC_BIAS_ON:
947 break;
948
949 case SND_SOC_BIAS_PREPARE:
950 if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
951 /* Enable bias generation */
952 reg = wm8961_read(codec, WM8961_ANTI_POP);
953 reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN;
954 wm8961_write(codec, WM8961_ANTI_POP, reg);
955
956 /* VMID=2*50k, VREF */
957 reg = wm8961_read(codec, WM8961_PWR_MGMT_1);
958 reg &= ~WM8961_VMIDSEL_MASK;
959 reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF;
960 wm8961_write(codec, WM8961_PWR_MGMT_1, reg);
961 }
962 break;
963
964 case SND_SOC_BIAS_STANDBY:
965 if (codec->bias_level == SND_SOC_BIAS_PREPARE) {
966 /* VREF off */
967 reg = wm8961_read(codec, WM8961_PWR_MGMT_1);
968 reg &= ~WM8961_VREF;
969 wm8961_write(codec, WM8961_PWR_MGMT_1, reg);
970
971 /* Bias generation off */
972 reg = wm8961_read(codec, WM8961_ANTI_POP);
973 reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN);
974 wm8961_write(codec, WM8961_ANTI_POP, reg);
975
976 /* VMID off */
977 reg = wm8961_read(codec, WM8961_PWR_MGMT_1);
978 reg &= ~WM8961_VMIDSEL_MASK;
979 wm8961_write(codec, WM8961_PWR_MGMT_1, reg);
980 }
981 break;
982
983 case SND_SOC_BIAS_OFF:
984 break;
985 }
986
987 codec->bias_level = level;
988
989 return 0;
990}
991
992
993#define WM8961_RATES SNDRV_PCM_RATE_8000_48000
994
995#define WM8961_FORMATS \
996 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
997 SNDRV_PCM_FMTBIT_S24_LE)
998
999static struct snd_soc_dai_ops wm8961_dai_ops = {
1000 .hw_params = wm8961_hw_params,
1001 .set_sysclk = wm8961_set_sysclk,
1002 .set_fmt = wm8961_set_fmt,
1003 .digital_mute = wm8961_digital_mute,
1004 .set_tristate = wm8961_set_tristate,
1005 .set_clkdiv = wm8961_set_clkdiv,
1006};
1007
1008struct snd_soc_dai wm8961_dai = {
1009 .name = "WM8961",
1010 .playback = {
1011 .stream_name = "HiFi Playback",
1012 .channels_min = 1,
1013 .channels_max = 2,
1014 .rates = WM8961_RATES,
1015 .formats = WM8961_FORMATS,},
1016 .capture = {
1017 .stream_name = "HiFi Capture",
1018 .channels_min = 1,
1019 .channels_max = 2,
1020 .rates = WM8961_RATES,
1021 .formats = WM8961_FORMATS,},
1022 .ops = &wm8961_dai_ops,
1023};
1024EXPORT_SYMBOL_GPL(wm8961_dai);
1025
1026
1027static struct snd_soc_codec *wm8961_codec;
1028
1029static int wm8961_probe(struct platform_device *pdev)
1030{
1031 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1032 struct snd_soc_codec *codec;
1033 int ret = 0;
1034
1035 if (wm8961_codec == NULL) {
1036 dev_err(&pdev->dev, "Codec device not registered\n");
1037 return -ENODEV;
1038 }
1039
1040 socdev->card->codec = wm8961_codec;
1041 codec = wm8961_codec;
1042
1043 /* register pcms */
1044 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1045 if (ret < 0) {
1046 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
1047 goto pcm_err;
1048 }
1049
1050 snd_soc_add_controls(codec, wm8961_snd_controls,
1051 ARRAY_SIZE(wm8961_snd_controls));
1052 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
1053 ARRAY_SIZE(wm8961_dapm_widgets));
1054 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1055 snd_soc_dapm_new_widgets(codec);
1056
1057 ret = snd_soc_init_card(socdev);
1058 if (ret < 0) {
1059 dev_err(codec->dev, "failed to register card: %d\n", ret);
1060 goto card_err;
1061 }
1062
1063 return ret;
1064
1065card_err:
1066 snd_soc_free_pcms(socdev);
1067 snd_soc_dapm_free(socdev);
1068pcm_err:
1069 return ret;
1070}
1071
1072static int wm8961_remove(struct platform_device *pdev)
1073{
1074 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1075
1076 snd_soc_free_pcms(socdev);
1077 snd_soc_dapm_free(socdev);
1078
1079 return 0;
1080}
1081
1082#ifdef CONFIG_PM
1083static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
1084{
1085 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1086 struct snd_soc_codec *codec = socdev->card->codec;
1087
1088 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1089
1090 return 0;
1091}
1092
1093static int wm8961_resume(struct platform_device *pdev)
1094{
1095 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1096 struct snd_soc_codec *codec = socdev->card->codec;
1097 u16 *reg_cache = codec->reg_cache;
1098 int i;
1099
1100 for (i = 0; i < codec->reg_cache_size; i++) {
1101 if (i == WM8961_SOFTWARE_RESET)
1102 continue;
1103
1104 wm8961_write(codec, i, reg_cache[i]);
1105 }
1106
1107 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1108
1109 return 0;
1110}
1111#else
1112#define wm8961_suspend NULL
1113#define wm8961_resume NULL
1114#endif
1115
1116struct snd_soc_codec_device soc_codec_dev_wm8961 = {
1117 .probe = wm8961_probe,
1118 .remove = wm8961_remove,
1119 .suspend = wm8961_suspend,
1120 .resume = wm8961_resume,
1121};
1122EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
1123
1124static int wm8961_register(struct wm8961_priv *wm8961)
1125{
1126 struct snd_soc_codec *codec = &wm8961->codec;
1127 int ret;
1128 u16 reg;
1129
1130 if (wm8961_codec) {
1131 dev_err(codec->dev, "Another WM8961 is registered\n");
1132 ret = -EINVAL;
1133 goto err;
1134 }
1135
1136 mutex_init(&codec->mutex);
1137 INIT_LIST_HEAD(&codec->dapm_widgets);
1138 INIT_LIST_HEAD(&codec->dapm_paths);
1139
1140 codec->private_data = wm8961;
1141 codec->name = "WM8961";
1142 codec->owner = THIS_MODULE;
1143 codec->read = wm8961_read;
1144 codec->write = wm8961_write;
1145 codec->dai = &wm8961_dai;
1146 codec->num_dai = 1;
1147 codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
1148 codec->reg_cache = &wm8961->reg_cache;
1149 codec->bias_level = SND_SOC_BIAS_OFF;
1150 codec->set_bias_level = wm8961_set_bias_level;
1151
1152 memcpy(codec->reg_cache, wm8961_reg_defaults,
1153 sizeof(wm8961_reg_defaults));
1154
1155 reg = wm8961_read_hw(codec, WM8961_SOFTWARE_RESET);
1156 if (reg != 0x1801) {
1157 dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
1158 ret = -EINVAL;
1159 goto err;
1160 }
1161
1162 reg = wm8961_read_hw(codec, WM8961_RIGHT_INPUT_VOLUME);
1163 dev_info(codec->dev, "WM8961 family %d revision %c\n",
1164 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
1165 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
1166 + 'A');
1167
1168 ret = wm8961_reset(codec);
1169 if (ret < 0) {
1170 dev_err(codec->dev, "Failed to issue reset\n");
1171 return ret;
1172 }
1173
1174 /* Enable class W */
1175 reg = wm8961_read(codec, WM8961_CHARGE_PUMP_B);
1176 reg |= WM8961_CP_DYN_PWR_MASK;
1177 wm8961_write(codec, WM8961_CHARGE_PUMP_B, reg);
1178
1179 /* Latch volume update bits (right channel only, we always
1180 * write both out) and default ZC on. */
1181 reg = wm8961_read(codec, WM8961_ROUT1_VOLUME);
1182 wm8961_write(codec, WM8961_ROUT1_VOLUME,
1183 reg | WM8961_LO1ZC | WM8961_OUT1VU);
1184 wm8961_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
1185 reg = wm8961_read(codec, WM8961_ROUT2_VOLUME);
1186 wm8961_write(codec, WM8961_ROUT2_VOLUME,
1187 reg | WM8961_SPKRZC | WM8961_SPKVU);
1188 wm8961_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);
1189
1190 reg = wm8961_read(codec, WM8961_RIGHT_ADC_VOLUME);
1191 wm8961_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
1192 reg = wm8961_read(codec, WM8961_RIGHT_INPUT_VOLUME);
1193 wm8961_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);
1194
1195 /* Use soft mute by default */
1196 reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_2);
1197 reg |= WM8961_DACSMM;
1198 wm8961_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
1199
1200 /* Use automatic clocking mode by default; for now this is all
1201 * we support.
1202 */
1203 reg = wm8961_read(codec, WM8961_CLOCKING_3);
1204 reg &= ~WM8961_MANUAL_MODE;
1205 wm8961_write(codec, WM8961_CLOCKING_3, reg);
1206
1207 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1208
1209 wm8961_dai.dev = codec->dev;
1210
1211 wm8961_codec = codec;
1212
1213 ret = snd_soc_register_codec(codec);
1214 if (ret != 0) {
1215 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1216 return ret;
1217 }
1218
1219 ret = snd_soc_register_dai(&wm8961_dai);
1220 if (ret != 0) {
1221 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1222 snd_soc_unregister_codec(codec);
1223 return ret;
1224 }
1225
1226 return 0;
1227
1228err:
1229 kfree(wm8961);
1230 return ret;
1231}
1232
1233static void wm8961_unregister(struct wm8961_priv *wm8961)
1234{
1235 wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF);
1236 snd_soc_unregister_dai(&wm8961_dai);
1237 snd_soc_unregister_codec(&wm8961->codec);
1238 kfree(wm8961);
1239 wm8961_codec = NULL;
1240}
1241
1242static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
1243 const struct i2c_device_id *id)
1244{
1245 struct wm8961_priv *wm8961;
1246 struct snd_soc_codec *codec;
1247
1248 wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
1249 if (wm8961 == NULL)
1250 return -ENOMEM;
1251
1252 codec = &wm8961->codec;
1253 codec->hw_write = (hw_write_t)i2c_master_send;
1254
1255 i2c_set_clientdata(i2c, wm8961);
1256 codec->control_data = i2c;
1257
1258 codec->dev = &i2c->dev;
1259
1260 return wm8961_register(wm8961);
1261}
1262
1263static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1264{
1265 struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
1266 wm8961_unregister(wm8961);
1267 return 0;
1268}
1269
1270#ifdef CONFIG_PM
1271static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
1272{
1273 return snd_soc_suspend_device(&client->dev);
1274}
1275
1276static int wm8961_i2c_resume(struct i2c_client *client)
1277{
1278 return snd_soc_resume_device(&client->dev);
1279}
1280#else
1281#define wm8961_i2c_suspend NULL
1282#define wm8961_i2c_resume NULL
1283#endif
1284
1285static const struct i2c_device_id wm8961_i2c_id[] = {
1286 { "wm8961", 0 },
1287 { }
1288};
1289MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
1290
1291static struct i2c_driver wm8961_i2c_driver = {
1292 .driver = {
1293 .name = "wm8961",
1294 .owner = THIS_MODULE,
1295 },
1296 .probe = wm8961_i2c_probe,
1297 .remove = __devexit_p(wm8961_i2c_remove),
1298 .suspend = wm8961_i2c_suspend,
1299 .resume = wm8961_i2c_resume,
1300 .id_table = wm8961_i2c_id,
1301};
1302
1303static int __init wm8961_modinit(void)
1304{
1305 int ret;
1306
1307 ret = i2c_add_driver(&wm8961_i2c_driver);
1308 if (ret != 0) {
1309 printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
1310 ret);
1311 }
1312
1313 return ret;
1314}
1315module_init(wm8961_modinit);
1316
1317static void __exit wm8961_exit(void)
1318{
1319 i2c_del_driver(&wm8961_i2c_driver);
1320}
1321module_exit(wm8961_exit);
1322
1323
1324MODULE_DESCRIPTION("ASoC WM8961 driver");
1325MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1326MODULE_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/wm8988.c b/sound/soc/codecs/wm8988.c
index c05f71803aa8..6f15acd10489 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -902,7 +902,7 @@ static int wm8988_register(struct wm8988_priv *wm8988)
902 ret = wm8988_reset(codec); 902 ret = wm8988_reset(codec);
903 if (ret < 0) { 903 if (ret < 0) {
904 dev_err(codec->dev, "Failed to issue reset\n"); 904 dev_err(codec->dev, "Failed to issue reset\n");
905 return ret; 905 goto err;
906 } 906 }
907 907
908 /* set the update bits (we always update left then right) */ 908 /* set the update bits (we always update left then right) */
@@ -926,18 +926,20 @@ static int wm8988_register(struct wm8988_priv *wm8988)
926 ret = snd_soc_register_codec(codec); 926 ret = snd_soc_register_codec(codec);
927 if (ret != 0) { 927 if (ret != 0) {
928 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 928 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
929 return ret; 929 goto err;
930 } 930 }
931 931
932 ret = snd_soc_register_dai(&wm8988_dai); 932 ret = snd_soc_register_dai(&wm8988_dai);
933 if (ret != 0) { 933 if (ret != 0) {
934 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 934 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
935 snd_soc_unregister_codec(codec); 935 snd_soc_unregister_codec(codec);
936 return ret; 936 goto err_codec;
937 } 937 }
938 938
939 return 0; 939 return 0;
940 940
941err_codec:
942 snd_soc_unregister_codec(codec);
941err: 943err:
942 kfree(wm8988); 944 kfree(wm8988);
943 return ret; 945 return ret;
@@ -981,6 +983,21 @@ static int wm8988_i2c_remove(struct i2c_client *client)
981 return 0; 983 return 0;
982} 984}
983 985
986#ifdef CONFIG_PM
987static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
988{
989 return snd_soc_suspend_device(&client->dev);
990}
991
992static int wm8988_i2c_resume(struct i2c_client *client)
993{
994 return snd_soc_resume_device(&client->dev);
995}
996#else
997#define wm8988_i2c_suspend NULL
998#define wm8988_i2c_resume NULL
999#endif
1000
984static const struct i2c_device_id wm8988_i2c_id[] = { 1001static const struct i2c_device_id wm8988_i2c_id[] = {
985 { "wm8988", 0 }, 1002 { "wm8988", 0 },
986 { } 1003 { }
@@ -994,6 +1011,8 @@ static struct i2c_driver wm8988_i2c_driver = {
994 }, 1011 },
995 .probe = wm8988_i2c_probe, 1012 .probe = wm8988_i2c_probe,
996 .remove = wm8988_i2c_remove, 1013 .remove = wm8988_i2c_remove,
1014 .suspend = wm8988_i2c_suspend,
1015 .resume = wm8988_i2c_resume,
997 .id_table = wm8988_i2c_id, 1016 .id_table = wm8988_i2c_id,
998}; 1017};
999#endif 1018#endif
@@ -1051,6 +1070,21 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
1051 return 0; 1070 return 0;
1052} 1071}
1053 1072
1073#ifdef CONFIG_PM
1074static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1075{
1076 return snd_soc_suspend_device(&spi->dev);
1077}
1078
1079static int wm8988_spi_resume(struct spi_device *spi)
1080{
1081 return snd_soc_resume_device(&spi->dev);
1082}
1083#else
1084#define wm8988_spi_suspend NULL
1085#define wm8988_spi_resume NULL
1086#endif
1087
1054static struct spi_driver wm8988_spi_driver = { 1088static struct spi_driver wm8988_spi_driver = {
1055 .driver = { 1089 .driver = {
1056 .name = "wm8988", 1090 .name = "wm8988",
@@ -1059,6 +1093,8 @@ static struct spi_driver wm8988_spi_driver = {
1059 }, 1093 },
1060 .probe = wm8988_spi_probe, 1094 .probe = wm8988_spi_probe,
1061 .remove = __devexit_p(wm8988_spi_remove), 1095 .remove = __devexit_p(wm8988_spi_remove),
1096 .suspend = wm8988_spi_suspend,
1097 .resume = wm8988_spi_resume,
1062}; 1098};
1063#endif 1099#endif
1064 1100
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
new file mode 100644
index 000000000000..e246ca079897
--- /dev/null
+++ b/sound/soc/codecs/wm8993.c
@@ -0,0 +1,2206 @@
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
31static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
32 0x8993, /* R0 - Software Reset */
33 0x0000, /* R1 - Power Management (1) */
34 0x6000, /* R2 - Power Management (2) */
35 0x0000, /* R3 - Power Management (3) */
36 0x4050, /* R4 - Audio Interface (1) */
37 0x4000, /* R5 - Audio Interface (2) */
38 0x01C8, /* R6 - Clocking 1 */
39 0x0000, /* R7 - Clocking 2 */
40 0x0000, /* R8 - Audio Interface (3) */
41 0x0040, /* R9 - Audio Interface (4) */
42 0x0004, /* R10 - DAC CTRL */
43 0x00C0, /* R11 - Left DAC Digital Volume */
44 0x00C0, /* R12 - Right DAC Digital Volume */
45 0x0000, /* R13 - Digital Side Tone */
46 0x0300, /* R14 - ADC CTRL */
47 0x00C0, /* R15 - Left ADC Digital Volume */
48 0x00C0, /* R16 - Right ADC Digital Volume */
49 0x0000, /* R17 */
50 0x0000, /* R18 - GPIO CTRL 1 */
51 0x0010, /* R19 - GPIO1 */
52 0x0000, /* R20 - IRQ_DEBOUNCE */
53 0x0000, /* R21 */
54 0x8000, /* R22 - GPIOCTRL 2 */
55 0x0800, /* R23 - GPIO_POL */
56 0x008B, /* R24 - Left Line Input 1&2 Volume */
57 0x008B, /* R25 - Left Line Input 3&4 Volume */
58 0x008B, /* R26 - Right Line Input 1&2 Volume */
59 0x008B, /* R27 - Right Line Input 3&4 Volume */
60 0x006D, /* R28 - Left Output Volume */
61 0x006D, /* R29 - Right Output Volume */
62 0x0066, /* R30 - Line Outputs Volume */
63 0x0020, /* R31 - HPOUT2 Volume */
64 0x0079, /* R32 - Left OPGA Volume */
65 0x0079, /* R33 - Right OPGA Volume */
66 0x0003, /* R34 - SPKMIXL Attenuation */
67 0x0003, /* R35 - SPKMIXR Attenuation */
68 0x0011, /* R36 - SPKOUT Mixers */
69 0x0100, /* R37 - SPKOUT Boost */
70 0x0079, /* R38 - Speaker Volume Left */
71 0x0079, /* R39 - Speaker Volume Right */
72 0x0000, /* R40 - Input Mixer2 */
73 0x0000, /* R41 - Input Mixer3 */
74 0x0000, /* R42 - Input Mixer4 */
75 0x0000, /* R43 - Input Mixer5 */
76 0x0000, /* R44 - Input Mixer6 */
77 0x0000, /* R45 - Output Mixer1 */
78 0x0000, /* R46 - Output Mixer2 */
79 0x0000, /* R47 - Output Mixer3 */
80 0x0000, /* R48 - Output Mixer4 */
81 0x0000, /* R49 - Output Mixer5 */
82 0x0000, /* R50 - Output Mixer6 */
83 0x0000, /* R51 - HPOUT2 Mixer */
84 0x0000, /* R52 - Line Mixer1 */
85 0x0000, /* R53 - Line Mixer2 */
86 0x0000, /* R54 - Speaker Mixer */
87 0x0000, /* R55 - Additional Control */
88 0x0000, /* R56 - AntiPOP1 */
89 0x0000, /* R57 - AntiPOP2 */
90 0x0000, /* R58 - MICBIAS */
91 0x0000, /* R59 */
92 0x0000, /* R60 - FLL Control 1 */
93 0x0000, /* R61 - FLL Control 2 */
94 0x0000, /* R62 - FLL Control 3 */
95 0x2EE0, /* R63 - FLL Control 4 */
96 0x0002, /* R64 - FLL Control 5 */
97 0x2287, /* R65 - Clocking 3 */
98 0x025F, /* R66 - Clocking 4 */
99 0x0000, /* R67 - MW Slave Control */
100 0x0000, /* R68 */
101 0x0002, /* R69 - Bus Control 1 */
102 0x0000, /* R70 - Write Sequencer 0 */
103 0x0000, /* R71 - Write Sequencer 1 */
104 0x0000, /* R72 - Write Sequencer 2 */
105 0x0000, /* R73 - Write Sequencer 3 */
106 0x0000, /* R74 - Write Sequencer 4 */
107 0x0000, /* R75 - Write Sequencer 5 */
108 0x1F25, /* R76 - Charge Pump 1 */
109 0x0000, /* R77 */
110 0x0000, /* R78 */
111 0x0000, /* R79 */
112 0x0000, /* R80 */
113 0x0000, /* R81 - Class W 0 */
114 0x0000, /* R82 */
115 0x0000, /* R83 */
116 0x0000, /* R84 - DC Servo 0 */
117 0x054A, /* R85 - DC Servo 1 */
118 0x0000, /* R86 */
119 0x0000, /* R87 - DC Servo 3 */
120 0x0000, /* R88 - DC Servo Readback 0 */
121 0x0000, /* R89 - DC Servo Readback 1 */
122 0x0000, /* R90 - DC Servo Readback 2 */
123 0x0000, /* R91 */
124 0x0000, /* R92 */
125 0x0000, /* R93 */
126 0x0000, /* R94 */
127 0x0000, /* R95 */
128 0x0100, /* R96 - Analogue HP 0 */
129 0x0000, /* R97 */
130 0x0000, /* R98 - EQ1 */
131 0x000C, /* R99 - EQ2 */
132 0x000C, /* R100 - EQ3 */
133 0x000C, /* R101 - EQ4 */
134 0x000C, /* R102 - EQ5 */
135 0x000C, /* R103 - EQ6 */
136 0x0FCA, /* R104 - EQ7 */
137 0x0400, /* R105 - EQ8 */
138 0x00D8, /* R106 - EQ9 */
139 0x1EB5, /* R107 - EQ10 */
140 0xF145, /* R108 - EQ11 */
141 0x0B75, /* R109 - EQ12 */
142 0x01C5, /* R110 - EQ13 */
143 0x1C58, /* R111 - EQ14 */
144 0xF373, /* R112 - EQ15 */
145 0x0A54, /* R113 - EQ16 */
146 0x0558, /* R114 - EQ17 */
147 0x168E, /* R115 - EQ18 */
148 0xF829, /* R116 - EQ19 */
149 0x07AD, /* R117 - EQ20 */
150 0x1103, /* R118 - EQ21 */
151 0x0564, /* R119 - EQ22 */
152 0x0559, /* R120 - EQ23 */
153 0x4000, /* R121 - EQ24 */
154 0x0000, /* R122 - Digital Pulls */
155 0x0F08, /* R123 - DRC Control 1 */
156 0x0000, /* R124 - DRC Control 2 */
157 0x0080, /* R125 - DRC Control 3 */
158 0x0000, /* R126 - DRC Control 4 */
159};
160
161static struct {
162 int ratio;
163 int clk_sys_rate;
164} clk_sys_rates[] = {
165 { 64, 0 },
166 { 128, 1 },
167 { 192, 2 },
168 { 256, 3 },
169 { 384, 4 },
170 { 512, 5 },
171 { 768, 6 },
172 { 1024, 7 },
173 { 1408, 8 },
174 { 1536, 9 },
175};
176
177static struct {
178 int rate;
179 int sample_rate;
180} sample_rates[] = {
181 { 8000, 0 },
182 { 11025, 1 },
183 { 12000, 1 },
184 { 16000, 2 },
185 { 22050, 3 },
186 { 24000, 3 },
187 { 32000, 4 },
188 { 44100, 5 },
189 { 48000, 5 },
190};
191
192static struct {
193 int div; /* *10 due to .5s */
194 int bclk_div;
195} bclk_divs[] = {
196 { 10, 0 },
197 { 15, 1 },
198 { 20, 2 },
199 { 30, 3 },
200 { 40, 4 },
201 { 55, 5 },
202 { 60, 6 },
203 { 80, 7 },
204 { 110, 8 },
205 { 120, 9 },
206 { 160, 10 },
207 { 220, 11 },
208 { 240, 12 },
209 { 320, 13 },
210 { 440, 14 },
211 { 480, 15 },
212};
213
214struct wm8993_priv {
215 u16 reg_cache[WM8993_REGISTER_COUNT];
216 struct wm8993_platform_data pdata;
217 struct snd_soc_codec codec;
218 int master;
219 int sysclk_source;
220 unsigned int mclk_rate;
221 unsigned int sysclk_rate;
222 unsigned int fs;
223 unsigned int bclk;
224 int class_w_users;
225 unsigned int fll_fref;
226 unsigned int fll_fout;
227};
228
229static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg)
230{
231 struct i2c_msg xfer[2];
232 u16 data;
233 int ret;
234 struct i2c_client *i2c = codec->control_data;
235
236 /* Write register */
237 xfer[0].addr = i2c->addr;
238 xfer[0].flags = 0;
239 xfer[0].len = 1;
240 xfer[0].buf = &reg;
241
242 /* Read data */
243 xfer[1].addr = i2c->addr;
244 xfer[1].flags = I2C_M_RD;
245 xfer[1].len = 2;
246 xfer[1].buf = (u8 *)&data;
247
248 ret = i2c_transfer(i2c->adapter, xfer, 2);
249 if (ret != 2) {
250 dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
251 return 0;
252 }
253
254 return (data >> 8) | ((data & 0xff) << 8);
255}
256
257static int wm8993_volatile(unsigned int reg)
258{
259 switch (reg) {
260 case WM8993_SOFTWARE_RESET:
261 case WM8993_DC_SERVO_0:
262 case WM8993_DC_SERVO_READBACK_0:
263 case WM8993_DC_SERVO_READBACK_1:
264 case WM8993_DC_SERVO_READBACK_2:
265 return 1;
266 default:
267 return 0;
268 }
269}
270
271static unsigned int wm8993_read(struct snd_soc_codec *codec,
272 unsigned int reg)
273{
274 u16 *reg_cache = codec->reg_cache;
275
276 BUG_ON(reg > WM8993_MAX_REGISTER);
277
278 if (wm8993_volatile(reg))
279 return wm8993_read_hw(codec, reg);
280 else
281 return reg_cache[reg];
282}
283
284static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg,
285 unsigned int value)
286{
287 u16 *reg_cache = codec->reg_cache;
288 u8 data[3];
289 int ret;
290
291 BUG_ON(reg > WM8993_MAX_REGISTER);
292
293 /* data is
294 * D15..D9 WM8993 register offset
295 * D8...D0 register data
296 */
297 data[0] = reg;
298 data[1] = value >> 8;
299 data[2] = value & 0x00ff;
300
301 if (!wm8993_volatile(reg))
302 reg_cache[reg] = value;
303
304 ret = codec->hw_write(codec->control_data, data, 3);
305
306 if (ret == 3)
307 return 0;
308 if (ret < 0)
309 return ret;
310 return -EIO;
311}
312
313struct _fll_div {
314 u16 fll_fratio;
315 u16 fll_outdiv;
316 u16 fll_clk_ref_div;
317 u16 n;
318 u16 k;
319};
320
321/* The size in bits of the FLL divide multiplied by 10
322 * to allow rounding later */
323#define FIXED_FLL_SIZE ((1 << 16) * 10)
324
325static struct {
326 unsigned int min;
327 unsigned int max;
328 u16 fll_fratio;
329 int ratio;
330} fll_fratios[] = {
331 { 0, 64000, 4, 16 },
332 { 64000, 128000, 3, 8 },
333 { 128000, 256000, 2, 4 },
334 { 256000, 1000000, 1, 2 },
335 { 1000000, 13500000, 0, 1 },
336};
337
338static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
339 unsigned int Fout)
340{
341 u64 Kpart;
342 unsigned int K, Ndiv, Nmod, target;
343 unsigned int div;
344 int i;
345
346 /* Fref must be <=13.5MHz */
347 div = 1;
348 fll_div->fll_clk_ref_div = 0;
349 while ((Fref / div) > 13500000) {
350 div *= 2;
351 fll_div->fll_clk_ref_div++;
352
353 if (div > 8) {
354 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
355 Fref);
356 return -EINVAL;
357 }
358 }
359
360 pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
361
362 /* Apply the division for our remaining calculations */
363 Fref /= div;
364
365 /* Fvco should be 90-100MHz; don't check the upper bound */
366 div = 0;
367 target = Fout * 2;
368 while (target < 90000000) {
369 div++;
370 target *= 2;
371 if (div > 7) {
372 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
373 Fout);
374 return -EINVAL;
375 }
376 }
377 fll_div->fll_outdiv = div;
378
379 pr_debug("Fvco=%dHz\n", target);
380
381 /* Find an appropraite FLL_FRATIO and factor it out of the target */
382 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
383 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
384 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
385 target /= fll_fratios[i].ratio;
386 break;
387 }
388 }
389 if (i == ARRAY_SIZE(fll_fratios)) {
390 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
391 return -EINVAL;
392 }
393
394 /* Now, calculate N.K */
395 Ndiv = target / Fref;
396
397 fll_div->n = Ndiv;
398 Nmod = target % Fref;
399 pr_debug("Nmod=%d\n", Nmod);
400
401 /* Calculate fractional part - scale up so we can round. */
402 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
403
404 do_div(Kpart, Fref);
405
406 K = Kpart & 0xFFFFFFFF;
407
408 if ((K % 10) >= 5)
409 K += 5;
410
411 /* Move down to proper range now rounding is done */
412 fll_div->k = K / 10;
413
414 pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
415 fll_div->n, fll_div->k,
416 fll_div->fll_fratio, fll_div->fll_outdiv,
417 fll_div->fll_clk_ref_div);
418
419 return 0;
420}
421
422static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id,
423 unsigned int Fref, unsigned int Fout)
424{
425 struct snd_soc_codec *codec = dai->codec;
426 struct wm8993_priv *wm8993 = codec->private_data;
427 u16 reg1, reg4, reg5;
428 struct _fll_div fll_div;
429 int ret;
430
431 /* Any change? */
432 if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout)
433 return 0;
434
435 /* Disable the FLL */
436 if (Fout == 0) {
437 dev_dbg(codec->dev, "FLL disabled\n");
438 wm8993->fll_fref = 0;
439 wm8993->fll_fout = 0;
440
441 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
442 reg1 &= ~WM8993_FLL_ENA;
443 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
444
445 return 0;
446 }
447
448 ret = fll_factors(&fll_div, Fref, Fout);
449 if (ret != 0)
450 return ret;
451
452 reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5);
453 reg5 &= ~WM8993_FLL_CLK_SRC_MASK;
454
455 switch (fll_id) {
456 case WM8993_FLL_MCLK:
457 break;
458
459 case WM8993_FLL_LRCLK:
460 reg5 |= 1;
461 break;
462
463 case WM8993_FLL_BCLK:
464 reg5 |= 2;
465 break;
466
467 default:
468 dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
469 return -EINVAL;
470 }
471
472 /* Any FLL configuration change requires that the FLL be
473 * disabled first. */
474 reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
475 reg1 &= ~WM8993_FLL_ENA;
476 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
477
478 /* Apply the configuration */
479 if (fll_div.k)
480 reg1 |= WM8993_FLL_FRAC_MASK;
481 else
482 reg1 &= ~WM8993_FLL_FRAC_MASK;
483 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
484
485 wm8993_write(codec, WM8993_FLL_CONTROL_2,
486 (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) |
487 (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT));
488 wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k);
489
490 reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4);
491 reg4 &= ~WM8993_FLL_N_MASK;
492 reg4 |= fll_div.n << WM8993_FLL_N_SHIFT;
493 wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4);
494
495 reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK;
496 reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
497 wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5);
498
499 /* Enable the FLL */
500 wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
501
502 dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
503
504 wm8993->fll_fref = Fref;
505 wm8993->fll_fout = Fout;
506
507 return 0;
508}
509
510static int configure_clock(struct snd_soc_codec *codec)
511{
512 struct wm8993_priv *wm8993 = codec->private_data;
513 unsigned int reg;
514
515 /* This should be done on init() for bypass paths */
516 switch (wm8993->sysclk_source) {
517 case WM8993_SYSCLK_MCLK:
518 dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate);
519
520 reg = wm8993_read(codec, WM8993_CLOCKING_2);
521 reg &= ~WM8993_SYSCLK_SRC;
522 if (wm8993->mclk_rate > 13500000) {
523 reg |= WM8993_MCLK_DIV;
524 wm8993->sysclk_rate = wm8993->mclk_rate / 2;
525 } else {
526 reg &= ~WM8993_MCLK_DIV;
527 wm8993->sysclk_rate = wm8993->mclk_rate;
528 }
529 reg &= ~WM8993_MCLK_DIV;
530 reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC);
531 wm8993_write(codec, WM8993_CLOCKING_2, reg);
532 break;
533
534 case WM8993_SYSCLK_FLL:
535 dev_dbg(codec->dev, "Using %dHz FLL clock\n",
536 wm8993->fll_fout);
537
538 reg = wm8993_read(codec, WM8993_CLOCKING_2);
539 reg |= WM8993_SYSCLK_SRC;
540 if (wm8993->fll_fout > 13500000) {
541 reg |= WM8993_MCLK_DIV;
542 wm8993->sysclk_rate = wm8993->fll_fout / 2;
543 } else {
544 reg &= ~WM8993_MCLK_DIV;
545 wm8993->sysclk_rate = wm8993->fll_fout;
546 }
547 wm8993_write(codec, WM8993_CLOCKING_2, reg);
548 break;
549
550 default:
551 dev_err(codec->dev, "System clock not configured\n");
552 return -EINVAL;
553 }
554
555 dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate);
556
557 return 0;
558}
559
560static void wait_for_dc_servo(struct snd_soc_codec *codec, int mask)
561{
562 unsigned int reg;
563 int count = 0;
564
565 dev_dbg(codec->dev, "Waiting for DC servo...\n");
566 do {
567 count++;
568 msleep(1);
569 reg = wm8993_read(codec, WM8993_DC_SERVO_READBACK_0);
570 dev_dbg(codec->dev, "DC servo status: %x\n", reg);
571 } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
572 != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000);
573
574 if ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
575 != WM8993_DCS_CAL_COMPLETE_MASK)
576 dev_err(codec->dev, "Timed out waiting for DC Servo\n");
577}
578
579static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
580static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
581static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
582static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
583static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
584static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
585static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
586static const unsigned int drc_max_tlv[] = {
587 TLV_DB_RANGE_HEAD(4),
588 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
589 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
590};
591static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
592static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
593static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
594static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
595static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
596static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
597static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
598static const DECLARE_TLV_DB_SCALE(spkmix_tlv, -300, 300, 0);
599static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
600static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
601static const unsigned int spkboost_tlv[] = {
602 TLV_DB_RANGE_HEAD(7),
603 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
604 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
605};
606static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
607
608static const char *speaker_ref_text[] = {
609 "SPKVDD/2",
610 "VMID",
611};
612
613static const struct soc_enum speaker_ref =
614 SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text);
615
616static const char *speaker_mode_text[] = {
617 "Class D",
618 "Class AB",
619};
620
621static const struct soc_enum speaker_mode =
622 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
623
624static const char *dac_deemph_text[] = {
625 "None",
626 "32kHz",
627 "44.1kHz",
628 "48kHz",
629};
630
631static const struct soc_enum dac_deemph =
632 SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text);
633
634static const char *adc_hpf_text[] = {
635 "Hi-Fi",
636 "Voice 1",
637 "Voice 2",
638 "Voice 3",
639};
640
641static const struct soc_enum adc_hpf =
642 SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text);
643
644static const char *drc_path_text[] = {
645 "ADC",
646 "DAC"
647};
648
649static const struct soc_enum drc_path =
650 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);
651
652static const char *drc_r0_text[] = {
653 "1",
654 "1/2",
655 "1/4",
656 "1/8",
657 "1/16",
658 "0",
659};
660
661static const struct soc_enum drc_r0 =
662 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text);
663
664static const char *drc_r1_text[] = {
665 "1",
666 "1/2",
667 "1/4",
668 "1/8",
669 "0",
670};
671
672static const struct soc_enum drc_r1 =
673 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text);
674
675static const char *drc_attack_text[] = {
676 "Reserved",
677 "181us",
678 "363us",
679 "726us",
680 "1.45ms",
681 "2.9ms",
682 "5.8ms",
683 "11.6ms",
684 "23.2ms",
685 "46.4ms",
686 "92.8ms",
687 "185.6ms",
688};
689
690static const struct soc_enum drc_attack =
691 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text);
692
693static const char *drc_decay_text[] = {
694 "186ms",
695 "372ms",
696 "743ms",
697 "1.49s",
698 "2.97ms",
699 "5.94ms",
700 "11.89ms",
701 "23.78ms",
702 "47.56ms",
703};
704
705static const struct soc_enum drc_decay =
706 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text);
707
708static const char *drc_ff_text[] = {
709 "5 samples",
710 "9 samples",
711};
712
713static const struct soc_enum drc_ff =
714 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text);
715
716static const char *drc_qr_rate_text[] = {
717 "0.725ms",
718 "1.45ms",
719 "5.8ms",
720};
721
722static const struct soc_enum drc_qr_rate =
723 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text);
724
725static const char *drc_smooth_text[] = {
726 "Low",
727 "Medium",
728 "High",
729};
730
731static const struct soc_enum drc_smooth =
732 SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text);
733
734
735/*
736 * Update the DC servo calibration on gain changes
737 */
738static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
739 struct snd_ctl_elem_value *ucontrol)
740{
741 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
742 int ret;
743
744 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
745
746 /* Only need to do this if the outputs are active */
747 if (wm8993_read(codec, WM8993_POWER_MANAGEMENT_1)
748 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
749 snd_soc_update_bits(codec,
750 WM8993_DC_SERVO_0,
751 WM8993_DCS_TRIG_SINGLE_0 |
752 WM8993_DCS_TRIG_SINGLE_1,
753 WM8993_DCS_TRIG_SINGLE_0 |
754 WM8993_DCS_TRIG_SINGLE_1);
755
756 return ret;
757}
758
759static const struct snd_kcontrol_new wm8993_snd_controls[] = {
760SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
761 inpga_tlv),
762SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
763SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
764
765SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
766 inpga_tlv),
767SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
768SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
769
770
771SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
772 inpga_tlv),
773SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
774SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
775
776SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
777 inpga_tlv),
778SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
779SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
780
781SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
782 inmix_sw_tlv),
783SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
784 inmix_sw_tlv),
785SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
786 inmix_tlv),
787SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
788SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
789 inmix_tlv),
790
791SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
792 inmix_sw_tlv),
793SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
794 inmix_sw_tlv),
795SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
796 inmix_tlv),
797SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
798SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
799 inmix_tlv),
800
801SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE,
802 5, 9, 12, 0, sidetone_tlv),
803
804SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0),
805SOC_ENUM("DRC Path", drc_path),
806SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2,
807 2, 60, 1, drc_comp_threash),
808SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3,
809 11, 30, 1, drc_comp_amp),
810SOC_ENUM("DRC R0", drc_r0),
811SOC_ENUM("DRC R1", drc_r1),
812SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1,
813 drc_min_tlv),
814SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0,
815 drc_max_tlv),
816SOC_ENUM("DRC Attack Rate", drc_attack),
817SOC_ENUM("DRC Decay Rate", drc_decay),
818SOC_ENUM("DRC FF Delay", drc_ff),
819SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0),
820SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0),
821SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0,
822 drc_qr_tlv),
823SOC_ENUM("DRC Quick Release Rate", drc_qr_rate),
824SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0),
825SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0),
826SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth),
827SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0,
828 drc_startup_tlv),
829
830SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0),
831
832SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME,
833 WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
834SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0),
835SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
836
837SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME,
838 WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
839SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0,
840 dac_boost_tlv),
841SOC_ENUM("DAC Deemphasis", dac_deemph),
842
843SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
844 outmix_tlv),
845SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
846 outmix_tlv),
847SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
848 outmix_tlv),
849SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
850 outmix_tlv),
851SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
852 outmix_tlv),
853SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
854 WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
855SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
856 WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
857SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
858 outmix_tlv),
859
860SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
861 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
862SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
863 WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
864SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
865 WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
866SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
867 WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
868SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
869 WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
870SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
871 WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
872SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
873 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
874SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
875 WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
876
877SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
878 WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
879SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
880 WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
881SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
882 WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
883
884SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
885SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
886
887SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
888 5, 1, 1, spkmix_tlv),
889SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
890 4, 1, 1, spkmix_tlv),
891SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
892 3, 1, 1, spkmix_tlv),
893SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION,
894 2, 1, 1, spkmix_tlv),
895
896SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
897 5, 1, 1, spkmix_tlv),
898SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
899 4, 1, 1, spkmix_tlv),
900SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
901 3, 1, 1, spkmix_tlv),
902SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION,
903 2, 1, 1, spkmix_tlv),
904
905SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
906 WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
907 0, 3, 1, spkmixout_tlv),
908SOC_DOUBLE_R_TLV("Speaker Volume",
909 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
910 0, 63, 0, outpga_tlv),
911SOC_DOUBLE_R("Speaker Switch",
912 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
913 6, 1, 0),
914SOC_DOUBLE_R("Speaker ZC Switch",
915 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
916 7, 1, 0),
917SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
918 spkboost_tlv),
919SOC_ENUM("Speaker Reference", speaker_ref),
920SOC_ENUM("Speaker Mode", speaker_mode),
921
922{
923 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
924 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
925 SNDRV_CTL_ELEM_ACCESS_READWRITE,
926 .tlv.p = outpga_tlv,
927 .info = snd_soc_info_volsw_2r,
928 .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
929 .private_value = (unsigned long)&(struct soc_mixer_control) {
930 .reg = WM8993_LEFT_OUTPUT_VOLUME,
931 .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
932 .shift = 0, .max = 63
933 },
934},
935SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
936 WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
937SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
938 WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
939
940SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
941SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
942SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
943 line_tlv),
944
945SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
946SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
947SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
948 line_tlv),
949};
950
951static const struct snd_kcontrol_new wm8993_eq_controls[] = {
952SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv),
953SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv),
954SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv),
955SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv),
956SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv),
957};
958
959static int wm8993_earpiece_event(struct snd_soc_dapm_widget *w,
960 struct snd_kcontrol *control, int event)
961{
962 struct snd_soc_codec *codec = w->codec;
963 u16 reg = wm8993_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
964
965 switch (event) {
966 case SND_SOC_DAPM_PRE_PMU:
967 reg |= WM8993_HPOUT2_IN_ENA;
968 wm8993_write(codec, WM8993_ANTIPOP1, reg);
969 udelay(50);
970 break;
971
972 case SND_SOC_DAPM_POST_PMD:
973 wm8993_write(codec, WM8993_ANTIPOP1, reg);
974 break;
975
976 default:
977 BUG();
978 break;
979 }
980
981 return 0;
982}
983
984static int clk_sys_event(struct snd_soc_dapm_widget *w,
985 struct snd_kcontrol *kcontrol, int event)
986{
987 struct snd_soc_codec *codec = w->codec;
988
989 switch (event) {
990 case SND_SOC_DAPM_PRE_PMU:
991 return configure_clock(codec);
992
993 case SND_SOC_DAPM_POST_PMD:
994 break;
995 }
996
997 return 0;
998}
999
1000/*
1001 * When used with DAC outputs only the WM8993 charge pump supports
1002 * operation in class W mode, providing very low power consumption
1003 * when used with digital sources. Enable and disable this mode
1004 * automatically depending on the mixer configuration.
1005 *
1006 * Currently the only supported paths are the direct DAC->headphone
1007 * paths (which provide minimum power consumption anyway).
1008 */
1009static int wm8993_class_w_put(struct snd_kcontrol *kcontrol,
1010 struct snd_ctl_elem_value *ucontrol)
1011{
1012 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1013 struct snd_soc_codec *codec = widget->codec;
1014 struct wm8993_priv *wm8993 = codec->private_data;
1015 int ret;
1016
1017 /* Turn it off if we're using the main output mixer */
1018 if (ucontrol->value.integer.value[0] == 0) {
1019 if (wm8993->class_w_users == 0) {
1020 dev_dbg(codec->dev, "Disabling Class W\n");
1021 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
1022 WM8993_CP_DYN_FREQ |
1023 WM8993_CP_DYN_V,
1024 0);
1025 }
1026 wm8993->class_w_users++;
1027 }
1028
1029 /* Implement the change */
1030 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1031
1032 /* Enable it if we're using the direct DAC path */
1033 if (ucontrol->value.integer.value[0] == 1) {
1034 if (wm8993->class_w_users == 1) {
1035 dev_dbg(codec->dev, "Enabling Class W\n");
1036 snd_soc_update_bits(codec, WM8993_CLASS_W_0,
1037 WM8993_CP_DYN_FREQ |
1038 WM8993_CP_DYN_V,
1039 WM8993_CP_DYN_FREQ |
1040 WM8993_CP_DYN_V);
1041 }
1042 wm8993->class_w_users--;
1043 }
1044
1045 dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
1046 wm8993->class_w_users);
1047
1048 return ret;
1049}
1050
1051#define SOC_DAPM_ENUM_W(xname, xenum) \
1052{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1053 .info = snd_soc_info_enum_double, \
1054 .get = snd_soc_dapm_get_enum_double, \
1055 .put = wm8993_class_w_put, \
1056 .private_value = (unsigned long)&xenum }
1057
1058static int hp_event(struct snd_soc_dapm_widget *w,
1059 struct snd_kcontrol *kcontrol, int event)
1060{
1061 struct snd_soc_codec *codec = w->codec;
1062 unsigned int reg = wm8993_read(codec, WM8993_ANALOGUE_HP_0);
1063
1064 switch (event) {
1065 case SND_SOC_DAPM_POST_PMU:
1066 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
1067 WM8993_CP_ENA, WM8993_CP_ENA);
1068
1069 msleep(5);
1070
1071 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1072 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
1073 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
1074
1075 reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
1076 wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg);
1077
1078 /* Start the DC servo */
1079 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
1080 WM8993_DCS_ENA_CHAN_0 |
1081 WM8993_DCS_ENA_CHAN_1 |
1082 WM8993_DCS_TRIG_STARTUP_1 |
1083 WM8993_DCS_TRIG_STARTUP_0,
1084 WM8993_DCS_ENA_CHAN_0 |
1085 WM8993_DCS_ENA_CHAN_1 |
1086 WM8993_DCS_TRIG_STARTUP_1 |
1087 WM8993_DCS_TRIG_STARTUP_0);
1088 wait_for_dc_servo(codec, WM8993_DCS_TRIG_STARTUP_0 |
1089 WM8993_DCS_TRIG_STARTUP_1);
1090 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
1091 WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa);
1092
1093 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
1094 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
1095 wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg);
1096 break;
1097
1098 case SND_SOC_DAPM_PRE_PMD:
1099 reg &= ~(WM8993_HPOUT1L_RMV_SHORT |
1100 WM8993_HPOUT1L_DLY |
1101 WM8993_HPOUT1L_OUTP |
1102 WM8993_HPOUT1R_RMV_SHORT |
1103 WM8993_HPOUT1R_DLY |
1104 WM8993_HPOUT1R_OUTP);
1105
1106 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
1107 WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
1108 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
1109 WM8993_DCS_ENA_CHAN_0 |
1110 WM8993_DCS_ENA_CHAN_1, 0);
1111
1112 wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg);
1113 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1114 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
1115 0);
1116
1117 snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
1118 WM8993_CP_ENA, 0);
1119 break;
1120 }
1121
1122 return 0;
1123}
1124
1125static const struct snd_kcontrol_new in1l_pga[] = {
1126SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
1127SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
1128};
1129
1130static const struct snd_kcontrol_new in1r_pga[] = {
1131SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
1132SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
1133};
1134
1135static const struct snd_kcontrol_new in2l_pga[] = {
1136SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
1137SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
1138};
1139
1140static const struct snd_kcontrol_new in2r_pga[] = {
1141SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
1142SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
1143};
1144
1145static const struct snd_kcontrol_new mixinl[] = {
1146SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
1147SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
1148};
1149
1150static const struct snd_kcontrol_new mixinr[] = {
1151SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
1152SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
1153};
1154
1155static const struct snd_kcontrol_new left_output_mixer[] = {
1156SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
1157SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
1158SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
1159SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
1160SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
1161SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
1162SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
1163SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
1164};
1165
1166static const struct snd_kcontrol_new right_output_mixer[] = {
1167SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
1168SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
1169SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
1170SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
1171SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
1172SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
1173SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
1174SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
1175};
1176
1177static const struct snd_kcontrol_new earpiece_mixer[] = {
1178SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
1179SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
1180SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
1181};
1182
1183static const struct snd_kcontrol_new left_speaker_mixer[] = {
1184SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
1185SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
1186SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0),
1187SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
1188};
1189
1190static const struct snd_kcontrol_new right_speaker_mixer[] = {
1191SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
1192SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0),
1193SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0),
1194SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0),
1195};
1196
1197static const struct snd_kcontrol_new left_speaker_boost[] = {
1198SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
1199SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
1200SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
1201};
1202
1203static const struct snd_kcontrol_new right_speaker_boost[] = {
1204SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
1205SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
1206SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
1207};
1208
1209static const char *hp_mux_text[] = {
1210 "Mixer",
1211 "DAC",
1212};
1213
1214static const struct soc_enum hpl_enum =
1215 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
1216
1217static const struct snd_kcontrol_new hpl_mux =
1218 SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
1219
1220static const struct soc_enum hpr_enum =
1221 SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
1222
1223static const struct snd_kcontrol_new hpr_mux =
1224 SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
1225
1226static const struct snd_kcontrol_new line1_mix[] = {
1227SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
1228SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
1229SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
1230};
1231
1232static const struct snd_kcontrol_new line1n_mix[] = {
1233SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
1234SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
1235};
1236
1237static const struct snd_kcontrol_new line1p_mix[] = {
1238SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
1239};
1240
1241static const struct snd_kcontrol_new line2_mix[] = {
1242SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
1243SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
1244SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
1245};
1246
1247static const struct snd_kcontrol_new line2n_mix[] = {
1248SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
1249SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
1250};
1251
1252static const struct snd_kcontrol_new line2p_mix[] = {
1253SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
1254};
1255
1256static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {
1257SND_SOC_DAPM_INPUT("IN1LN"),
1258SND_SOC_DAPM_INPUT("IN1LP"),
1259SND_SOC_DAPM_INPUT("IN2LN"),
1260SND_SOC_DAPM_INPUT("IN2LP/VXRN"),
1261SND_SOC_DAPM_INPUT("IN1RN"),
1262SND_SOC_DAPM_INPUT("IN1RP"),
1263SND_SOC_DAPM_INPUT("IN2RN"),
1264SND_SOC_DAPM_INPUT("IN2RP/VXRP"),
1265
1266SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
1267 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1268SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
1269SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
1270
1271SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
1272SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
1273
1274SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
1275 in1l_pga, ARRAY_SIZE(in1l_pga)),
1276SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
1277 in1r_pga, ARRAY_SIZE(in1r_pga)),
1278
1279SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
1280 in2l_pga, ARRAY_SIZE(in2l_pga)),
1281SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
1282 in2r_pga, ARRAY_SIZE(in2r_pga)),
1283
1284/* Dummy widgets to represent differential paths */
1285SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
1286
1287SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
1288 mixinl, ARRAY_SIZE(mixinl)),
1289SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
1290 mixinr, ARRAY_SIZE(mixinr)),
1291
1292SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0),
1293SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0),
1294
1295SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0),
1296SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0),
1297
1298SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
1299 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
1300SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
1301 right_output_mixer, ARRAY_SIZE(right_output_mixer)),
1302
1303SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
1304SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
1305
1306SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
1307 earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
1308SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
1309 NULL, 0, wm8993_earpiece_event,
1310 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1311
1312SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
1313 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
1314SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0,
1315 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
1316
1317SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
1318 left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
1319SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
1320 right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
1321
1322SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
1323 NULL, 0),
1324SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
1325 NULL, 0),
1326
1327SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
1328SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
1329SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
1330 NULL, 0,
1331 hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
1332
1333SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
1334 line1_mix, ARRAY_SIZE(line1_mix)),
1335SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
1336 line2_mix, ARRAY_SIZE(line2_mix)),
1337
1338SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
1339 line1n_mix, ARRAY_SIZE(line1n_mix)),
1340SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
1341 line1p_mix, ARRAY_SIZE(line1p_mix)),
1342SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
1343 line2n_mix, ARRAY_SIZE(line2n_mix)),
1344SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
1345 line2p_mix, ARRAY_SIZE(line2p_mix)),
1346
1347SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
1348 NULL, 0),
1349SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
1350 NULL, 0),
1351SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
1352 NULL, 0),
1353SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
1354 NULL, 0),
1355
1356SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
1357SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
1358SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
1359SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
1360SND_SOC_DAPM_OUTPUT("HPOUT1L"),
1361SND_SOC_DAPM_OUTPUT("HPOUT1R"),
1362SND_SOC_DAPM_OUTPUT("HPOUT2P"),
1363SND_SOC_DAPM_OUTPUT("HPOUT2N"),
1364SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
1365SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
1366SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
1367SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
1368};
1369
1370static const struct snd_soc_dapm_route routes[] = {
1371 { "IN1L PGA", "IN1LP Switch", "IN1LP" },
1372 { "IN1L PGA", "IN1LN Switch", "IN1LN" },
1373
1374 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
1375 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
1376
1377 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" },
1378 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
1379
1380 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" },
1381 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
1382
1383 { "Direct Voice", NULL, "IN2LP/VXRN" },
1384 { "Direct Voice", NULL, "IN2RP/VXRP" },
1385
1386 { "MIXINL", "IN1L Switch", "IN1L PGA" },
1387 { "MIXINL", "IN2L Switch", "IN2L PGA" },
1388 { "MIXINL", NULL, "Direct Voice" },
1389 { "MIXINL", NULL, "IN1LP" },
1390 { "MIXINL", NULL, "Left Output Mixer" },
1391
1392 { "MIXINR", "IN1R Switch", "IN1R PGA" },
1393 { "MIXINR", "IN2R Switch", "IN2R PGA" },
1394 { "MIXINR", NULL, "Direct Voice" },
1395 { "MIXINR", NULL, "IN1RP" },
1396 { "MIXINR", NULL, "Right Output Mixer" },
1397
1398 { "ADCL", NULL, "MIXINL" },
1399 { "ADCL", NULL, "CLK_SYS" },
1400 { "ADCL", NULL, "CLK_DSP" },
1401 { "ADCR", NULL, "MIXINR" },
1402 { "ADCR", NULL, "CLK_SYS" },
1403 { "ADCR", NULL, "CLK_DSP" },
1404
1405 { "DACL", NULL, "CLK_SYS" },
1406 { "DACL", NULL, "CLK_DSP" },
1407 { "DACR", NULL, "CLK_SYS" },
1408 { "DACR", NULL, "CLK_DSP" },
1409
1410 { "Left Output Mixer", "Left Input Switch", "MIXINL" },
1411 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
1412 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
1413 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
1414 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" },
1415 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
1416 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
1417 { "Left Output Mixer", "DAC Switch", "DACL" },
1418
1419 { "Right Output Mixer", "Left Input Switch", "MIXINL" },
1420 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
1421 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
1422 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
1423 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" },
1424 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
1425 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
1426 { "Right Output Mixer", "DAC Switch", "DACR" },
1427
1428 { "Left Output PGA", NULL, "Left Output Mixer" },
1429 { "Left Output PGA", NULL, "CLK_SYS" },
1430 { "Left Output PGA", NULL, "TOCLK" },
1431
1432 { "Right Output PGA", NULL, "Right Output Mixer" },
1433 { "Right Output PGA", NULL, "CLK_SYS" },
1434 { "Right Output PGA", NULL, "TOCLK" },
1435
1436 { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
1437 { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
1438 { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
1439
1440 { "Earpiece Driver", NULL, "Earpiece Mixer" },
1441 { "HPOUT2N", NULL, "Earpiece Driver" },
1442 { "HPOUT2P", NULL, "Earpiece Driver" },
1443
1444 { "SPKL", "Input Switch", "MIXINL" },
1445 { "SPKL", "IN1LP Switch", "IN1LP" },
1446 { "SPKL", "Output Switch", "Left Output Mixer" },
1447 { "SPKL", "DAC Switch", "DACL" },
1448 { "SPKL", NULL, "CLK_SYS" },
1449 { "SPKL", NULL, "TOCLK" },
1450
1451 { "SPKR", "Input Switch", "MIXINR" },
1452 { "SPKR", "IN1RP Switch", "IN1RP" },
1453 { "SPKR", "Output Switch", "Right Output Mixer" },
1454 { "SPKR", "DAC Switch", "DACR" },
1455 { "SPKR", NULL, "CLK_SYS" },
1456 { "SPKR", NULL, "TOCLK" },
1457
1458 { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
1459 { "SPKL Boost", "SPKL Switch", "SPKL" },
1460 { "SPKL Boost", "SPKR Switch", "SPKR" },
1461
1462 { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
1463 { "SPKR Boost", "SPKR Switch", "SPKR" },
1464 { "SPKR Boost", "SPKL Switch", "SPKL" },
1465
1466 { "SPKL Driver", NULL, "SPKL Boost" },
1467 { "SPKL Driver", NULL, "CLK_SYS" },
1468
1469 { "SPKR Driver", NULL, "SPKR Boost" },
1470 { "SPKR Driver", NULL, "CLK_SYS" },
1471
1472 { "SPKOUTLP", NULL, "SPKL Driver" },
1473 { "SPKOUTLN", NULL, "SPKL Driver" },
1474 { "SPKOUTRP", NULL, "SPKR Driver" },
1475 { "SPKOUTRN", NULL, "SPKR Driver" },
1476
1477 { "Left Headphone Mux", "DAC", "DACL" },
1478 { "Left Headphone Mux", "Mixer", "Left Output Mixer" },
1479 { "Right Headphone Mux", "DAC", "DACR" },
1480 { "Right Headphone Mux", "Mixer", "Right Output Mixer" },
1481
1482 { "Headphone PGA", NULL, "Left Headphone Mux" },
1483 { "Headphone PGA", NULL, "Right Headphone Mux" },
1484 { "Headphone PGA", NULL, "CLK_SYS" },
1485 { "Headphone PGA", NULL, "TOCLK" },
1486
1487 { "HPOUT1L", NULL, "Headphone PGA" },
1488 { "HPOUT1R", NULL, "Headphone PGA" },
1489
1490 { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
1491 { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
1492 { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
1493 { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
1494};
1495
1496static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
1497 { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
1498 { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
1499 { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
1500
1501 { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
1502 { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
1503};
1504
1505static const struct snd_soc_dapm_route lineout1_se_routes[] = {
1506 { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
1507 { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
1508
1509 { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
1510
1511 { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
1512 { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
1513};
1514
1515static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
1516 { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
1517 { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
1518 { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
1519
1520 { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
1521 { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
1522};
1523
1524static const struct snd_soc_dapm_route lineout2_se_routes[] = {
1525 { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
1526 { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
1527
1528 { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
1529
1530 { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
1531 { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
1532};
1533
1534static int wm8993_set_bias_level(struct snd_soc_codec *codec,
1535 enum snd_soc_bias_level level)
1536{
1537 struct wm8993_priv *wm8993 = codec->private_data;
1538
1539 switch (level) {
1540 case SND_SOC_BIAS_ON:
1541 case SND_SOC_BIAS_PREPARE:
1542 /* VMID=2*40k */
1543 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1544 WM8993_VMID_SEL_MASK, 0x2);
1545 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
1546 WM8993_TSHUT_ENA, WM8993_TSHUT_ENA);
1547 break;
1548
1549 case SND_SOC_BIAS_STANDBY:
1550 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1551 /* Bring up VMID with fast soft start */
1552 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
1553 WM8993_STARTUP_BIAS_ENA |
1554 WM8993_VMID_BUF_ENA |
1555 WM8993_VMID_RAMP_MASK |
1556 WM8993_BIAS_SRC,
1557 WM8993_STARTUP_BIAS_ENA |
1558 WM8993_VMID_BUF_ENA |
1559 WM8993_VMID_RAMP_MASK |
1560 WM8993_BIAS_SRC);
1561
1562 /* If either line output is single ended we
1563 * need the VMID buffer */
1564 if (!wm8993->pdata.lineout1_diff ||
1565 !wm8993->pdata.lineout2_diff)
1566 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
1567 WM8993_LINEOUT_VMID_BUF_ENA,
1568 WM8993_LINEOUT_VMID_BUF_ENA);
1569
1570 /* VMID=2*40k */
1571 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1572 WM8993_VMID_SEL_MASK |
1573 WM8993_BIAS_ENA,
1574 WM8993_BIAS_ENA | 0x2);
1575 msleep(32);
1576
1577 /* Switch to normal bias */
1578 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
1579 WM8993_BIAS_SRC |
1580 WM8993_STARTUP_BIAS_ENA, 0);
1581 }
1582
1583 /* VMID=2*240k */
1584 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1585 WM8993_VMID_SEL_MASK, 0x4);
1586
1587 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
1588 WM8993_TSHUT_ENA, 0);
1589 break;
1590
1591 case SND_SOC_BIAS_OFF:
1592 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
1593 WM8993_LINEOUT_VMID_BUF_ENA, 0);
1594
1595 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
1596 WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA,
1597 0);
1598 break;
1599 }
1600
1601 codec->bias_level = level;
1602
1603 return 0;
1604}
1605
1606static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai,
1607 int clk_id, unsigned int freq, int dir)
1608{
1609 struct snd_soc_codec *codec = codec_dai->codec;
1610 struct wm8993_priv *wm8993 = codec->private_data;
1611
1612 switch (clk_id) {
1613 case WM8993_SYSCLK_MCLK:
1614 wm8993->mclk_rate = freq;
1615 case WM8993_SYSCLK_FLL:
1616 wm8993->sysclk_source = clk_id;
1617 break;
1618
1619 default:
1620 return -EINVAL;
1621 }
1622
1623 return 0;
1624}
1625
1626static int wm8993_set_dai_fmt(struct snd_soc_dai *dai,
1627 unsigned int fmt)
1628{
1629 struct snd_soc_codec *codec = dai->codec;
1630 struct wm8993_priv *wm8993 = codec->private_data;
1631 unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
1632 unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1633
1634 aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV |
1635 WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK);
1636 aif4 &= ~WM8993_LRCLK_DIR;
1637
1638 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1639 case SND_SOC_DAIFMT_CBS_CFS:
1640 wm8993->master = 0;
1641 break;
1642 case SND_SOC_DAIFMT_CBS_CFM:
1643 aif4 |= WM8993_LRCLK_DIR;
1644 wm8993->master = 1;
1645 break;
1646 case SND_SOC_DAIFMT_CBM_CFS:
1647 aif1 |= WM8993_BCLK_DIR;
1648 wm8993->master = 1;
1649 break;
1650 case SND_SOC_DAIFMT_CBM_CFM:
1651 aif1 |= WM8993_BCLK_DIR;
1652 aif4 |= WM8993_LRCLK_DIR;
1653 wm8993->master = 1;
1654 break;
1655 default:
1656 return -EINVAL;
1657 }
1658
1659 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1660 case SND_SOC_DAIFMT_DSP_B:
1661 aif1 |= WM8993_AIF_LRCLK_INV;
1662 case SND_SOC_DAIFMT_DSP_A:
1663 aif1 |= 0x18;
1664 break;
1665 case SND_SOC_DAIFMT_I2S:
1666 aif1 |= 0x10;
1667 break;
1668 case SND_SOC_DAIFMT_RIGHT_J:
1669 break;
1670 case SND_SOC_DAIFMT_LEFT_J:
1671 aif1 |= 0x8;
1672 break;
1673 default:
1674 return -EINVAL;
1675 }
1676
1677 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1678 case SND_SOC_DAIFMT_DSP_A:
1679 case SND_SOC_DAIFMT_DSP_B:
1680 /* frame inversion not valid for DSP modes */
1681 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1682 case SND_SOC_DAIFMT_NB_NF:
1683 break;
1684 case SND_SOC_DAIFMT_IB_NF:
1685 aif1 |= WM8993_AIF_BCLK_INV;
1686 break;
1687 default:
1688 return -EINVAL;
1689 }
1690 break;
1691
1692 case SND_SOC_DAIFMT_I2S:
1693 case SND_SOC_DAIFMT_RIGHT_J:
1694 case SND_SOC_DAIFMT_LEFT_J:
1695 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1696 case SND_SOC_DAIFMT_NB_NF:
1697 break;
1698 case SND_SOC_DAIFMT_IB_IF:
1699 aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV;
1700 break;
1701 case SND_SOC_DAIFMT_IB_NF:
1702 aif1 |= WM8993_AIF_BCLK_INV;
1703 break;
1704 case SND_SOC_DAIFMT_NB_IF:
1705 aif1 |= WM8993_AIF_LRCLK_INV;
1706 break;
1707 default:
1708 return -EINVAL;
1709 }
1710 break;
1711 default:
1712 return -EINVAL;
1713 }
1714
1715 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1716 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1717
1718 return 0;
1719}
1720
1721static int wm8993_hw_params(struct snd_pcm_substream *substream,
1722 struct snd_pcm_hw_params *params,
1723 struct snd_soc_dai *dai)
1724{
1725 struct snd_soc_codec *codec = dai->codec;
1726 struct wm8993_priv *wm8993 = codec->private_data;
1727 int ret, i, best, best_val, cur_val;
1728 unsigned int clocking1, clocking3, aif1, aif4;
1729
1730 clocking1 = wm8993_read(codec, WM8993_CLOCKING_1);
1731 clocking1 &= ~WM8993_BCLK_DIV_MASK;
1732
1733 clocking3 = wm8993_read(codec, WM8993_CLOCKING_3);
1734 clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK);
1735
1736 aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
1737 aif1 &= ~WM8993_AIF_WL_MASK;
1738
1739 aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
1740 aif4 &= ~WM8993_LRCLK_RATE_MASK;
1741
1742 /* What BCLK do we need? */
1743 wm8993->fs = params_rate(params);
1744 wm8993->bclk = 2 * wm8993->fs;
1745 switch (params_format(params)) {
1746 case SNDRV_PCM_FORMAT_S16_LE:
1747 wm8993->bclk *= 16;
1748 break;
1749 case SNDRV_PCM_FORMAT_S20_3LE:
1750 wm8993->bclk *= 20;
1751 aif1 |= 0x8;
1752 break;
1753 case SNDRV_PCM_FORMAT_S24_LE:
1754 wm8993->bclk *= 24;
1755 aif1 |= 0x10;
1756 break;
1757 case SNDRV_PCM_FORMAT_S32_LE:
1758 wm8993->bclk *= 32;
1759 aif1 |= 0x18;
1760 break;
1761 default:
1762 return -EINVAL;
1763 }
1764
1765 dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk);
1766
1767 ret = configure_clock(codec);
1768 if (ret != 0)
1769 return ret;
1770
1771 /* Select nearest CLK_SYS_RATE */
1772 best = 0;
1773 best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio)
1774 - wm8993->fs);
1775 for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
1776 cur_val = abs((wm8993->sysclk_rate /
1777 clk_sys_rates[i].ratio) - wm8993->fs);;
1778 if (cur_val < best_val) {
1779 best = i;
1780 best_val = cur_val;
1781 }
1782 }
1783 dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
1784 clk_sys_rates[best].ratio);
1785 clocking3 |= (clk_sys_rates[best].clk_sys_rate
1786 << WM8993_CLK_SYS_RATE_SHIFT);
1787
1788 /* SAMPLE_RATE */
1789 best = 0;
1790 best_val = abs(wm8993->fs - sample_rates[0].rate);
1791 for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
1792 /* Closest match */
1793 cur_val = abs(wm8993->fs - sample_rates[i].rate);
1794 if (cur_val < best_val) {
1795 best = i;
1796 best_val = cur_val;
1797 }
1798 }
1799 dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
1800 sample_rates[best].rate);
1801 clocking3 |= (sample_rates[best].sample_rate
1802 << WM8993_SAMPLE_RATE_SHIFT);
1803
1804 /* BCLK_DIV */
1805 best = 0;
1806 best_val = INT_MAX;
1807 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1808 cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div)
1809 - wm8993->bclk;
1810 if (cur_val < 0) /* Table is sorted */
1811 break;
1812 if (cur_val < best_val) {
1813 best = i;
1814 best_val = cur_val;
1815 }
1816 }
1817 wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div;
1818 dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1819 bclk_divs[best].div, wm8993->bclk);
1820 clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT;
1821
1822 /* LRCLK is a simple fraction of BCLK */
1823 dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs);
1824 aif4 |= wm8993->bclk / wm8993->fs;
1825
1826 wm8993_write(codec, WM8993_CLOCKING_1, clocking1);
1827 wm8993_write(codec, WM8993_CLOCKING_3, clocking3);
1828 wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
1829 wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
1830
1831 /* ReTune Mobile? */
1832 if (wm8993->pdata.num_retune_configs) {
1833 u16 eq1 = wm8993_read(codec, WM8993_EQ1);
1834 struct wm8993_retune_mobile_setting *s;
1835
1836 best = 0;
1837 best_val = abs(wm8993->pdata.retune_configs[0].rate
1838 - wm8993->fs);
1839 for (i = 0; i < wm8993->pdata.num_retune_configs; i++) {
1840 cur_val = abs(wm8993->pdata.retune_configs[i].rate
1841 - wm8993->fs);
1842 if (cur_val < best_val) {
1843 best_val = cur_val;
1844 best = i;
1845 }
1846 }
1847 s = &wm8993->pdata.retune_configs[best];
1848
1849 dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
1850 s->name, s->rate);
1851
1852 /* Disable EQ while we reconfigure */
1853 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0);
1854
1855 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1856 wm8993_write(codec, WM8993_EQ1 + i, s->config[i]);
1857
1858 snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1);
1859 }
1860
1861 return 0;
1862}
1863
1864static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1865{
1866 struct snd_soc_codec *codec = codec_dai->codec;
1867 unsigned int reg;
1868
1869 reg = wm8993_read(codec, WM8993_DAC_CTRL);
1870
1871 if (mute)
1872 reg |= WM8993_DAC_MUTE;
1873 else
1874 reg &= ~WM8993_DAC_MUTE;
1875
1876 wm8993_write(codec, WM8993_DAC_CTRL, reg);
1877
1878 return 0;
1879}
1880
1881static struct snd_soc_dai_ops wm8993_ops = {
1882 .set_sysclk = wm8993_set_sysclk,
1883 .set_fmt = wm8993_set_dai_fmt,
1884 .hw_params = wm8993_hw_params,
1885 .digital_mute = wm8993_digital_mute,
1886 .set_pll = wm8993_set_fll,
1887};
1888
1889#define WM8993_RATES SNDRV_PCM_RATE_8000_48000
1890
1891#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1892 SNDRV_PCM_FMTBIT_S20_3LE |\
1893 SNDRV_PCM_FMTBIT_S24_LE |\
1894 SNDRV_PCM_FMTBIT_S32_LE)
1895
1896struct snd_soc_dai wm8993_dai = {
1897 .name = "WM8993",
1898 .playback = {
1899 .stream_name = "Playback",
1900 .channels_min = 1,
1901 .channels_max = 2,
1902 .rates = WM8993_RATES,
1903 .formats = WM8993_FORMATS,
1904 },
1905 .capture = {
1906 .stream_name = "Capture",
1907 .channels_min = 1,
1908 .channels_max = 2,
1909 .rates = WM8993_RATES,
1910 .formats = WM8993_FORMATS,
1911 },
1912 .ops = &wm8993_ops,
1913 .symmetric_rates = 1,
1914};
1915EXPORT_SYMBOL_GPL(wm8993_dai);
1916
1917static struct snd_soc_codec *wm8993_codec;
1918
1919static int wm8993_probe(struct platform_device *pdev)
1920{
1921 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1922 struct snd_soc_codec *codec;
1923 struct wm8993_priv *wm8993;
1924 int ret = 0;
1925
1926 if (!wm8993_codec) {
1927 dev_err(&pdev->dev, "I2C device not yet probed\n");
1928 goto err;
1929 }
1930
1931 socdev->card->codec = wm8993_codec;
1932 codec = wm8993_codec;
1933 wm8993 = codec->private_data;
1934
1935 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1936 if (ret < 0) {
1937 dev_err(codec->dev, "failed to create pcms\n");
1938 goto err;
1939 }
1940
1941 snd_soc_add_controls(codec, wm8993_snd_controls,
1942 ARRAY_SIZE(wm8993_snd_controls));
1943 if (wm8993->pdata.num_retune_configs != 0) {
1944 dev_dbg(codec->dev, "Using ReTune Mobile\n");
1945 } else {
1946 dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
1947 snd_soc_add_controls(codec, wm8993_eq_controls,
1948 ARRAY_SIZE(wm8993_eq_controls));
1949 }
1950
1951 snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets,
1952 ARRAY_SIZE(wm8993_dapm_widgets));
1953
1954 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
1955
1956 if (wm8993->pdata.lineout1_diff)
1957 snd_soc_dapm_add_routes(codec,
1958 lineout1_diff_routes,
1959 ARRAY_SIZE(lineout1_diff_routes));
1960 else
1961 snd_soc_dapm_add_routes(codec,
1962 lineout1_se_routes,
1963 ARRAY_SIZE(lineout1_se_routes));
1964
1965 if (wm8993->pdata.lineout2_diff)
1966 snd_soc_dapm_add_routes(codec,
1967 lineout2_diff_routes,
1968 ARRAY_SIZE(lineout2_diff_routes));
1969 else
1970 snd_soc_dapm_add_routes(codec,
1971 lineout2_se_routes,
1972 ARRAY_SIZE(lineout2_se_routes));
1973
1974 snd_soc_dapm_new_widgets(codec);
1975
1976 ret = snd_soc_init_card(socdev);
1977 if (ret < 0) {
1978 dev_err(codec->dev, "failed to register card\n");
1979 goto card_err;
1980 }
1981
1982 return ret;
1983
1984card_err:
1985 snd_soc_free_pcms(socdev);
1986 snd_soc_dapm_free(socdev);
1987err:
1988 return ret;
1989}
1990
1991static int wm8993_remove(struct platform_device *pdev)
1992{
1993 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1994
1995 snd_soc_free_pcms(socdev);
1996 snd_soc_dapm_free(socdev);
1997
1998 return 0;
1999}
2000
2001struct snd_soc_codec_device soc_codec_dev_wm8993 = {
2002 .probe = wm8993_probe,
2003 .remove = wm8993_remove,
2004};
2005EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
2006
2007static int wm8993_i2c_probe(struct i2c_client *i2c,
2008 const struct i2c_device_id *id)
2009{
2010 struct wm8993_priv *wm8993;
2011 struct snd_soc_codec *codec;
2012 unsigned int val;
2013 int ret;
2014
2015 if (wm8993_codec) {
2016 dev_err(&i2c->dev, "A WM8993 is already registered\n");
2017 return -EINVAL;
2018 }
2019
2020 wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
2021 if (wm8993 == NULL)
2022 return -ENOMEM;
2023
2024 codec = &wm8993->codec;
2025 if (i2c->dev.platform_data)
2026 memcpy(&wm8993->pdata, i2c->dev.platform_data,
2027 sizeof(wm8993->pdata));
2028
2029 mutex_init(&codec->mutex);
2030 INIT_LIST_HEAD(&codec->dapm_widgets);
2031 INIT_LIST_HEAD(&codec->dapm_paths);
2032
2033 codec->name = "WM8993";
2034 codec->read = wm8993_read;
2035 codec->write = wm8993_write;
2036 codec->hw_write = (hw_write_t)i2c_master_send;
2037 codec->reg_cache = wm8993->reg_cache;
2038 codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
2039 codec->bias_level = SND_SOC_BIAS_OFF;
2040 codec->set_bias_level = wm8993_set_bias_level;
2041 codec->dai = &wm8993_dai;
2042 codec->num_dai = 1;
2043 codec->private_data = wm8993;
2044
2045 memcpy(wm8993->reg_cache, wm8993_reg_defaults,
2046 sizeof(wm8993->reg_cache));
2047
2048 i2c_set_clientdata(i2c, wm8993);
2049 codec->control_data = i2c;
2050 wm8993_codec = codec;
2051
2052 codec->dev = &i2c->dev;
2053
2054 val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET);
2055 if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
2056 dev_err(codec->dev, "Invalid ID register value %x\n", val);
2057 ret = -EINVAL;
2058 goto err;
2059 }
2060
2061 ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
2062 if (ret != 0)
2063 goto err;
2064
2065 /* By default we're using the output mixers */
2066 wm8993->class_w_users = 2;
2067
2068 /* Latch volume update bits and default ZC on */
2069 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
2070 WM8993_IN1_VU, WM8993_IN1_VU);
2071 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
2072 WM8993_IN1_VU, WM8993_IN1_VU);
2073 snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
2074 WM8993_IN2_VU, WM8993_IN2_VU);
2075 snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
2076 WM8993_IN2_VU, WM8993_IN2_VU);
2077
2078 snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
2079 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
2080
2081 snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
2082 WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
2083 snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
2084 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
2085 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
2086
2087 snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
2088 WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
2089 snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
2090 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
2091 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
2092
2093 snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
2094 WM8993_DAC_VU, WM8993_DAC_VU);
2095 snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
2096 WM8993_ADC_VU, WM8993_ADC_VU);
2097
2098 /* Manualy manage the HPOUT sequencing for independent stereo
2099 * control. */
2100 snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
2101 WM8993_HPOUT1_AUTO_PU, 0);
2102
2103 /* Use automatic clock configuration */
2104 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
2105
2106 if (!wm8993->pdata.lineout1_diff)
2107 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
2108 WM8993_LINEOUT1_MODE,
2109 WM8993_LINEOUT1_MODE);
2110 if (!wm8993->pdata.lineout2_diff)
2111 snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
2112 WM8993_LINEOUT2_MODE,
2113 WM8993_LINEOUT2_MODE);
2114
2115 if (wm8993->pdata.lineout1fb)
2116 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
2117 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
2118
2119 if (wm8993->pdata.lineout2fb)
2120 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
2121 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
2122
2123 /* Apply the microphone bias/detection configuration - the
2124 * platform data is directly applicable to the register. */
2125 snd_soc_update_bits(codec, WM8993_MICBIAS,
2126 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
2127 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
2128 wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
2129 wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
2130 wm8993->pdata.micbias1_lvl |
2131 wm8993->pdata.micbias1_lvl << 1);
2132
2133 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2134 if (ret != 0)
2135 goto err;
2136
2137 wm8993_dai.dev = codec->dev;
2138
2139 ret = snd_soc_register_dai(&wm8993_dai);
2140 if (ret != 0)
2141 goto err_bias;
2142
2143 ret = snd_soc_register_codec(codec);
2144
2145 return 0;
2146
2147err_bias:
2148 wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
2149err:
2150 wm8993_codec = NULL;
2151 kfree(wm8993);
2152 return ret;
2153}
2154
2155static int wm8993_i2c_remove(struct i2c_client *client)
2156{
2157 struct wm8993_priv *wm8993 = i2c_get_clientdata(client);
2158
2159 snd_soc_unregister_codec(&wm8993->codec);
2160 snd_soc_unregister_dai(&wm8993_dai);
2161
2162 wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
2163 kfree(wm8993);
2164
2165 return 0;
2166}
2167
2168static const struct i2c_device_id wm8993_i2c_id[] = {
2169 { "wm8993", 0 },
2170 { }
2171};
2172MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
2173
2174static struct i2c_driver wm8993_i2c_driver = {
2175 .driver = {
2176 .name = "WM8993",
2177 .owner = THIS_MODULE,
2178 },
2179 .probe = wm8993_i2c_probe,
2180 .remove = wm8993_i2c_remove,
2181 .id_table = wm8993_i2c_id,
2182};
2183
2184
2185static int __init wm8993_modinit(void)
2186{
2187 int ret;
2188
2189 ret = i2c_add_driver(&wm8993_i2c_driver);
2190 if (ret != 0)
2191 pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
2192
2193 return ret;
2194}
2195module_init(wm8993_modinit);
2196
2197static void __exit wm8993_exit(void)
2198{
2199 i2c_del_driver(&wm8993_i2c_driver);
2200}
2201module_exit(wm8993_exit);
2202
2203
2204MODULE_DESCRIPTION("ASoC WM8993 driver");
2205MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2206MODULE_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
index 86fc57e25f97..156f2a4a5930 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -707,6 +707,10 @@ static int configure_clock(struct snd_soc_codec *codec)
707 target > 3000000) 707 target > 3000000)
708 break; 708 break;
709 } 709 }
710
711 if (i == ARRAY_SIZE(clk_sys_rates))
712 return -EINVAL;
713
710 } else if (wm9081->fs) { 714 } else if (wm9081->fs) {
711 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) { 715 for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
712 new_sysclk = clk_sys_rates[i].ratio 716 new_sysclk = clk_sys_rates[i].ratio
@@ -714,6 +718,10 @@ static int configure_clock(struct snd_soc_codec *codec)
714 if (new_sysclk > 3000000) 718 if (new_sysclk > 3000000)
715 break; 719 break;
716 } 720 }
721
722 if (i == ARRAY_SIZE(clk_sys_rates))
723 return -EINVAL;
724
717 } else { 725 } else {
718 new_sysclk = 12288000; 726 new_sysclk = 12288000;
719 } 727 }
@@ -1492,6 +1500,21 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1492 return 0; 1500 return 0;
1493} 1501}
1494 1502
1503#ifdef CONFIG_PM
1504static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1505{
1506 return snd_soc_suspend_device(&client->dev);
1507}
1508
1509static int wm9081_i2c_resume(struct i2c_client *client)
1510{
1511 return snd_soc_resume_device(&client->dev);
1512}
1513#else
1514#define wm9081_i2c_suspend NULL
1515#define wm9081_i2c_resume NULL
1516#endif
1517
1495static const struct i2c_device_id wm9081_i2c_id[] = { 1518static const struct i2c_device_id wm9081_i2c_id[] = {
1496 { "wm9081", 0 }, 1519 { "wm9081", 0 },
1497 { } 1520 { }
@@ -1505,6 +1528,8 @@ static struct i2c_driver wm9081_i2c_driver = {
1505 }, 1528 },
1506 .probe = wm9081_i2c_probe, 1529 .probe = wm9081_i2c_probe,
1507 .remove = __devexit_p(wm9081_i2c_remove), 1530 .remove = __devexit_p(wm9081_i2c_remove),
1531 .suspend = wm9081_i2c_suspend,
1532 .resume = wm9081_i2c_resume,
1508 .id_table = wm9081_i2c_id, 1533 .id_table = wm9081_i2c_id,
1509}; 1534};
1510 1535
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 411a710be660..6802dd5e4731 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -9,6 +9,9 @@ config SND_DAVINCI_SOC
9config SND_DAVINCI_SOC_I2S 9config SND_DAVINCI_SOC_I2S
10 tristate 10 tristate
11 11
12config SND_DAVINCI_SOC_MCASP
13 tristate
14
12config SND_DAVINCI_SOC_EVM 15config SND_DAVINCI_SOC_EVM
13 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" 16 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
14 depends on SND_DAVINCI_SOC 17 depends on SND_DAVINCI_SOC
@@ -19,6 +22,16 @@ config SND_DAVINCI_SOC_EVM
19 Say Y if you want to add support for SoC audio on TI 22 Say Y if you want to add support for SoC audio on TI
20 DaVinci DM6446 or DM355 EVM platforms. 23 DaVinci DM6446 or DM355 EVM platforms.
21 24
25config SND_DM6467_SOC_EVM
26 tristate "SoC Audio support for DaVinci DM6467 EVM"
27 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM
28 select SND_DAVINCI_SOC_MCASP
29 select SND_SOC_TLV320AIC3X
30 select SND_SOC_SPDIF
31
32 help
33 Say Y if you want to add support for SoC audio on TI
34
22config SND_DAVINCI_SOC_SFFSDR 35config SND_DAVINCI_SOC_SFFSDR
23 tristate "SoC Audio support for SFFSDR" 36 tristate "SoC Audio support for SFFSDR"
24 depends on SND_DAVINCI_SOC && MACH_SFFSDR 37 depends on SND_DAVINCI_SOC && MACH_SFFSDR
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index ca8bae1fc3f6..67be54f3a3a5 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -1,13 +1,16 @@
1# DAVINCI Platform Support 1# DAVINCI Platform Support
2snd-soc-davinci-objs := davinci-pcm.o 2snd-soc-davinci-objs := davinci-pcm.o
3snd-soc-davinci-i2s-objs := davinci-i2s.o 3snd-soc-davinci-i2s-objs := davinci-i2s.o
4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
4 5
5obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o 6obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
6obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o 7obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
8obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
7 9
8# DAVINCI Machine Support 10# DAVINCI Machine Support
9snd-soc-evm-objs := davinci-evm.o 11snd-soc-evm-objs := davinci-evm.o
10snd-soc-sffsdr-objs := davinci-sffsdr.o 12snd-soc-sffsdr-objs := davinci-sffsdr.o
11 13
12obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o 14obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
15obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
13obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o 16obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 58fd1cbedd88..f3bb6f60f205 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -27,9 +27,10 @@
27#include <mach/mux.h> 27#include <mach/mux.h>
28 28
29#include "../codecs/tlv320aic3x.h" 29#include "../codecs/tlv320aic3x.h"
30#include "../codecs/spdif_transciever.h"
30#include "davinci-pcm.h" 31#include "davinci-pcm.h"
31#include "davinci-i2s.h" 32#include "davinci-i2s.h"
32 33#include "davinci-mcasp.h"
33 34
34#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 35#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
35 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 36 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -43,7 +44,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
43 unsigned sysclk; 44 unsigned sysclk;
44 45
45 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 46 /* ASP1 on DM355 EVM is clocked by an external oscillator */
46 if (machine_is_davinci_dm355_evm()) 47 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm())
47 sysclk = 27000000; 48 sysclk = 27000000;
48 49
49 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 50 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -144,6 +145,24 @@ static struct snd_soc_dai_link evm_dai = {
144 .ops = &evm_ops, 145 .ops = &evm_ops,
145}; 146};
146 147
148static struct snd_soc_dai_link dm6467_evm_dai[] = {
149 {
150 .name = "TLV320AIC3X",
151 .stream_name = "AIC3X",
152 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI],
153 .codec_dai = &aic3x_dai,
154 .init = evm_aic3x_init,
155 .ops = &evm_ops,
156 },
157 {
158 .name = "McASP",
159 .stream_name = "spdif",
160 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI],
161 .codec_dai = &dit_stub_dai,
162 .ops = &evm_ops,
163 },
164};
165
147/* davinci-evm audio machine driver */ 166/* davinci-evm audio machine driver */
148static struct snd_soc_card snd_soc_card_evm = { 167static struct snd_soc_card snd_soc_card_evm = {
149 .name = "DaVinci EVM", 168 .name = "DaVinci EVM",
@@ -152,12 +171,26 @@ static struct snd_soc_card snd_soc_card_evm = {
152 .num_links = 1, 171 .num_links = 1,
153}; 172};
154 173
174/* davinci dm6467 evm audio machine driver */
175static struct snd_soc_card dm6467_snd_soc_card_evm = {
176 .name = "DaVinci DM6467 EVM",
177 .platform = &davinci_soc_platform,
178 .dai_link = dm6467_evm_dai,
179 .num_links = ARRAY_SIZE(dm6467_evm_dai),
180};
181
155/* evm audio private data */ 182/* evm audio private data */
156static struct aic3x_setup_data evm_aic3x_setup = { 183static struct aic3x_setup_data evm_aic3x_setup = {
157 .i2c_bus = 1, 184 .i2c_bus = 1,
158 .i2c_address = 0x1b, 185 .i2c_address = 0x1b,
159}; 186};
160 187
188/* dm6467 evm audio private data */
189static struct aic3x_setup_data dm6467_evm_aic3x_setup = {
190 .i2c_bus = 1,
191 .i2c_address = 0x18,
192};
193
161/* evm audio subsystem */ 194/* evm audio subsystem */
162static struct snd_soc_device evm_snd_devdata = { 195static struct snd_soc_device evm_snd_devdata = {
163 .card = &snd_soc_card_evm, 196 .card = &snd_soc_card_evm,
@@ -165,60 +198,30 @@ static struct snd_soc_device evm_snd_devdata = {
165 .codec_data = &evm_aic3x_setup, 198 .codec_data = &evm_aic3x_setup,
166}; 199};
167 200
168/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */ 201/* evm audio subsystem */
169static struct resource evm_snd_resources[] = { 202static struct snd_soc_device dm6467_evm_snd_devdata = {
170 { 203 .card = &dm6467_snd_soc_card_evm,
171 .start = DAVINCI_ASP0_BASE, 204 .codec_dev = &soc_codec_dev_aic3x,
172 .end = DAVINCI_ASP0_BASE + SZ_8K - 1, 205 .codec_data = &dm6467_evm_aic3x_setup,
173 .flags = IORESOURCE_MEM,
174 },
175};
176
177static struct evm_snd_platform_data evm_snd_data = {
178 .tx_dma_ch = DAVINCI_DMA_ASP0_TX,
179 .rx_dma_ch = DAVINCI_DMA_ASP0_RX,
180};
181
182/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
183static struct resource dm335evm_snd_resources[] = {
184 {
185 .start = DAVINCI_ASP1_BASE,
186 .end = DAVINCI_ASP1_BASE + SZ_8K - 1,
187 .flags = IORESOURCE_MEM,
188 },
189};
190
191static struct evm_snd_platform_data dm335evm_snd_data = {
192 .tx_dma_ch = DAVINCI_DMA_ASP1_TX,
193 .rx_dma_ch = DAVINCI_DMA_ASP1_RX,
194}; 206};
195 207
196static struct platform_device *evm_snd_device; 208static struct platform_device *evm_snd_device;
197 209
198static int __init evm_init(void) 210static int __init evm_init(void)
199{ 211{
200 struct resource *resources; 212 struct snd_soc_device *evm_snd_dev_data;
201 unsigned num_resources;
202 struct evm_snd_platform_data *data;
203 int index; 213 int index;
204 int ret; 214 int ret;
205 215
206 if (machine_is_davinci_evm()) { 216 if (machine_is_davinci_evm()) {
207 davinci_cfg_reg(DM644X_MCBSP); 217 evm_snd_dev_data = &evm_snd_devdata;
208
209 resources = evm_snd_resources;
210 num_resources = ARRAY_SIZE(evm_snd_resources);
211 data = &evm_snd_data;
212 index = 0; 218 index = 0;
213 } else if (machine_is_davinci_dm355_evm()) { 219 } else if (machine_is_davinci_dm355_evm()) {
214 /* we don't use ASP1 IRQs, or we'd need to mux them ... */ 220 evm_snd_dev_data = &evm_snd_devdata;
215 davinci_cfg_reg(DM355_EVT8_ASP1_TX);
216 davinci_cfg_reg(DM355_EVT9_ASP1_RX);
217
218 resources = dm335evm_snd_resources;
219 num_resources = ARRAY_SIZE(dm335evm_snd_resources);
220 data = &dm335evm_snd_data;
221 index = 1; 221 index = 1;
222 } else if (machine_is_davinci_dm6467_evm()) {
223 evm_snd_dev_data = &dm6467_evm_snd_devdata;
224 index = 0;
222 } else 225 } else
223 return -EINVAL; 226 return -EINVAL;
224 227
@@ -226,17 +229,8 @@ static int __init evm_init(void)
226 if (!evm_snd_device) 229 if (!evm_snd_device)
227 return -ENOMEM; 230 return -ENOMEM;
228 231
229 platform_set_drvdata(evm_snd_device, &evm_snd_devdata); 232 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
230 evm_snd_devdata.dev = &evm_snd_device->dev; 233 evm_snd_dev_data->dev = &evm_snd_device->dev;
231 platform_device_add_data(evm_snd_device, data, sizeof(*data));
232
233 ret = platform_device_add_resources(evm_snd_device, resources,
234 num_resources);
235 if (ret) {
236 platform_device_put(evm_snd_device);
237 return ret;
238 }
239
240 ret = platform_device_add(evm_snd_device); 234 ret = platform_device_add(evm_snd_device);
241 if (ret) 235 if (ret)
242 platform_device_put(evm_snd_device); 236 platform_device_put(evm_snd_device);
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index b1ea52fc83c7..2a56fb78f67a 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -22,6 +22,8 @@
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24 24
25#include <mach/asp.h>
26
25#include "davinci-pcm.h" 27#include "davinci-pcm.h"
26 28
27 29
@@ -63,6 +65,7 @@
63#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) 65#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5)
64#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) 66#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8)
65#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) 67#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)
68#define DAVINCI_MCBSP_RCR_RFIG (1 << 18)
66#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) 69#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)
67 70
68#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) 71#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)
@@ -85,14 +88,6 @@
85#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) 88#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
86#define DAVINCI_MCBSP_PCR_FSXM (1 << 11) 89#define DAVINCI_MCBSP_PCR_FSXM (1 << 11)
87 90
88#define MOD_REG_BIT(val, mask, set) do { \
89 if (set) { \
90 val |= mask; \
91 } else { \
92 val &= ~mask; \
93 } \
94} while (0)
95
96enum { 91enum {
97 DAVINCI_MCBSP_WORD_8 = 0, 92 DAVINCI_MCBSP_WORD_8 = 0,
98 DAVINCI_MCBSP_WORD_12, 93 DAVINCI_MCBSP_WORD_12,
@@ -112,6 +107,10 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
112 107
113struct davinci_mcbsp_dev { 108struct davinci_mcbsp_dev {
114 void __iomem *base; 109 void __iomem *base;
110#define MOD_DSP_A 0
111#define MOD_DSP_B 1
112 int mode;
113 u32 pcr;
115 struct clk *clk; 114 struct clk *clk;
116 struct davinci_pcm_dma_params *dma_params[2]; 115 struct davinci_pcm_dma_params *dma_params[2];
117}; 116};
@@ -127,96 +126,100 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
127 return __raw_readl(dev->base + reg); 126 return __raw_readl(dev->base + reg);
128} 127}
129 128
130static void davinci_mcbsp_start(struct snd_pcm_substream *substream) 129static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
130{
131 u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
132 /* The clock needs to toggle to complete reset.
133 * So, fake it by toggling the clk polarity.
134 */
135 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
136 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
137}
138
139static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
140 struct snd_pcm_substream *substream)
131{ 141{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
134 struct snd_soc_device *socdev = rtd->socdev; 143 struct snd_soc_device *socdev = rtd->socdev;
135 struct snd_soc_platform *platform = socdev->card->platform; 144 struct snd_soc_platform *platform = socdev->card->platform;
136 u32 w; 145 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
137 int ret; 146 u32 spcr;
138 147 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
139 /* Start the sample generator and enable transmitter/receiver */ 148 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
140 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 149 if (spcr & mask) {
141 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); 150 /* start off disabled */
142 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 151 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
152 spcr & ~mask);
153 toggle_clock(dev, playback);
154 }
155 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
156 DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
157 /* Start the sample generator */
158 spcr |= DAVINCI_MCBSP_SPCR_GRST;
159 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
160 }
143 161
144 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 162 if (playback) {
145 /* Stop the DMA to avoid data loss */ 163 /* Stop the DMA to avoid data loss */
146 /* while the transmitter is out of reset to handle XSYNCERR */ 164 /* while the transmitter is out of reset to handle XSYNCERR */
147 if (platform->pcm_ops->trigger) { 165 if (platform->pcm_ops->trigger) {
148 ret = platform->pcm_ops->trigger(substream, 166 int ret = platform->pcm_ops->trigger(substream,
149 SNDRV_PCM_TRIGGER_STOP); 167 SNDRV_PCM_TRIGGER_STOP);
150 if (ret < 0) 168 if (ret < 0)
151 printk(KERN_DEBUG "Playback DMA stop failed\n"); 169 printk(KERN_DEBUG "Playback DMA stop failed\n");
152 } 170 }
153 171
154 /* Enable the transmitter */ 172 /* Enable the transmitter */
155 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 173 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
156 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); 174 spcr |= DAVINCI_MCBSP_SPCR_XRST;
157 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 175 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
158 176
159 /* wait for any unexpected frame sync error to occur */ 177 /* wait for any unexpected frame sync error to occur */
160 udelay(100); 178 udelay(100);
161 179
162 /* Disable the transmitter to clear any outstanding XSYNCERR */ 180 /* Disable the transmitter to clear any outstanding XSYNCERR */
163 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 181 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
164 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); 182 spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
165 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 183 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
184 toggle_clock(dev, playback);
166 185
167 /* Restart the DMA */ 186 /* Restart the DMA */
168 if (platform->pcm_ops->trigger) { 187 if (platform->pcm_ops->trigger) {
169 ret = platform->pcm_ops->trigger(substream, 188 int ret = platform->pcm_ops->trigger(substream,
170 SNDRV_PCM_TRIGGER_START); 189 SNDRV_PCM_TRIGGER_START);
171 if (ret < 0) 190 if (ret < 0)
172 printk(KERN_DEBUG "Playback DMA start failed\n"); 191 printk(KERN_DEBUG "Playback DMA start failed\n");
173 } 192 }
174 /* Enable the transmitter */
175 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
176 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
177 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
178
179 } else {
180
181 /* Enable the reciever */
182 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
183 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
184 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
185 } 193 }
186 194
195 /* Enable transmitter or receiver */
196 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
197 spcr |= mask;
187 198
188 /* Start frame sync */ 199 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
189 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 200 /* Start frame sync */
190 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1); 201 spcr |= DAVINCI_MCBSP_SPCR_FRST;
191 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 202 }
203 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
192} 204}
193 205
194static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) 206static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
195{ 207{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 208 u32 spcr;
197 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
198 u32 w;
199 209
200 /* Reset transmitter/receiver and sample rate/frame sync generators */ 210 /* Reset transmitter/receiver and sample rate/frame sync generators */
201 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 211 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
202 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST | 212 spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
203 DAVINCI_MCBSP_SPCR_FRST, 0); 213 spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 214 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
205 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); 215 toggle_clock(dev, playback);
206 else
207 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
208 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
209} 216}
210 217
211static int davinci_i2s_startup(struct snd_pcm_substream *substream, 218static int davinci_i2s_startup(struct snd_pcm_substream *substream,
212 struct snd_soc_dai *dai) 219 struct snd_soc_dai *cpu_dai)
213{ 220{
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 221 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
215 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
216 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
217
218 cpu_dai->dma_data = dev->dma_params[substream->stream]; 222 cpu_dai->dma_data = dev->dma_params[substream->stream];
219
220 return 0; 223 return 0;
221} 224}
222 225
@@ -228,12 +231,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
228 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 231 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
229 unsigned int pcr; 232 unsigned int pcr;
230 unsigned int srgr; 233 unsigned int srgr;
231 unsigned int rcr;
232 unsigned int xcr;
233 srgr = DAVINCI_MCBSP_SRGR_FSGM | 234 srgr = DAVINCI_MCBSP_SRGR_FSGM |
234 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | 235 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
235 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); 236 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
236 237
238 /* set master/slave audio interface */
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 239 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBS_CFS: 240 case SND_SOC_DAIFMT_CBS_CFS:
239 /* cpu is master */ 241 /* cpu is master */
@@ -258,11 +260,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
258 return -EINVAL; 260 return -EINVAL;
259 } 261 }
260 262
261 rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1); 263 /* interface format */
262 xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
263 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 264 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
264 case SND_SOC_DAIFMT_DSP_B:
265 break;
266 case SND_SOC_DAIFMT_I2S: 265 case SND_SOC_DAIFMT_I2S:
267 /* Davinci doesn't support TRUE I2S, but some codecs will have 266 /* Davinci doesn't support TRUE I2S, but some codecs will have
268 * the left and right channels contiguous. This allows 267 * the left and right channels contiguous. This allows
@@ -282,8 +281,10 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
282 */ 281 */
283 fmt ^= SND_SOC_DAIFMT_NB_IF; 282 fmt ^= SND_SOC_DAIFMT_NB_IF;
284 case SND_SOC_DAIFMT_DSP_A: 283 case SND_SOC_DAIFMT_DSP_A:
285 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); 284 dev->mode = MOD_DSP_A;
286 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); 285 break;
286 case SND_SOC_DAIFMT_DSP_B:
287 dev->mode = MOD_DSP_B;
287 break; 288 break;
288 default: 289 default:
289 printk(KERN_ERR "%s:bad format\n", __func__); 290 printk(KERN_ERR "%s:bad format\n", __func__);
@@ -343,9 +344,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
343 return -EINVAL; 344 return -EINVAL;
344 } 345 }
345 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); 346 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
347 dev->pcr = pcr;
346 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); 348 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
347 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
348 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
349 return 0; 349 return 0;
350} 350}
351 351
@@ -353,31 +353,40 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
353 struct snd_pcm_hw_params *params, 353 struct snd_pcm_hw_params *params,
354 struct snd_soc_dai *dai) 354 struct snd_soc_dai *dai)
355{ 355{
356 struct snd_soc_pcm_runtime *rtd = substream->private_data; 356 struct davinci_pcm_dma_params *dma_params = dai->dma_data;
357 struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; 357 struct davinci_mcbsp_dev *dev = dai->private_data;
358 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
359 struct snd_interval *i = NULL; 358 struct snd_interval *i = NULL;
360 int mcbsp_word_length; 359 int mcbsp_word_length;
361 u32 w; 360 unsigned int rcr, xcr, srgr;
361 u32 spcr;
362 362
363 /* general line settings */ 363 /* general line settings */
364 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 364 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
365 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 365 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
366 w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; 366 spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
367 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 367 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
368 } else { 368 } else {
369 w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; 369 spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
370 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 370 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
371 } 371 }
372 372
373 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 373 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
374 w = DAVINCI_MCBSP_SRGR_FSGM; 374 srgr = DAVINCI_MCBSP_SRGR_FSGM;
375 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); 375 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
376 376
377 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); 377 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
378 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); 378 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
379 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); 379 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
380 380
381 rcr = DAVINCI_MCBSP_RCR_RFIG;
382 xcr = DAVINCI_MCBSP_XCR_XFIG;
383 if (dev->mode == MOD_DSP_B) {
384 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
385 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
386 } else {
387 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
388 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
389 }
381 /* Determine xfer data type */ 390 /* Determine xfer data type */
382 switch (params_format(params)) { 391 switch (params_format(params)) {
383 case SNDRV_PCM_FORMAT_S8: 392 case SNDRV_PCM_FORMAT_S8:
@@ -397,18 +406,30 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
397 return -EINVAL; 406 return -EINVAL;
398 } 407 }
399 408
400 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 409 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
401 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); 410 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
402 MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
403 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
404 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
405 411
406 } else { 412 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
407 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); 413 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
408 MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | 414 xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
409 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); 415 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
410 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
411 416
417 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
418 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
419 else
420 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
421 return 0;
422}
423
424static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
425 struct snd_soc_dai *dai)
426{
427 struct davinci_mcbsp_dev *dev = dai->private_data;
428 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
429 davinci_mcbsp_stop(dev, playback);
430 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
431 /* codec is master */
432 davinci_mcbsp_start(dev, substream);
412 } 433 }
413 return 0; 434 return 0;
414} 435}
@@ -416,35 +437,72 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
416static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 437static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
417 struct snd_soc_dai *dai) 438 struct snd_soc_dai *dai)
418{ 439{
440 struct davinci_mcbsp_dev *dev = dai->private_data;
419 int ret = 0; 441 int ret = 0;
442 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
443 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
444 return 0; /* return if codec is master */
420 445
421 switch (cmd) { 446 switch (cmd) {
422 case SNDRV_PCM_TRIGGER_START: 447 case SNDRV_PCM_TRIGGER_START:
423 case SNDRV_PCM_TRIGGER_RESUME: 448 case SNDRV_PCM_TRIGGER_RESUME:
424 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 449 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
425 davinci_mcbsp_start(substream); 450 davinci_mcbsp_start(dev, substream);
426 break; 451 break;
427 case SNDRV_PCM_TRIGGER_STOP: 452 case SNDRV_PCM_TRIGGER_STOP:
428 case SNDRV_PCM_TRIGGER_SUSPEND: 453 case SNDRV_PCM_TRIGGER_SUSPEND:
429 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 454 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
430 davinci_mcbsp_stop(substream); 455 davinci_mcbsp_stop(dev, playback);
431 break; 456 break;
432 default: 457 default:
433 ret = -EINVAL; 458 ret = -EINVAL;
434 } 459 }
435
436 return ret; 460 return ret;
437} 461}
438 462
439static int davinci_i2s_probe(struct platform_device *pdev, 463static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
440 struct snd_soc_dai *dai) 464 struct snd_soc_dai *dai)
465{
466 struct davinci_mcbsp_dev *dev = dai->private_data;
467 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
468 davinci_mcbsp_stop(dev, playback);
469}
470
471#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
472
473static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
474 .startup = davinci_i2s_startup,
475 .shutdown = davinci_i2s_shutdown,
476 .prepare = davinci_i2s_prepare,
477 .trigger = davinci_i2s_trigger,
478 .hw_params = davinci_i2s_hw_params,
479 .set_fmt = davinci_i2s_set_dai_fmt,
480
481};
482
483struct snd_soc_dai davinci_i2s_dai = {
484 .name = "davinci-i2s",
485 .id = 0,
486 .playback = {
487 .channels_min = 2,
488 .channels_max = 2,
489 .rates = DAVINCI_I2S_RATES,
490 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
491 .capture = {
492 .channels_min = 2,
493 .channels_max = 2,
494 .rates = DAVINCI_I2S_RATES,
495 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
496 .ops = &davinci_i2s_dai_ops,
497
498};
499EXPORT_SYMBOL_GPL(davinci_i2s_dai);
500
501static int davinci_i2s_probe(struct platform_device *pdev)
441{ 502{
442 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 503 struct snd_platform_data *pdata = pdev->dev.platform_data;
443 struct snd_soc_card *card = socdev->card;
444 struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
445 struct davinci_mcbsp_dev *dev; 504 struct davinci_mcbsp_dev *dev;
446 struct resource *mem, *ioarea; 505 struct resource *mem, *ioarea, *res;
447 struct evm_snd_platform_data *pdata;
448 int ret; 506 int ret;
449 507
450 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 508 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -466,8 +524,6 @@ static int davinci_i2s_probe(struct platform_device *pdev,
466 goto err_release_region; 524 goto err_release_region;
467 } 525 }
468 526
469 cpu_dai->private_data = dev;
470
471 dev->clk = clk_get(&pdev->dev, NULL); 527 dev->clk = clk_get(&pdev->dev, NULL);
472 if (IS_ERR(dev->clk)) { 528 if (IS_ERR(dev->clk)) {
473 ret = -ENODEV; 529 ret = -ENODEV;
@@ -476,18 +532,37 @@ static int davinci_i2s_probe(struct platform_device *pdev,
476 clk_enable(dev->clk); 532 clk_enable(dev->clk);
477 533
478 dev->base = (void __iomem *)IO_ADDRESS(mem->start); 534 dev->base = (void __iomem *)IO_ADDRESS(mem->start);
479 pdata = pdev->dev.platform_data;
480 535
481 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out; 536 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
482 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
483 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr = 537 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
484 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); 538 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
485 539
486 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in; 540 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
487 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
488 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr = 541 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
489 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); 542 (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
490 543
544 /* first TX, then RX */
545 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
546 if (!res) {
547 dev_err(&pdev->dev, "no DMA resource\n");
548 ret = -ENXIO;
549 goto err_free_mem;
550 }
551 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start;
552
553 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
554 if (!res) {
555 dev_err(&pdev->dev, "no DMA resource\n");
556 ret = -ENXIO;
557 goto err_free_mem;
558 }
559 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start;
560
561 davinci_i2s_dai.private_data = dev;
562 ret = snd_soc_register_dai(&davinci_i2s_dai);
563 if (ret != 0)
564 goto err_free_mem;
565
491 return 0; 566 return 0;
492 567
493err_free_mem: 568err_free_mem:
@@ -498,62 +573,40 @@ err_release_region:
498 return ret; 573 return ret;
499} 574}
500 575
501static void davinci_i2s_remove(struct platform_device *pdev, 576static int davinci_i2s_remove(struct platform_device *pdev)
502 struct snd_soc_dai *dai)
503{ 577{
504 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 578 struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
505 struct snd_soc_card *card = socdev->card;
506 struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
507 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
508 struct resource *mem; 579 struct resource *mem;
509 580
581 snd_soc_unregister_dai(&davinci_i2s_dai);
510 clk_disable(dev->clk); 582 clk_disable(dev->clk);
511 clk_put(dev->clk); 583 clk_put(dev->clk);
512 dev->clk = NULL; 584 dev->clk = NULL;
513
514 kfree(dev); 585 kfree(dev);
515
516 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 586 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
517 release_mem_region(mem->start, (mem->end - mem->start) + 1); 587 release_mem_region(mem->start, (mem->end - mem->start) + 1);
518}
519 588
520#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 589 return 0;
521 590}
522static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
523 .startup = davinci_i2s_startup,
524 .trigger = davinci_i2s_trigger,
525 .hw_params = davinci_i2s_hw_params,
526 .set_fmt = davinci_i2s_set_dai_fmt,
527};
528 591
529struct snd_soc_dai davinci_i2s_dai = { 592static struct platform_driver davinci_mcbsp_driver = {
530 .name = "davinci-i2s", 593 .probe = davinci_i2s_probe,
531 .id = 0, 594 .remove = davinci_i2s_remove,
532 .probe = davinci_i2s_probe, 595 .driver = {
533 .remove = davinci_i2s_remove, 596 .name = "davinci-asp",
534 .playback = { 597 .owner = THIS_MODULE,
535 .channels_min = 2, 598 },
536 .channels_max = 2,
537 .rates = DAVINCI_I2S_RATES,
538 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
539 .capture = {
540 .channels_min = 2,
541 .channels_max = 2,
542 .rates = DAVINCI_I2S_RATES,
543 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
544 .ops = &davinci_i2s_dai_ops,
545}; 599};
546EXPORT_SYMBOL_GPL(davinci_i2s_dai);
547 600
548static int __init davinci_i2s_init(void) 601static int __init davinci_i2s_init(void)
549{ 602{
550 return snd_soc_register_dai(&davinci_i2s_dai); 603 return platform_driver_register(&davinci_mcbsp_driver);
551} 604}
552module_init(davinci_i2s_init); 605module_init(davinci_i2s_init);
553 606
554static void __exit davinci_i2s_exit(void) 607static void __exit davinci_i2s_exit(void)
555{ 608{
556 snd_soc_unregister_dai(&davinci_i2s_dai); 609 platform_driver_unregister(&davinci_mcbsp_driver);
557} 610}
558module_exit(davinci_i2s_exit); 611module_exit(davinci_i2s_exit);
559 612
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
new file mode 100644
index 000000000000..f0c034771062
--- /dev/null
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -0,0 +1,874 @@
1/*
2 * ALSA SoC McASP Audio Layer for TI DAVINCI processor
3 *
4 * Multi-channel Audio Serial Port Driver
5 *
6 * Author: Nirmal Pandey <n-pandey@ti.com>,
7 * Suresh Rajashekara <suresh.r@ti.com>
8 * Steve Chen <schen@.mvista.com>
9 *
10 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
11 * Copyright: (C) 2009 Texas Instruments, India
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 version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23#include <linux/clk.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30
31#include "davinci-pcm.h"
32#include "davinci-mcasp.h"
33
34/*
35 * McASP register definitions
36 */
37#define DAVINCI_MCASP_PID_REG 0x00
38#define DAVINCI_MCASP_PWREMUMGT_REG 0x04
39
40#define DAVINCI_MCASP_PFUNC_REG 0x10
41#define DAVINCI_MCASP_PDIR_REG 0x14
42#define DAVINCI_MCASP_PDOUT_REG 0x18
43#define DAVINCI_MCASP_PDSET_REG 0x1c
44
45#define DAVINCI_MCASP_PDCLR_REG 0x20
46
47#define DAVINCI_MCASP_TLGC_REG 0x30
48#define DAVINCI_MCASP_TLMR_REG 0x34
49
50#define DAVINCI_MCASP_GBLCTL_REG 0x44
51#define DAVINCI_MCASP_AMUTE_REG 0x48
52#define DAVINCI_MCASP_LBCTL_REG 0x4c
53
54#define DAVINCI_MCASP_TXDITCTL_REG 0x50
55
56#define DAVINCI_MCASP_GBLCTLR_REG 0x60
57#define DAVINCI_MCASP_RXMASK_REG 0x64
58#define DAVINCI_MCASP_RXFMT_REG 0x68
59#define DAVINCI_MCASP_RXFMCTL_REG 0x6c
60
61#define DAVINCI_MCASP_ACLKRCTL_REG 0x70
62#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74
63#define DAVINCI_MCASP_RXTDM_REG 0x78
64#define DAVINCI_MCASP_EVTCTLR_REG 0x7c
65
66#define DAVINCI_MCASP_RXSTAT_REG 0x80
67#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84
68#define DAVINCI_MCASP_RXCLKCHK_REG 0x88
69#define DAVINCI_MCASP_REVTCTL_REG 0x8c
70
71#define DAVINCI_MCASP_GBLCTLX_REG 0xa0
72#define DAVINCI_MCASP_TXMASK_REG 0xa4
73#define DAVINCI_MCASP_TXFMT_REG 0xa8
74#define DAVINCI_MCASP_TXFMCTL_REG 0xac
75
76#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0
77#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4
78#define DAVINCI_MCASP_TXTDM_REG 0xb8
79#define DAVINCI_MCASP_EVTCTLX_REG 0xbc
80
81#define DAVINCI_MCASP_TXSTAT_REG 0xc0
82#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4
83#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8
84#define DAVINCI_MCASP_XEVTCTL_REG 0xcc
85
86/* Left(even TDM Slot) Channel Status Register File */
87#define DAVINCI_MCASP_DITCSRA_REG 0x100
88/* Right(odd TDM slot) Channel Status Register File */
89#define DAVINCI_MCASP_DITCSRB_REG 0x118
90/* Left(even TDM slot) User Data Register File */
91#define DAVINCI_MCASP_DITUDRA_REG 0x130
92/* Right(odd TDM Slot) User Data Register File */
93#define DAVINCI_MCASP_DITUDRB_REG 0x148
94
95/* Serializer n Control Register */
96#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
97#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
98 (n << 2))
99
100/* Transmit Buffer for Serializer n */
101#define DAVINCI_MCASP_TXBUF_REG 0x200
102/* Receive Buffer for Serializer n */
103#define DAVINCI_MCASP_RXBUF_REG 0x280
104
105
106/*
107 * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
108 * Register Bits
109 */
110#define MCASP_FREE BIT(0)
111#define MCASP_SOFT BIT(1)
112
113/*
114 * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
115 */
116#define AXR(n) (1<<n)
117#define PFUNC_AMUTE BIT(25)
118#define ACLKX BIT(26)
119#define AHCLKX BIT(27)
120#define AFSX BIT(28)
121#define ACLKR BIT(29)
122#define AHCLKR BIT(30)
123#define AFSR BIT(31)
124
125/*
126 * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
127 */
128#define AXR(n) (1<<n)
129#define PDIR_AMUTE BIT(25)
130#define ACLKX BIT(26)
131#define AHCLKX BIT(27)
132#define AFSX BIT(28)
133#define ACLKR BIT(29)
134#define AHCLKR BIT(30)
135#define AFSR BIT(31)
136
137/*
138 * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
139 */
140#define DITEN BIT(0) /* Transmit DIT mode enable/disable */
141#define VA BIT(2)
142#define VB BIT(3)
143
144/*
145 * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
146 */
147#define TXROT(val) (val)
148#define TXSEL BIT(3)
149#define TXSSZ(val) (val<<4)
150#define TXPBIT(val) (val<<8)
151#define TXPAD(val) (val<<13)
152#define TXORD BIT(15)
153#define FSXDLY(val) (val<<16)
154
155/*
156 * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
157 */
158#define RXROT(val) (val)
159#define RXSEL BIT(3)
160#define RXSSZ(val) (val<<4)
161#define RXPBIT(val) (val<<8)
162#define RXPAD(val) (val<<13)
163#define RXORD BIT(15)
164#define FSRDLY(val) (val<<16)
165
166/*
167 * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits
168 */
169#define FSXPOL BIT(0)
170#define AFSXE BIT(1)
171#define FSXDUR BIT(4)
172#define FSXMOD(val) (val<<7)
173
174/*
175 * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
176 */
177#define FSRPOL BIT(0)
178#define AFSRE BIT(1)
179#define FSRDUR BIT(4)
180#define FSRMOD(val) (val<<7)
181
182/*
183 * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
184 */
185#define ACLKXDIV(val) (val)
186#define ACLKXE BIT(5)
187#define TX_ASYNC BIT(6)
188#define ACLKXPOL BIT(7)
189
190/*
191 * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
192 */
193#define ACLKRDIV(val) (val)
194#define ACLKRE BIT(5)
195#define RX_ASYNC BIT(6)
196#define ACLKRPOL BIT(7)
197
198/*
199 * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
200 * Register Bits
201 */
202#define AHCLKXDIV(val) (val)
203#define AHCLKXPOL BIT(14)
204#define AHCLKXE BIT(15)
205
206/*
207 * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
208 * Register Bits
209 */
210#define AHCLKRDIV(val) (val)
211#define AHCLKRPOL BIT(14)
212#define AHCLKRE BIT(15)
213
214/*
215 * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits
216 */
217#define MODE(val) (val)
218#define DISMOD (val)(val<<2)
219#define TXSTATE BIT(4)
220#define RXSTATE BIT(5)
221
222/*
223 * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
224 */
225#define LBEN BIT(0)
226#define LBORD BIT(1)
227#define LBGENMODE(val) (val<<2)
228
229/*
230 * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
231 */
232#define TXTDMS(n) (1<<n)
233
234/*
235 * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
236 */
237#define RXTDMS(n) (1<<n)
238
239/*
240 * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits
241 */
242#define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */
243#define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */
244#define RXSERCLR BIT(2) /* Receiver Serializer Clear */
245#define RXSMRST BIT(3) /* Receiver State Machine Reset */
246#define RXFSRST BIT(4) /* Frame Sync Generator Reset */
247#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */
248#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/
249#define TXSERCLR BIT(10) /* Transmit Serializer Clear */
250#define TXSMRST BIT(11) /* Transmitter State Machine Reset */
251#define TXFSRST BIT(12) /* Frame Sync Generator Reset */
252
253/*
254 * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits
255 */
256#define MUTENA(val) (val)
257#define MUTEINPOL BIT(2)
258#define MUTEINENA BIT(3)
259#define MUTEIN BIT(4)
260#define MUTER BIT(5)
261#define MUTEX BIT(6)
262#define MUTEFSR BIT(7)
263#define MUTEFSX BIT(8)
264#define MUTEBADCLKR BIT(9)
265#define MUTEBADCLKX BIT(10)
266#define MUTERXDMAERR BIT(11)
267#define MUTETXDMAERR BIT(12)
268
269/*
270 * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
271 */
272#define RXDATADMADIS BIT(0)
273
274/*
275 * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
276 */
277#define TXDATADMADIS BIT(0)
278
279#define DAVINCI_MCASP_NUM_SERIALIZER 16
280
281static inline void mcasp_set_bits(void __iomem *reg, u32 val)
282{
283 __raw_writel(__raw_readl(reg) | val, reg);
284}
285
286static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
287{
288 __raw_writel((__raw_readl(reg) & ~(val)), reg);
289}
290
291static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
292{
293 __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
294}
295
296static inline void mcasp_set_reg(void __iomem *reg, u32 val)
297{
298 __raw_writel(val, reg);
299}
300
301static inline u32 mcasp_get_reg(void __iomem *reg)
302{
303 return (unsigned int)__raw_readl(reg);
304}
305
306static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
307{
308 int i = 0;
309
310 mcasp_set_bits(regs, val);
311
312 /* programming GBLCTL needs to read back from GBLCTL and verfiy */
313 /* loop count is to avoid the lock-up */
314 for (i = 0; i < 1000; i++) {
315 if ((mcasp_get_reg(regs) & val) == val)
316 break;
317 }
318
319 if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
320 printk(KERN_ERR "GBLCTL write error\n");
321}
322
323static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
324 struct snd_soc_dai *cpu_dai)
325{
326 struct davinci_audio_dev *dev = cpu_dai->private_data;
327 cpu_dai->dma_data = dev->dma_params[substream->stream];
328 return 0;
329}
330
331static void mcasp_start_rx(struct davinci_audio_dev *dev)
332{
333 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
334 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
335 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
336 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
337
338 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
339 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
340 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
341
342 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
343 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
344}
345
346static void mcasp_start_tx(struct davinci_audio_dev *dev)
347{
348 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
349 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
350 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
351 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
352
353 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
354 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
355 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
356 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
357}
358
359static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
360{
361 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
362 mcasp_start_tx(dev);
363 else
364 mcasp_start_rx(dev);
365}
366
367static void mcasp_stop_rx(struct davinci_audio_dev *dev)
368{
369 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
370 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
371}
372
373static void mcasp_stop_tx(struct davinci_audio_dev *dev)
374{
375 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
376 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
377}
378
379static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
380{
381 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
382 mcasp_stop_tx(dev);
383 else
384 mcasp_stop_rx(dev);
385}
386
387static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
388 unsigned int fmt)
389{
390 struct davinci_audio_dev *dev = cpu_dai->private_data;
391 void __iomem *base = dev->base;
392
393 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
394 case SND_SOC_DAIFMT_CBS_CFS:
395 /* codec is clock and frame slave */
396 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
397 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
398
399 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
400 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
401
402 mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
403 break;
404
405 case SND_SOC_DAIFMT_CBM_CFM:
406 /* codec is clock and frame master */
407 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
408 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
409
410 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
411 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
412
413 mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
414 break;
415
416 default:
417 return -EINVAL;
418 }
419
420 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
421 case SND_SOC_DAIFMT_IB_NF:
422 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
423 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
424
425 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
426 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
427 break;
428
429 case SND_SOC_DAIFMT_NB_IF:
430 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
431 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
432
433 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
434 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
435 break;
436
437 case SND_SOC_DAIFMT_IB_IF:
438 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
439 mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
440
441 mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
442 mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
443 break;
444
445 case SND_SOC_DAIFMT_NB_NF:
446 mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
447 mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
448
449 mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
450 mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
451 break;
452
453 default:
454 return -EINVAL;
455 }
456
457 return 0;
458}
459
460static int davinci_config_channel_size(struct davinci_audio_dev *dev,
461 int channel_size)
462{
463 u32 fmt = 0;
464
465 switch (channel_size) {
466 case DAVINCI_AUDIO_WORD_8:
467 fmt = 0x03;
468 break;
469
470 case DAVINCI_AUDIO_WORD_12:
471 fmt = 0x05;
472 break;
473
474 case DAVINCI_AUDIO_WORD_16:
475 fmt = 0x07;
476 break;
477
478 case DAVINCI_AUDIO_WORD_20:
479 fmt = 0x09;
480 break;
481
482 case DAVINCI_AUDIO_WORD_24:
483 fmt = 0x0B;
484 break;
485
486 case DAVINCI_AUDIO_WORD_28:
487 fmt = 0x0D;
488 break;
489
490 case DAVINCI_AUDIO_WORD_32:
491 fmt = 0x0F;
492 break;
493
494 default:
495 return -EINVAL;
496 }
497
498 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
499 RXSSZ(fmt), RXSSZ(0x0F));
500 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
501 TXSSZ(fmt), TXSSZ(0x0F));
502 return 0;
503}
504
505static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
506{
507 int i;
508
509 /* Default configuration */
510 mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
511
512 /* All PINS as McASP */
513 mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
514
515 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
516 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
517 mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
518 TXDATADMADIS);
519 } else {
520 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
521 mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
522 RXDATADMADIS);
523 }
524
525 for (i = 0; i < dev->num_serializer; i++) {
526 mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
527 dev->serial_dir[i]);
528 if (dev->serial_dir[i] == TX_MODE)
529 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
530 AXR(i));
531 else if (dev->serial_dir[i] == RX_MODE)
532 mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
533 AXR(i));
534 }
535}
536
537static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
538{
539 int i, active_slots;
540 u32 mask = 0;
541
542 active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
543 for (i = 0; i < active_slots; i++)
544 mask |= (1 << i);
545
546 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
547 /* bit stream is MSB first with no delay */
548 /* DSP_B mode */
549 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
550 AHCLKXE);
551 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
552 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
553
554 if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
555 mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
556 FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
557 else
558 printk(KERN_ERR "playback tdm slot %d not supported\n",
559 dev->tdm_slots);
560
561 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0xFFFFFFFF);
562 mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
563 } else {
564 /* bit stream is MSB first with no delay */
565 /* DSP_B mode */
566 mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
567 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
568 AHCLKRE);
569 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
570
571 if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
572 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
573 FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
574 else
575 printk(KERN_ERR "capture tdm slot %d not supported\n",
576 dev->tdm_slots);
577
578 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 0xFFFFFFFF);
579 mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
580 }
581}
582
583/* S/PDIF */
584static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
585{
586 /* Set the PDIR for Serialiser as output */
587 mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
588
589 /* TXMASK for 24 bits */
590 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
591
592 /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
593 and LSB first */
594 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
595 TXROT(6) | TXSSZ(15));
596
597 /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
598 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
599 AFSXE | FSXMOD(0x180));
600
601 /* Set the TX tdm : for all the slots */
602 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
603
604 /* Set the TX clock controls : div = 1 and internal */
605 mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
606 ACLKXE | TX_ASYNC);
607
608 mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
609
610 /* Only 44100 and 48000 are valid, both have the same setting */
611 mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
612
613 /* Enable the DIT */
614 mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
615}
616
617static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
618 struct snd_pcm_hw_params *params,
619 struct snd_soc_dai *cpu_dai)
620{
621 struct davinci_audio_dev *dev = cpu_dai->private_data;
622 struct davinci_pcm_dma_params *dma_params =
623 dev->dma_params[substream->stream];
624 int word_length;
625
626 davinci_hw_common_param(dev, substream->stream);
627
628 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
629 davinci_hw_dit_param(dev);
630 else
631 davinci_hw_param(dev, substream->stream);
632
633 switch (params_format(params)) {
634 case SNDRV_PCM_FORMAT_S8:
635 dma_params->data_type = 1;
636 word_length = DAVINCI_AUDIO_WORD_8;
637 break;
638
639 case SNDRV_PCM_FORMAT_S16_LE:
640 dma_params->data_type = 2;
641 word_length = DAVINCI_AUDIO_WORD_16;
642 break;
643
644 case SNDRV_PCM_FORMAT_S32_LE:
645 dma_params->data_type = 4;
646 word_length = DAVINCI_AUDIO_WORD_32;
647 break;
648
649 default:
650 printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
651 return -EINVAL;
652 }
653 davinci_config_channel_size(dev, word_length);
654
655 return 0;
656}
657
658static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
659 int cmd, struct snd_soc_dai *cpu_dai)
660{
661 struct snd_soc_pcm_runtime *rtd = substream->private_data;
662 struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data;
663 int ret = 0;
664
665 switch (cmd) {
666 case SNDRV_PCM_TRIGGER_START:
667 case SNDRV_PCM_TRIGGER_RESUME:
668 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
669 davinci_mcasp_start(dev, substream->stream);
670 break;
671
672 case SNDRV_PCM_TRIGGER_STOP:
673 case SNDRV_PCM_TRIGGER_SUSPEND:
674 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
675 davinci_mcasp_stop(dev, substream->stream);
676 break;
677
678 default:
679 ret = -EINVAL;
680 }
681
682 return ret;
683}
684
685static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
686 .startup = davinci_mcasp_startup,
687 .trigger = davinci_mcasp_trigger,
688 .hw_params = davinci_mcasp_hw_params,
689 .set_fmt = davinci_mcasp_set_dai_fmt,
690
691};
692
693struct snd_soc_dai davinci_mcasp_dai[] = {
694 {
695 .name = "davinci-i2s",
696 .id = 0,
697 .playback = {
698 .channels_min = 2,
699 .channels_max = 2,
700 .rates = DAVINCI_MCASP_RATES,
701 .formats = SNDRV_PCM_FMTBIT_S8 |
702 SNDRV_PCM_FMTBIT_S16_LE |
703 SNDRV_PCM_FMTBIT_S32_LE,
704 },
705 .capture = {
706 .channels_min = 2,
707 .channels_max = 2,
708 .rates = DAVINCI_MCASP_RATES,
709 .formats = SNDRV_PCM_FMTBIT_S8 |
710 SNDRV_PCM_FMTBIT_S16_LE |
711 SNDRV_PCM_FMTBIT_S32_LE,
712 },
713 .ops = &davinci_mcasp_dai_ops,
714
715 },
716 {
717 .name = "davinci-dit",
718 .id = 1,
719 .playback = {
720 .channels_min = 1,
721 .channels_max = 384,
722 .rates = DAVINCI_MCASP_RATES,
723 .formats = SNDRV_PCM_FMTBIT_S16_LE,
724 },
725 .ops = &davinci_mcasp_dai_ops,
726 },
727
728};
729EXPORT_SYMBOL_GPL(davinci_mcasp_dai);
730
731static int davinci_mcasp_probe(struct platform_device *pdev)
732{
733 struct davinci_pcm_dma_params *dma_data;
734 struct resource *mem, *ioarea, *res;
735 struct snd_platform_data *pdata;
736 struct davinci_audio_dev *dev;
737 int count = 0;
738 int ret = 0;
739
740 dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL);
741 if (!dev)
742 return -ENOMEM;
743
744 dma_data = kzalloc(sizeof(struct davinci_pcm_dma_params) * 2,
745 GFP_KERNEL);
746 if (!dma_data) {
747 ret = -ENOMEM;
748 goto err_release_dev;
749 }
750
751 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
752 if (!mem) {
753 dev_err(&pdev->dev, "no mem resource?\n");
754 ret = -ENODEV;
755 goto err_release_data;
756 }
757
758 ioarea = request_mem_region(mem->start,
759 (mem->end - mem->start) + 1, pdev->name);
760 if (!ioarea) {
761 dev_err(&pdev->dev, "Audio region already claimed\n");
762 ret = -EBUSY;
763 goto err_release_data;
764 }
765
766 pdata = pdev->dev.platform_data;
767 dev->clk = clk_get(&pdev->dev, NULL);
768 if (IS_ERR(dev->clk)) {
769 ret = -ENODEV;
770 goto err_release_region;
771 }
772
773 clk_enable(dev->clk);
774
775 dev->base = (void __iomem *)IO_ADDRESS(mem->start);
776 dev->op_mode = pdata->op_mode;
777 dev->tdm_slots = pdata->tdm_slots;
778 dev->num_serializer = pdata->num_serializer;
779 dev->serial_dir = pdata->serial_dir;
780 dev->codec_fmt = pdata->codec_fmt;
781
782 dma_data[count].name = "I2S PCM Stereo out";
783 dma_data[count].eventq_no = pdata->eventq_no;
784 dma_data[count].dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
785 io_v2p(dev->base));
786 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &dma_data[count];
787
788 /* first TX, then RX */
789 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
790 if (!res) {
791 dev_err(&pdev->dev, "no DMA resource\n");
792 goto err_release_region;
793 }
794
795 dma_data[count].channel = res->start;
796 count++;
797 dma_data[count].name = "I2S PCM Stereo in";
798 dma_data[count].eventq_no = pdata->eventq_no;
799 dma_data[count].dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
800 io_v2p(dev->base));
801 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &dma_data[count];
802
803 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
804 if (!res) {
805 dev_err(&pdev->dev, "no DMA resource\n");
806 goto err_release_region;
807 }
808
809 dma_data[count].channel = res->start;
810 davinci_mcasp_dai[pdev->id].private_data = dev;
811 davinci_mcasp_dai[pdev->id].dev = &pdev->dev;
812 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdev->id]);
813
814 if (ret != 0)
815 goto err_release_region;
816 return 0;
817
818err_release_region:
819 release_mem_region(mem->start, (mem->end - mem->start) + 1);
820err_release_data:
821 kfree(dma_data);
822err_release_dev:
823 kfree(dev);
824
825 return ret;
826}
827
828static int davinci_mcasp_remove(struct platform_device *pdev)
829{
830 struct davinci_pcm_dma_params *dma_data;
831 struct davinci_audio_dev *dev;
832 struct resource *mem;
833
834 snd_soc_unregister_dai(&davinci_mcasp_dai[pdev->id]);
835 dev = davinci_mcasp_dai[pdev->id].private_data;
836 clk_disable(dev->clk);
837 clk_put(dev->clk);
838 dev->clk = NULL;
839
840 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
841 release_mem_region(mem->start, (mem->end - mem->start) + 1);
842
843 dma_data = dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
844 kfree(dma_data);
845 kfree(dev);
846
847 return 0;
848}
849
850static struct platform_driver davinci_mcasp_driver = {
851 .probe = davinci_mcasp_probe,
852 .remove = davinci_mcasp_remove,
853 .driver = {
854 .name = "davinci-mcasp",
855 .owner = THIS_MODULE,
856 },
857};
858
859static int __init davinci_mcasp_init(void)
860{
861 return platform_driver_register(&davinci_mcasp_driver);
862}
863module_init(davinci_mcasp_init);
864
865static void __exit davinci_mcasp_exit(void)
866{
867 platform_driver_unregister(&davinci_mcasp_driver);
868}
869module_exit(davinci_mcasp_exit);
870
871MODULE_AUTHOR("Steve Chen");
872MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
873MODULE_LICENSE("GPL");
874
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
new file mode 100644
index 000000000000..36b71047a06c
--- /dev/null
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -0,0 +1,55 @@
1/*
2 * ALSA SoC McASP Audio Layer for TI DAVINCI processor
3 *
4 * MCASP related definitions
5 *
6 * Author: Nirmal Pandey <n-pandey@ti.com>,
7 * Suresh Rajashekara <suresh.r@ti.com>
8 * Steve Chen <schen@.mvista.com>
9 *
10 * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com>
11 * Copyright: (C) 2009 Texas Instruments, India
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 version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#ifndef DAVINCI_MCASP_H
19#define DAVINCI_MCASP_H
20
21#include <linux/io.h>
22#include <mach/asp.h>
23#include "davinci-pcm.h"
24
25extern struct snd_soc_dai davinci_mcasp_dai[];
26
27#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000
28#define DAVINCI_MCASP_I2S_DAI 0
29#define DAVINCI_MCASP_DIT_DAI 1
30
31enum {
32 DAVINCI_AUDIO_WORD_8 = 0,
33 DAVINCI_AUDIO_WORD_12,
34 DAVINCI_AUDIO_WORD_16,
35 DAVINCI_AUDIO_WORD_20,
36 DAVINCI_AUDIO_WORD_24,
37 DAVINCI_AUDIO_WORD_32,
38 DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */
39};
40
41struct davinci_audio_dev {
42 void __iomem *base;
43 int sample_rate;
44 struct clk *clk;
45 struct davinci_pcm_dma_params *dma_params[2];
46 unsigned int codec_fmt;
47
48 /* McASP specific data */
49 int tdm_slots;
50 u8 op_mode;
51 u8 num_serializer;
52 u8 *serial_dir;
53};
54
55#endif /* DAVINCI_MCASP_H */
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index a05996588489..ab43a539c11d 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -206,6 +206,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
206 /* Copy self-linked parameter RAM entry into master channel */ 206 /* Copy self-linked parameter RAM entry into master channel */
207 edma_read_slot(prtd->slave_lch, &temp); 207 edma_read_slot(prtd->slave_lch, &temp);
208 edma_write_slot(prtd->master_lch, &temp); 208 edma_write_slot(prtd->master_lch, &temp);
209 davinci_pcm_enqueue_dma(substream);
209 210
210 return 0; 211 return 0;
211} 212}
@@ -243,6 +244,11 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
243 int ret = 0; 244 int ret = 0;
244 245
245 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); 246 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
247 /* ensure that buffer size is a multiple of period size */
248 ret = snd_pcm_hw_constraint_integer(runtime,
249 SNDRV_PCM_HW_PARAM_PERIODS);
250 if (ret < 0)
251 return ret;
246 252
247 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); 253 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
248 if (prtd == NULL) 254 if (prtd == NULL)
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 62cb4eb07e34..eb4287faa3d5 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -12,17 +12,19 @@
12#ifndef _DAVINCI_PCM_H 12#ifndef _DAVINCI_PCM_H
13#define _DAVINCI_PCM_H 13#define _DAVINCI_PCM_H
14 14
15#include <mach/edma.h>
16#include <mach/asp.h>
17
18
15struct davinci_pcm_dma_params { 19struct davinci_pcm_dma_params {
16 char *name; /* stream identifier */ 20 char *name; /* stream identifier */
17 int channel; /* sync dma channel ID */ 21 int channel; /* sync dma channel ID */
18 dma_addr_t dma_addr; /* device physical address for DMA */ 22 dma_addr_t dma_addr; /* device physical address for DMA */
19 unsigned int data_type; /* xfer data type */ 23 enum dma_event_q eventq_no; /* event queue number */
24 unsigned char data_type; /* xfer data type */
25 unsigned char convert_mono_stereo;
20}; 26};
21 27
22struct evm_snd_platform_data {
23 int tx_dma_ch;
24 int rx_dma_ch;
25};
26 28
27extern struct snd_soc_platform davinci_soc_platform; 29extern struct snd_soc_platform davinci_soc_platform;
28 30
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index f0a2d4071998..9ff62e3a9b1d 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -69,6 +69,23 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
69 69
70static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s) 70static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
71{ 71{
72 if (s->appl_ptr > s->runtime->control->appl_ptr) {
73 /*
74 * In this case s->runtime->control->appl_ptr has wrapped around.
75 * Play the data to the end of the boundary, then wrap our own
76 * appl_ptr back around.
77 */
78 while (s->appl_ptr < s->runtime->boundary) {
79 if (bcom_queue_full(s->bcom_task))
80 return;
81
82 s->appl_ptr += s->period_size;
83
84 psc_dma_bcom_enqueue_next_buffer(s);
85 }
86 s->appl_ptr -= s->runtime->boundary;
87 }
88
72 while (s->appl_ptr < s->runtime->control->appl_ptr) { 89 while (s->appl_ptr < s->runtime->control->appl_ptr) {
73 90
74 if (bcom_queue_full(s->bcom_task)) 91 if (bcom_queue_full(s->bcom_task))
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 7eb549985d49..c4ae3e096bb9 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -12,6 +12,7 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/of_device.h> 13#include <linux/of_device.h>
14#include <linux/of_platform.h> 14#include <linux/of_platform.h>
15#include <linux/delay.h>
15 16
16#include <sound/pcm.h> 17#include <sound/pcm.h>
17#include <sound/pcm_params.h> 18#include <sound/pcm_params.h>
@@ -112,7 +113,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
112 out_8(&regs->op1, MPC52xx_PSC_OP_RES); 113 out_8(&regs->op1, MPC52xx_PSC_OP_RES);
113 udelay(10); 114 udelay(10);
114 out_8(&regs->op0, MPC52xx_PSC_OP_RES); 115 out_8(&regs->op0, MPC52xx_PSC_OP_RES);
115 udelay(50); 116 msleep(1);
116 psc_ac97_warm_reset(ac97); 117 psc_ac97_warm_reset(ac97);
117} 118}
118 119
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index b771238662b6..2dee9839be86 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -15,6 +15,14 @@ config SND_OMAP_SOC_N810
15 help 15 help
16 Say Y if you want to add support for SoC audio on Nokia N810. 16 Say Y if you want to add support for SoC audio on Nokia N810.
17 17
18config SND_OMAP_SOC_AMS_DELTA
19 tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
20 depends on SND_OMAP_SOC && MACH_AMS_DELTA
21 select SND_OMAP_SOC_MCBSP
22 select SND_SOC_CX20442
23 help
24 Say Y if you want to add support for SoC audio on Amstrad Delta.
25
18config SND_OMAP_SOC_OSK5912 26config SND_OMAP_SOC_OSK5912
19 tristate "SoC Audio support for omap osk5912" 27 tristate "SoC Audio support for omap osk5912"
20 depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C 28 depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
@@ -72,4 +80,11 @@ config SND_OMAP_SOC_OMAP3_BEAGLE
72 help 80 help
73 Say Y if you want to add support for SoC audio on the Beagleboard. 81 Say Y if you want to add support for SoC audio on the Beagleboard.
74 82
83config SND_OMAP_SOC_ZOOM2
84 tristate "SoC Audio support for Zoom2"
85 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
86 select SND_OMAP_SOC_MCBSP
87 select SND_SOC_TWL4030
88 help
89 Say Y if you want to add support for Soc audio on Zoom2 board.
75 90
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index a37f49862389..02d69471dcb5 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
7 7
8# OMAP Machine Support 8# OMAP Machine Support
9snd-soc-n810-objs := n810.o 9snd-soc-n810-objs := n810.o
10snd-soc-ams-delta-objs := ams-delta.o
10snd-soc-osk5912-objs := osk5912.o 11snd-soc-osk5912-objs := osk5912.o
11snd-soc-overo-objs := overo.o 12snd-soc-overo-objs := overo.o
12snd-soc-omap2evm-objs := omap2evm.o 13snd-soc-omap2evm-objs := omap2evm.o
@@ -14,8 +15,10 @@ snd-soc-omap3evm-objs := omap3evm.o
14snd-soc-sdp3430-objs := sdp3430.o 15snd-soc-sdp3430-objs := sdp3430.o
15snd-soc-omap3pandora-objs := omap3pandora.o 16snd-soc-omap3pandora-objs := omap3pandora.o
16snd-soc-omap3beagle-objs := omap3beagle.o 17snd-soc-omap3beagle-objs := omap3beagle.o
18snd-soc-zoom2-objs := zoom2.o
17 19
18obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 20obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
21obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
19obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 22obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
20obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 23obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
21obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 24obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
@@ -23,3 +26,4 @@ obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
23obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 26obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
24obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 27obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
25obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 28obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
29obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
new file mode 100644
index 000000000000..4f35b1f18cb9
--- /dev/null
+++ b/sound/soc/omap/ams-delta.c
@@ -0,0 +1,646 @@
1/*
2 * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone
3 *
4 * Copyright (C) 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
5 *
6 * Initially based on sound/soc/omap/osk5912.x
7 * Copyright (C) 2008 Mistral Solutions
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include <linux/gpio.h>
26#include <linux/spinlock.h>
27#include <linux/tty.h>
28
29#include <sound/soc-dapm.h>
30#include <sound/jack.h>
31
32#include <asm/mach-types.h>
33
34#include <mach/board-ams-delta.h>
35#include <mach/mcbsp.h>
36
37#include "omap-mcbsp.h"
38#include "omap-pcm.h"
39#include "../codecs/cx20442.h"
40
41
42/* Board specific DAPM widgets */
43 const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
44 /* Handset */
45 SND_SOC_DAPM_MIC("Mouthpiece", NULL),
46 SND_SOC_DAPM_HP("Earpiece", NULL),
47 /* Handsfree/Speakerphone */
48 SND_SOC_DAPM_MIC("Microphone", NULL),
49 SND_SOC_DAPM_SPK("Speaker", NULL),
50};
51
52/* How they are connected to codec pins */
53static const struct snd_soc_dapm_route ams_delta_audio_map[] = {
54 {"TELIN", NULL, "Mouthpiece"},
55 {"Earpiece", NULL, "TELOUT"},
56
57 {"MIC", NULL, "Microphone"},
58 {"Speaker", NULL, "SPKOUT"},
59};
60
61/*
62 * Controls, functional after the modem line discipline is activated.
63 */
64
65/* Virtual switch: audio input/output constellations */
66static const char *ams_delta_audio_mode[] =
67 {"Mixed", "Handset", "Handsfree", "Speakerphone"};
68
69/* Selection <-> pin translation */
70#define AMS_DELTA_MOUTHPIECE 0
71#define AMS_DELTA_EARPIECE 1
72#define AMS_DELTA_MICROPHONE 2
73#define AMS_DELTA_SPEAKER 3
74#define AMS_DELTA_AGC 4
75
76#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \
77 (1 << AMS_DELTA_MICROPHONE))
78#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \
79 (1 << AMS_DELTA_EARPIECE))
80#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \
81 (1 << AMS_DELTA_SPEAKER))
82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
83
84unsigned short ams_delta_audio_mode_pins[] = {
85 AMS_DELTA_MIXED,
86 AMS_DELTA_HANDSET,
87 AMS_DELTA_HANDSFREE,
88 AMS_DELTA_SPEAKERPHONE,
89};
90
91static unsigned short ams_delta_audio_agc;
92
93static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
94 struct snd_ctl_elem_value *ucontrol)
95{
96 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
97 struct soc_enum *control = (struct soc_enum *)kcontrol->private_value;
98 unsigned short pins;
99 int pin, changed = 0;
100
101 /* Refuse any mode changes if we are not able to control the codec. */
102 if (!codec->control_data)
103 return -EUNATCH;
104
105 if (ucontrol->value.enumerated.item[0] >= control->max)
106 return -EINVAL;
107
108 mutex_lock(&codec->mutex);
109
110 /* Translate selection to bitmap */
111 pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]];
112
113 /* Setup pins after corresponding bits if changed */
114 pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE));
115 if (pin != snd_soc_dapm_get_pin_status(codec, "Mouthpiece")) {
116 changed = 1;
117 if (pin)
118 snd_soc_dapm_enable_pin(codec, "Mouthpiece");
119 else
120 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
121 }
122 pin = !!(pins & (1 << AMS_DELTA_EARPIECE));
123 if (pin != snd_soc_dapm_get_pin_status(codec, "Earpiece")) {
124 changed = 1;
125 if (pin)
126 snd_soc_dapm_enable_pin(codec, "Earpiece");
127 else
128 snd_soc_dapm_disable_pin(codec, "Earpiece");
129 }
130 pin = !!(pins & (1 << AMS_DELTA_MICROPHONE));
131 if (pin != snd_soc_dapm_get_pin_status(codec, "Microphone")) {
132 changed = 1;
133 if (pin)
134 snd_soc_dapm_enable_pin(codec, "Microphone");
135 else
136 snd_soc_dapm_disable_pin(codec, "Microphone");
137 }
138 pin = !!(pins & (1 << AMS_DELTA_SPEAKER));
139 if (pin != snd_soc_dapm_get_pin_status(codec, "Speaker")) {
140 changed = 1;
141 if (pin)
142 snd_soc_dapm_enable_pin(codec, "Speaker");
143 else
144 snd_soc_dapm_disable_pin(codec, "Speaker");
145 }
146 pin = !!(pins & (1 << AMS_DELTA_AGC));
147 if (pin != ams_delta_audio_agc) {
148 ams_delta_audio_agc = pin;
149 changed = 1;
150 if (pin)
151 snd_soc_dapm_enable_pin(codec, "AGCIN");
152 else
153 snd_soc_dapm_disable_pin(codec, "AGCIN");
154 }
155 if (changed)
156 snd_soc_dapm_sync(codec);
157
158 mutex_unlock(&codec->mutex);
159
160 return changed;
161}
162
163static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
164 struct snd_ctl_elem_value *ucontrol)
165{
166 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
167 unsigned short pins, mode;
168
169 pins = ((snd_soc_dapm_get_pin_status(codec, "Mouthpiece") <<
170 AMS_DELTA_MOUTHPIECE) |
171 (snd_soc_dapm_get_pin_status(codec, "Earpiece") <<
172 AMS_DELTA_EARPIECE));
173 if (pins)
174 pins |= (snd_soc_dapm_get_pin_status(codec, "Microphone") <<
175 AMS_DELTA_MICROPHONE);
176 else
177 pins = ((snd_soc_dapm_get_pin_status(codec, "Microphone") <<
178 AMS_DELTA_MICROPHONE) |
179 (snd_soc_dapm_get_pin_status(codec, "Speaker") <<
180 AMS_DELTA_SPEAKER) |
181 (ams_delta_audio_agc << AMS_DELTA_AGC));
182
183 for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++)
184 if (pins == ams_delta_audio_mode_pins[mode])
185 break;
186
187 if (mode >= ARRAY_SIZE(ams_delta_audio_mode))
188 return -EINVAL;
189
190 ucontrol->value.enumerated.item[0] = mode;
191
192 return 0;
193}
194
195static const struct soc_enum ams_delta_audio_enum[] = {
196 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode),
197 ams_delta_audio_mode),
198};
199
200static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
201 SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0],
202 ams_delta_get_audio_mode, ams_delta_set_audio_mode),
203};
204
205/* Hook switch */
206static struct snd_soc_jack ams_delta_hook_switch;
207static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
208 {
209 .gpio = 4,
210 .name = "hook_switch",
211 .report = SND_JACK_HEADSET,
212 .invert = 1,
213 .debounce_time = 150,
214 }
215};
216
217/* After we are able to control the codec over the modem,
218 * the hook switch can be used for dynamic DAPM reconfiguration. */
219static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = {
220 /* Handset */
221 {
222 .pin = "Mouthpiece",
223 .mask = SND_JACK_MICROPHONE,
224 },
225 {
226 .pin = "Earpiece",
227 .mask = SND_JACK_HEADPHONE,
228 },
229 /* Handsfree */
230 {
231 .pin = "Microphone",
232 .mask = SND_JACK_MICROPHONE,
233 .invert = 1,
234 },
235 {
236 .pin = "Speaker",
237 .mask = SND_JACK_HEADPHONE,
238 .invert = 1,
239 },
240};
241
242
243/*
244 * Modem line discipline, required for making above controls functional.
245 * Activated from userspace with ldattach, possibly invoked from udev rule.
246 */
247
248/* To actually apply any modem controlled configuration changes to the codec,
249 * we must connect codec DAI pins to the modem for a moment. Be carefull not
250 * to interfere with our digital mute function that shares the same hardware. */
251static struct timer_list cx81801_timer;
252static bool cx81801_cmd_pending;
253static bool ams_delta_muted;
254static DEFINE_SPINLOCK(ams_delta_lock);
255
256static void cx81801_timeout(unsigned long data)
257{
258 int muted;
259
260 spin_lock(&ams_delta_lock);
261 cx81801_cmd_pending = 0;
262 muted = ams_delta_muted;
263 spin_unlock(&ams_delta_lock);
264
265 /* Reconnect the codec DAI back from the modem to the CPU DAI
266 * only if digital mute still off */
267 if (!muted)
268 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
269}
270
271/* Line discipline .open() */
272static int cx81801_open(struct tty_struct *tty)
273{
274 return v253_ops.open(tty);
275}
276
277/* Line discipline .close() */
278static void cx81801_close(struct tty_struct *tty)
279{
280 struct snd_soc_codec *codec = tty->disc_data;
281
282 del_timer_sync(&cx81801_timer);
283
284 v253_ops.close(tty);
285
286 /* Prevent the hook switch from further changing the DAPM pins */
287 INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
288
289 /* Revert back to default audio input/output constellation */
290 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
291 snd_soc_dapm_enable_pin(codec, "Earpiece");
292 snd_soc_dapm_enable_pin(codec, "Microphone");
293 snd_soc_dapm_disable_pin(codec, "Speaker");
294 snd_soc_dapm_disable_pin(codec, "AGCIN");
295 snd_soc_dapm_sync(codec);
296}
297
298/* Line discipline .hangup() */
299static int cx81801_hangup(struct tty_struct *tty)
300{
301 cx81801_close(tty);
302 return 0;
303}
304
305/* Line discipline .recieve_buf() */
306static void cx81801_receive(struct tty_struct *tty,
307 const unsigned char *cp, char *fp, int count)
308{
309 struct snd_soc_codec *codec = tty->disc_data;
310 const unsigned char *c;
311 int apply, ret;
312
313 if (!codec->control_data) {
314 /* First modem response, complete setup procedure */
315
316 /* Initialize timer used for config pulse generation */
317 setup_timer(&cx81801_timer, cx81801_timeout, 0);
318
319 v253_ops.receive_buf(tty, cp, fp, count);
320
321 /* Link hook switch to DAPM pins */
322 ret = snd_soc_jack_add_pins(&ams_delta_hook_switch,
323 ARRAY_SIZE(ams_delta_hook_switch_pins),
324 ams_delta_hook_switch_pins);
325 if (ret)
326 dev_warn(codec->socdev->card->dev,
327 "Failed to link hook switch to DAPM pins, "
328 "will continue with hook switch unlinked.\n");
329
330 return;
331 }
332
333 v253_ops.receive_buf(tty, cp, fp, count);
334
335 for (c = &cp[count - 1]; c >= cp; c--) {
336 if (*c != '\r')
337 continue;
338 /* Complete modem response received, apply config to codec */
339
340 spin_lock_bh(&ams_delta_lock);
341 mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
342 apply = !ams_delta_muted && !cx81801_cmd_pending;
343 cx81801_cmd_pending = 1;
344 spin_unlock_bh(&ams_delta_lock);
345
346 /* Apply config pulse by connecting the codec to the modem
347 * if not already done */
348 if (apply)
349 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
350 AMS_DELTA_LATCH2_MODEM_CODEC);
351 break;
352 }
353}
354
355/* Line discipline .write_wakeup() */
356static void cx81801_wakeup(struct tty_struct *tty)
357{
358 v253_ops.write_wakeup(tty);
359}
360
361static struct tty_ldisc_ops cx81801_ops = {
362 .magic = TTY_LDISC_MAGIC,
363 .name = "cx81801",
364 .owner = THIS_MODULE,
365 .open = cx81801_open,
366 .close = cx81801_close,
367 .hangup = cx81801_hangup,
368 .receive_buf = cx81801_receive,
369 .write_wakeup = cx81801_wakeup,
370};
371
372
373/*
374 * Even if not very usefull, the sound card can still work without any of the
375 * above functonality activated. You can still control its audio input/output
376 * constellation and speakerphone gain from userspace by issueing AT commands
377 * over the modem port.
378 */
379
380static int ams_delta_hw_params(struct snd_pcm_substream *substream,
381 struct snd_pcm_hw_params *params)
382{
383 struct snd_soc_pcm_runtime *rtd = substream->private_data;
384
385 /* Set cpu DAI configuration */
386 return snd_soc_dai_set_fmt(rtd->dai->cpu_dai,
387 SND_SOC_DAIFMT_DSP_A |
388 SND_SOC_DAIFMT_NB_NF |
389 SND_SOC_DAIFMT_CBM_CFM);
390}
391
392static struct snd_soc_ops ams_delta_ops = {
393 .hw_params = ams_delta_hw_params,
394};
395
396
397/* Board specific codec bias level control */
398static int ams_delta_set_bias_level(struct snd_soc_card *card,
399 enum snd_soc_bias_level level)
400{
401 struct snd_soc_codec *codec = card->codec;
402
403 switch (level) {
404 case SND_SOC_BIAS_ON:
405 case SND_SOC_BIAS_PREPARE:
406 case SND_SOC_BIAS_STANDBY:
407 if (codec->bias_level == SND_SOC_BIAS_OFF)
408 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
409 AMS_DELTA_LATCH2_MODEM_NRESET);
410 break;
411 case SND_SOC_BIAS_OFF:
412 if (codec->bias_level != SND_SOC_BIAS_OFF)
413 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
414 0);
415 }
416 codec->bias_level = level;
417
418 return 0;
419}
420
421/* Digital mute implemented using modem/CPU multiplexer.
422 * Shares hardware with codec config pulse generation */
423static bool ams_delta_muted = 1;
424
425static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
426{
427 int apply;
428
429 if (ams_delta_muted == mute)
430 return 0;
431
432 spin_lock_bh(&ams_delta_lock);
433 ams_delta_muted = mute;
434 apply = !cx81801_cmd_pending;
435 spin_unlock_bh(&ams_delta_lock);
436
437 if (apply)
438 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
439 mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
440 return 0;
441}
442
443/* Our codec DAI probably doesn't have its own .ops structure */
444static struct snd_soc_dai_ops ams_delta_dai_ops = {
445 .digital_mute = ams_delta_digital_mute,
446};
447
448/* Will be used if the codec ever has its own digital_mute function */
449static int ams_delta_startup(struct snd_pcm_substream *substream)
450{
451 return ams_delta_digital_mute(NULL, 0);
452}
453
454static void ams_delta_shutdown(struct snd_pcm_substream *substream)
455{
456 ams_delta_digital_mute(NULL, 1);
457}
458
459
460/*
461 * Card initialization
462 */
463
464static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
465{
466 struct snd_soc_dai *codec_dai = codec->dai;
467 struct snd_soc_card *card = codec->socdev->card;
468 int ret;
469 /* Codec is ready, now add/activate board specific controls */
470
471 /* Set up digital mute if not provided by the codec */
472 if (!codec_dai->ops) {
473 codec_dai->ops = &ams_delta_dai_ops;
474 } else if (!codec_dai->ops->digital_mute) {
475 codec_dai->ops->digital_mute = ams_delta_digital_mute;
476 } else {
477 ams_delta_ops.startup = ams_delta_startup;
478 ams_delta_ops.shutdown = ams_delta_shutdown;
479 }
480
481 /* Set codec bias level */
482 ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY);
483
484 /* Add hook switch - can be used to control the codec from userspace
485 * even if line discipline fails */
486 ret = snd_soc_jack_new(card, "hook_switch",
487 SND_JACK_HEADSET, &ams_delta_hook_switch);
488 if (ret)
489 dev_warn(card->dev,
490 "Failed to allocate resources for hook switch, "
491 "will continue without one.\n");
492 else {
493 ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
494 ARRAY_SIZE(ams_delta_hook_switch_gpios),
495 ams_delta_hook_switch_gpios);
496 if (ret)
497 dev_warn(card->dev,
498 "Failed to set up hook switch GPIO line, "
499 "will continue with hook switch inactive.\n");
500 }
501
502 /* Register optional line discipline for over the modem control */
503 ret = tty_register_ldisc(N_AMSDELTA, &cx81801_ops);
504 if (ret) {
505 dev_warn(card->dev,
506 "Failed to register line discipline, "
507 "will continue without any controls.\n");
508 return 0;
509 }
510
511 /* Add board specific DAPM widgets and routes */
512 ret = snd_soc_dapm_new_controls(codec, ams_delta_dapm_widgets,
513 ARRAY_SIZE(ams_delta_dapm_widgets));
514 if (ret) {
515 dev_warn(card->dev,
516 "Failed to register DAPM controls, "
517 "will continue without any.\n");
518 return 0;
519 }
520
521 ret = snd_soc_dapm_add_routes(codec, ams_delta_audio_map,
522 ARRAY_SIZE(ams_delta_audio_map));
523 if (ret) {
524 dev_warn(card->dev,
525 "Failed to set up DAPM routes, "
526 "will continue with codec default map.\n");
527 return 0;
528 }
529
530 /* Set up initial pin constellation */
531 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
532 snd_soc_dapm_enable_pin(codec, "Earpiece");
533 snd_soc_dapm_enable_pin(codec, "Microphone");
534 snd_soc_dapm_disable_pin(codec, "Speaker");
535 snd_soc_dapm_disable_pin(codec, "AGCIN");
536 snd_soc_dapm_disable_pin(codec, "AGCOUT");
537 snd_soc_dapm_sync(codec);
538
539 /* Add virtual switch */
540 ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
541 ARRAY_SIZE(ams_delta_audio_controls));
542 if (ret)
543 dev_warn(card->dev,
544 "Failed to register audio mode control, "
545 "will continue without it.\n");
546
547 return 0;
548}
549
550/* DAI glue - connects codec <--> CPU */
551static struct snd_soc_dai_link ams_delta_dai_link = {
552 .name = "CX20442",
553 .stream_name = "CX20442",
554 .cpu_dai = &omap_mcbsp_dai[0],
555 .codec_dai = &cx20442_dai,
556 .init = ams_delta_cx20442_init,
557 .ops = &ams_delta_ops,
558};
559
560/* Audio card driver */
561static struct snd_soc_card ams_delta_audio_card = {
562 .name = "AMS_DELTA",
563 .platform = &omap_soc_platform,
564 .dai_link = &ams_delta_dai_link,
565 .num_links = 1,
566 .set_bias_level = ams_delta_set_bias_level,
567};
568
569/* Audio subsystem */
570static struct snd_soc_device ams_delta_snd_soc_device = {
571 .card = &ams_delta_audio_card,
572 .codec_dev = &cx20442_codec_dev,
573};
574
575/* Module init/exit */
576static struct platform_device *ams_delta_audio_platform_device;
577static struct platform_device *cx20442_platform_device;
578
579static int __init ams_delta_module_init(void)
580{
581 int ret;
582
583 if (!(machine_is_ams_delta()))
584 return -ENODEV;
585
586 ams_delta_audio_platform_device =
587 platform_device_alloc("soc-audio", -1);
588 if (!ams_delta_audio_platform_device)
589 return -ENOMEM;
590
591 platform_set_drvdata(ams_delta_audio_platform_device,
592 &ams_delta_snd_soc_device);
593 ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev;
594 *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1;
595
596 ret = platform_device_add(ams_delta_audio_platform_device);
597 if (ret)
598 goto err;
599
600 /*
601 * Codec platform device could be registered from elsewhere (board?),
602 * but I do it here as it makes sense only if used with the card.
603 */
604 cx20442_platform_device = platform_device_register_simple("cx20442",
605 -1, NULL, 0);
606 return 0;
607err:
608 platform_device_put(ams_delta_audio_platform_device);
609 return ret;
610}
611module_init(ams_delta_module_init);
612
613static void __exit ams_delta_module_exit(void)
614{
615 struct snd_soc_codec *codec;
616 struct tty_struct *tty;
617
618 if (ams_delta_audio_card.codec) {
619 codec = ams_delta_audio_card.codec;
620
621 if (codec->control_data) {
622 tty = codec->control_data;
623
624 tty_hangup(tty);
625 }
626 }
627
628 if (tty_unregister_ldisc(N_AMSDELTA) != 0)
629 dev_warn(&ams_delta_audio_platform_device->dev,
630 "failed to unregister AMSDELTA line discipline\n");
631
632 snd_soc_jack_free_gpios(&ams_delta_hook_switch,
633 ARRAY_SIZE(ams_delta_hook_switch_gpios),
634 ams_delta_hook_switch_gpios);
635
636 /* Keep modem power on */
637 ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY);
638
639 platform_device_unregister(cx20442_platform_device);
640 platform_device_unregister(ams_delta_audio_platform_device);
641}
642module_exit(ams_delta_module_exit);
643
644MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
645MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
646MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 84a1950880eb..c3c931d4537a 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -330,7 +330,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
330 } 330 }
331} 331}
332 332
333int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 333static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
334 struct snd_pcm *pcm) 334 struct snd_pcm *pcm)
335{ 335{
336 int ret = 0; 336 int ret = 0;
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index b719e5db4f57..f7e5b7488c35 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -24,6 +24,7 @@
24 24
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/i2c/twl4030.h>
27#include <sound/core.h> 28#include <sound/core.h>
28#include <sound/pcm.h> 29#include <sound/pcm.h>
29#include <sound/soc.h> 30#include <sound/soc.h>
@@ -39,6 +40,9 @@
39#include "omap-pcm.h" 40#include "omap-pcm.h"
40#include "../codecs/twl4030.h" 41#include "../codecs/twl4030.h"
41 42
43#define TWL4030_INTBR_PMBR1 0x0D
44#define EXTMUTE(value) (value << 2)
45
42static struct snd_soc_card snd_soc_sdp3430; 46static struct snd_soc_card snd_soc_sdp3430;
43 47
44static int sdp3430_hw_params(struct snd_pcm_substream *substream, 48static int sdp3430_hw_params(struct snd_pcm_substream *substream,
@@ -96,7 +100,7 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
96 ret = snd_soc_dai_set_fmt(codec_dai, 100 ret = snd_soc_dai_set_fmt(codec_dai,
97 SND_SOC_DAIFMT_DSP_A | 101 SND_SOC_DAIFMT_DSP_A |
98 SND_SOC_DAIFMT_IB_NF | 102 SND_SOC_DAIFMT_IB_NF |
99 SND_SOC_DAIFMT_CBS_CFM); 103 SND_SOC_DAIFMT_CBM_CFM);
100 if (ret) { 104 if (ret) {
101 printk(KERN_ERR "can't set codec DAI configuration\n"); 105 printk(KERN_ERR "can't set codec DAI configuration\n");
102 return ret; 106 return ret;
@@ -280,6 +284,7 @@ static struct snd_soc_card snd_soc_sdp3430 = {
280static struct twl4030_setup_data twl4030_setup = { 284static struct twl4030_setup_data twl4030_setup = {
281 .ramp_delay_value = 3, 285 .ramp_delay_value = 3,
282 .sysclk = 26000, 286 .sysclk = 26000,
287 .hs_extmute = 1,
283}; 288};
284 289
285/* Audio subsystem */ 290/* Audio subsystem */
@@ -312,6 +317,10 @@ static int __init sdp3430_soc_init(void)
312 *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ 317 *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
313 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ 318 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
314 319
320 /* Set TWL4030 GPIO6 as EXTMUTE signal */
321 twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, EXTMUTE(0x02),
322 TWL4030_MODULE_INTBR);
323
315 ret = platform_device_add(sdp3430_snd_device); 324 ret = platform_device_add(sdp3430_snd_device);
316 if (ret) 325 if (ret)
317 goto err1; 326 goto err1;
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
new file mode 100644
index 000000000000..f90b45f56220
--- /dev/null
+++ b/sound/soc/omap/zoom2.c
@@ -0,0 +1,314 @@
1/*
2 * zoom2.c -- SoC audio for Zoom2
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <mach/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
39#define ZOOM2_HEADSET_EXTMUTE_GPIO 153
40
41static int zoom2_hw_params(struct snd_pcm_substream *substream,
42 struct snd_pcm_hw_params *params)
43{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
47 int ret;
48
49 /* Set codec DAI configuration */
50 ret = snd_soc_dai_set_fmt(codec_dai,
51 SND_SOC_DAIFMT_I2S |
52 SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBM_CFM);
54 if (ret < 0) {
55 printk(KERN_ERR "can't set codec DAI configuration\n");
56 return ret;
57 }
58
59 /* Set cpu DAI configuration */
60 ret = snd_soc_dai_set_fmt(cpu_dai,
61 SND_SOC_DAIFMT_I2S |
62 SND_SOC_DAIFMT_NB_NF |
63 SND_SOC_DAIFMT_CBM_CFM);
64 if (ret < 0) {
65 printk(KERN_ERR "can't set cpu DAI configuration\n");
66 return ret;
67 }
68
69 /* Set the codec system clock for DAC and ADC */
70 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
71 SND_SOC_CLOCK_IN);
72 if (ret < 0) {
73 printk(KERN_ERR "can't set codec system clock\n");
74 return ret;
75 }
76
77 return 0;
78}
79
80static struct snd_soc_ops zoom2_ops = {
81 .hw_params = zoom2_hw_params,
82};
83
84static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
85 struct snd_pcm_hw_params *params)
86{
87 struct snd_soc_pcm_runtime *rtd = substream->private_data;
88 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
89 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
90 int ret;
91
92 /* Set codec DAI configuration */
93 ret = snd_soc_dai_set_fmt(codec_dai,
94 SND_SOC_DAIFMT_DSP_A |
95 SND_SOC_DAIFMT_IB_NF |
96 SND_SOC_DAIFMT_CBM_CFM);
97 if (ret) {
98 printk(KERN_ERR "can't set codec DAI configuration\n");
99 return ret;
100 }
101
102 /* Set cpu DAI configuration */
103 ret = snd_soc_dai_set_fmt(cpu_dai,
104 SND_SOC_DAIFMT_DSP_A |
105 SND_SOC_DAIFMT_IB_NF |
106 SND_SOC_DAIFMT_CBM_CFM);
107 if (ret < 0) {
108 printk(KERN_ERR "can't set cpu DAI configuration\n");
109 return ret;
110 }
111
112 /* Set the codec system clock for DAC and ADC */
113 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
114 SND_SOC_CLOCK_IN);
115 if (ret < 0) {
116 printk(KERN_ERR "can't set codec system clock\n");
117 return ret;
118 }
119
120 return 0;
121}
122
123static struct snd_soc_ops zoom2_voice_ops = {
124 .hw_params = zoom2_hw_voice_params,
125};
126
127/* Zoom2 machine DAPM */
128static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
129 SND_SOC_DAPM_MIC("Ext Mic", NULL),
130 SND_SOC_DAPM_SPK("Ext Spk", NULL),
131 SND_SOC_DAPM_MIC("Headset Mic", NULL),
132 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
133 SND_SOC_DAPM_LINE("Aux In", NULL),
134};
135
136static const struct snd_soc_dapm_route audio_map[] = {
137 /* External Mics: MAINMIC, SUBMIC with bias*/
138 {"MAINMIC", NULL, "Mic Bias 1"},
139 {"SUBMIC", NULL, "Mic Bias 2"},
140 {"Mic Bias 1", NULL, "Ext Mic"},
141 {"Mic Bias 2", NULL, "Ext Mic"},
142
143 /* External Speakers: HFL, HFR */
144 {"Ext Spk", NULL, "HFL"},
145 {"Ext Spk", NULL, "HFR"},
146
147 /* Headset Stereophone: HSOL, HSOR */
148 {"Headset Stereophone", NULL, "HSOL"},
149 {"Headset Stereophone", NULL, "HSOR"},
150
151 /* Headset Mic: HSMIC with bias */
152 {"HSMIC", NULL, "Headset Mic Bias"},
153 {"Headset Mic Bias", NULL, "Headset Mic"},
154
155 /* Aux In: AUXL, AUXR */
156 {"Aux In", NULL, "AUXL"},
157 {"Aux In", NULL, "AUXR"},
158};
159
160static int zoom2_twl4030_init(struct snd_soc_codec *codec)
161{
162 int ret;
163
164 /* Add Zoom2 specific widgets */
165 ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets,
166 ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
167 if (ret)
168 return ret;
169
170 /* Set up Zoom2 specific audio path audio_map */
171 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
172
173 /* Zoom2 connected pins */
174 snd_soc_dapm_enable_pin(codec, "Ext Mic");
175 snd_soc_dapm_enable_pin(codec, "Ext Spk");
176 snd_soc_dapm_enable_pin(codec, "Headset Mic");
177 snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
178 snd_soc_dapm_enable_pin(codec, "Aux In");
179
180 /* TWL4030 not connected pins */
181 snd_soc_dapm_nc_pin(codec, "CARKITMIC");
182 snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
183 snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
184
185 snd_soc_dapm_nc_pin(codec, "OUTL");
186 snd_soc_dapm_nc_pin(codec, "OUTR");
187 snd_soc_dapm_nc_pin(codec, "EARPIECE");
188 snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
189 snd_soc_dapm_nc_pin(codec, "PREDRIVER");
190 snd_soc_dapm_nc_pin(codec, "CARKITL");
191 snd_soc_dapm_nc_pin(codec, "CARKITR");
192
193 ret = snd_soc_dapm_sync(codec);
194
195 return ret;
196}
197
198static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec)
199{
200 unsigned short reg;
201
202 /* Enable voice interface */
203 reg = codec->read(codec, TWL4030_REG_VOICE_IF);
204 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
205 codec->write(codec, TWL4030_REG_VOICE_IF, reg);
206
207 return 0;
208}
209
210/* Digital audio interface glue - connects codec <--> CPU */
211static struct snd_soc_dai_link zoom2_dai[] = {
212 {
213 .name = "TWL4030 I2S",
214 .stream_name = "TWL4030 Audio",
215 .cpu_dai = &omap_mcbsp_dai[0],
216 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
217 .init = zoom2_twl4030_init,
218 .ops = &zoom2_ops,
219 },
220 {
221 .name = "TWL4030 PCM",
222 .stream_name = "TWL4030 Voice",
223 .cpu_dai = &omap_mcbsp_dai[1],
224 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
225 .init = zoom2_twl4030_voice_init,
226 .ops = &zoom2_voice_ops,
227 },
228};
229
230/* Audio machine driver */
231static struct snd_soc_card snd_soc_zoom2 = {
232 .name = "Zoom2",
233 .platform = &omap_soc_platform,
234 .dai_link = zoom2_dai,
235 .num_links = ARRAY_SIZE(zoom2_dai),
236};
237
238/* EXTMUTE callback function */
239void zoom2_set_hs_extmute(int mute)
240{
241 gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
242}
243
244/* twl4030 setup */
245static struct twl4030_setup_data twl4030_setup = {
246 .ramp_delay_value = 3, /* 161 ms */
247 .sysclk = 26000,
248 .hs_extmute = 1,
249 .set_hs_extmute = zoom2_set_hs_extmute,
250};
251
252/* Audio subsystem */
253static struct snd_soc_device zoom2_snd_devdata = {
254 .card = &snd_soc_zoom2,
255 .codec_dev = &soc_codec_dev_twl4030,
256 .codec_data = &twl4030_setup,
257};
258
259static struct platform_device *zoom2_snd_device;
260
261static int __init zoom2_soc_init(void)
262{
263 int ret;
264
265 if (!machine_is_omap_zoom2()) {
266 pr_debug("Not Zoom2!\n");
267 return -ENODEV;
268 }
269 printk(KERN_INFO "Zoom2 SoC init\n");
270
271 zoom2_snd_device = platform_device_alloc("soc-audio", -1);
272 if (!zoom2_snd_device) {
273 printk(KERN_ERR "Platform device allocation failed\n");
274 return -ENOMEM;
275 }
276
277 platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata);
278 zoom2_snd_devdata.dev = &zoom2_snd_device->dev;
279 *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
280 *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
281
282 ret = platform_device_add(zoom2_snd_device);
283 if (ret)
284 goto err1;
285
286 BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
287 gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
288
289 BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0);
290 gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0);
291
292 return 0;
293
294err1:
295 printk(KERN_ERR "Unable to add platform device\n");
296 platform_device_put(zoom2_snd_device);
297
298 return ret;
299}
300module_init(zoom2_soc_init);
301
302static void __exit zoom2_soc_exit(void)
303{
304 gpio_free(ZOOM2_HEADSET_MUX_GPIO);
305 gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO);
306
307 platform_device_unregister(zoom2_snd_device);
308}
309module_exit(zoom2_soc_exit);
310
311MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
312MODULE_DESCRIPTION("ALSA SoC Zoom2");
313MODULE_LICENSE("GPL");
314
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 326955dea36c..8889cd371608 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -20,12 +20,14 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/gpio.h> 22#include <linux/gpio.h>
23#include <linux/i2c.h>
23 24
24#include <sound/core.h> 25#include <sound/core.h>
25#include <sound/pcm.h> 26#include <sound/pcm.h>
26#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
27#include <sound/soc.h> 28#include <sound/soc.h>
28#include <sound/soc-dapm.h> 29#include <sound/soc-dapm.h>
30#include <sound/uda1380.h>
29 31
30#include <mach/magician.h> 32#include <mach/magician.h>
31#include <asm/mach-types.h> 33#include <asm/mach-types.h>
@@ -447,34 +449,47 @@ static struct snd_soc_card snd_soc_card_magician = {
447 .platform = &pxa2xx_soc_platform, 449 .platform = &pxa2xx_soc_platform,
448}; 450};
449 451
450/* magician audio private data */
451static struct uda1380_setup_data magician_uda1380_setup = {
452 .i2c_address = 0x18,
453 .dac_clk = UDA1380_DAC_CLK_WSPLL,
454};
455
456/* magician audio subsystem */ 452/* magician audio subsystem */
457static struct snd_soc_device magician_snd_devdata = { 453static struct snd_soc_device magician_snd_devdata = {
458 .card = &snd_soc_card_magician, 454 .card = &snd_soc_card_magician,
459 .codec_dev = &soc_codec_dev_uda1380, 455 .codec_dev = &soc_codec_dev_uda1380,
460 .codec_data = &magician_uda1380_setup,
461}; 456};
462 457
463static struct platform_device *magician_snd_device; 458static struct platform_device *magician_snd_device;
464 459
460/*
461 * FIXME: move into magician board file once merged into the pxa tree
462 */
463static struct uda1380_platform_data uda1380_info = {
464 .gpio_power = EGPIO_MAGICIAN_CODEC_POWER,
465 .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET,
466 .dac_clk = UDA1380_DAC_CLK_WSPLL,
467};
468
469static struct i2c_board_info i2c_board_info[] = {
470 {
471 I2C_BOARD_INFO("uda1380", 0x18),
472 .platform_data = &uda1380_info,
473 },
474};
475
465static int __init magician_init(void) 476static int __init magician_init(void)
466{ 477{
467 int ret; 478 int ret;
479 struct i2c_adapter *adapter;
480 struct i2c_client *client;
468 481
469 if (!machine_is_magician()) 482 if (!machine_is_magician())
470 return -ENODEV; 483 return -ENODEV;
471 484
472 ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER"); 485 adapter = i2c_get_adapter(0);
473 if (ret) 486 if (!adapter)
474 goto err_request_power; 487 return -ENODEV;
475 ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET"); 488 client = i2c_new_device(adapter, i2c_board_info);
476 if (ret) 489 i2c_put_adapter(adapter);
477 goto err_request_reset; 490 if (!client)
491 return -ENODEV;
492
478 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); 493 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
479 if (ret) 494 if (ret)
480 goto err_request_spk; 495 goto err_request_spk;
@@ -491,14 +506,8 @@ static int __init magician_init(void)
491 if (ret) 506 if (ret)
492 goto err_request_in_sel1; 507 goto err_request_in_sel1;
493 508
494 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
495 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); 509 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
496 510
497 /* we may need to have the clock running here - pH5 */
498 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
499 udelay(5);
500 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
501
502 magician_snd_device = platform_device_alloc("soc-audio", -1); 511 magician_snd_device = platform_device_alloc("soc-audio", -1);
503 if (!magician_snd_device) { 512 if (!magician_snd_device) {
504 ret = -ENOMEM; 513 ret = -ENOMEM;
@@ -526,10 +535,6 @@ err_request_mic:
526err_request_ep: 535err_request_ep:
527 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 536 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
528err_request_spk: 537err_request_spk:
529 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
530err_request_reset:
531 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
532err_request_power:
533 return ret; 538 return ret;
534} 539}
535 540
@@ -540,15 +545,12 @@ static void __exit magician_exit(void)
540 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); 545 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
541 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); 546 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
542 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); 547 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
543 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
544 548
545 gpio_free(EGPIO_MAGICIAN_IN_SEL1); 549 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
546 gpio_free(EGPIO_MAGICIAN_IN_SEL0); 550 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
547 gpio_free(EGPIO_MAGICIAN_MIC_POWER); 551 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
548 gpio_free(EGPIO_MAGICIAN_EP_POWER); 552 gpio_free(EGPIO_MAGICIAN_EP_POWER);
549 gpio_free(EGPIO_MAGICIAN_SPK_POWER); 553 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
550 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
551 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
552} 554}
553 555
554module_init(magician_init); 556module_init(magician_init);
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index e6102fda0a7f..1f96e3227be5 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -17,13 +17,12 @@
17#include <linux/moduleparam.h> 17#include <linux/moduleparam.h>
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/gpio.h> 19#include <linux/gpio.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22 20
23#include <sound/core.h> 21#include <sound/core.h>
24#include <sound/pcm.h> 22#include <sound/pcm.h>
25#include <sound/soc.h> 23#include <sound/soc.h>
26#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25#include <sound/jack.h>
27 26
28#include <asm/mach-types.h> 27#include <asm/mach-types.h>
29#include <mach/audio.h> 28#include <mach/audio.h>
@@ -33,90 +32,31 @@
33#include "pxa2xx-pcm.h" 32#include "pxa2xx-pcm.h"
34#include "pxa2xx-ac97.h" 33#include "pxa2xx-ac97.h"
35 34
36static int palm27x_jack_func = 1; 35static struct snd_soc_jack hs_jack;
37static int palm27x_spk_func = 1;
38static int palm27x_ep_gpio = -1;
39 36
40static void palm27x_ext_control(struct snd_soc_codec *codec) 37/* Headphones jack detection DAPM pins */
41{ 38static struct snd_soc_jack_pin hs_jack_pins[] = {
42 if (!palm27x_spk_func) 39 {
43 snd_soc_dapm_enable_pin(codec, "Speaker"); 40 .pin = "Headphone Jack",
44 else 41 .mask = SND_JACK_HEADPHONE,
45 snd_soc_dapm_disable_pin(codec, "Speaker"); 42 },
46
47 if (!palm27x_jack_func)
48 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
49 else
50 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
51
52 snd_soc_dapm_sync(codec);
53}
54
55static int palm27x_startup(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_codec *codec = rtd->socdev->card->codec;
59
60 /* check the jack status at stream startup */
61 palm27x_ext_control(codec);
62 return 0;
63}
64
65static struct snd_soc_ops palm27x_ops = {
66 .startup = palm27x_startup,
67}; 43};
68 44
69static irqreturn_t palm27x_interrupt(int irq, void *v) 45/* Headphones jack detection gpios */
70{ 46static struct snd_soc_jack_gpio hs_jack_gpios[] = {
71 palm27x_spk_func = gpio_get_value(palm27x_ep_gpio); 47 [0] = {
72 palm27x_jack_func = !palm27x_spk_func; 48 /* gpio is set on per-platform basis */
73 return IRQ_HANDLED; 49 .name = "hp-gpio",
74} 50 .report = SND_JACK_HEADPHONE,
75 51 .debounce_time = 200,
76static int palm27x_get_jack(struct snd_kcontrol *kcontrol, 52 },
77 struct snd_ctl_elem_value *ucontrol) 53};
78{
79 ucontrol->value.integer.value[0] = palm27x_jack_func;
80 return 0;
81}
82
83static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_value *ucontrol)
85{
86 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
87
88 if (palm27x_jack_func == ucontrol->value.integer.value[0])
89 return 0;
90
91 palm27x_jack_func = ucontrol->value.integer.value[0];
92 palm27x_ext_control(codec);
93 return 1;
94}
95
96static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
98{
99 ucontrol->value.integer.value[0] = palm27x_spk_func;
100 return 0;
101}
102
103static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
107
108 if (palm27x_spk_func == ucontrol->value.integer.value[0])
109 return 0;
110
111 palm27x_spk_func = ucontrol->value.integer.value[0];
112 palm27x_ext_control(codec);
113 return 1;
114}
115 54
116/* PalmTX machine dapm widgets */ 55/* Palm27x machine dapm widgets */
117static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { 56static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
118 SND_SOC_DAPM_HP("Headphone Jack", NULL), 57 SND_SOC_DAPM_HP("Headphone Jack", NULL),
119 SND_SOC_DAPM_SPK("Speaker", NULL), 58 SND_SOC_DAPM_SPK("Ext. Speaker", NULL),
59 SND_SOC_DAPM_MIC("Ext. Microphone", NULL),
120}; 60};
121 61
122/* PalmTX audio map */ 62/* PalmTX audio map */
@@ -126,46 +66,66 @@ static const struct snd_soc_dapm_route audio_map[] = {
126 {"Headphone Jack", NULL, "HPOUTR"}, 66 {"Headphone Jack", NULL, "HPOUTR"},
127 67
128 /* ext speaker connected to ROUT2, LOUT2 */ 68 /* ext speaker connected to ROUT2, LOUT2 */
129 {"Speaker", NULL, "LOUT2"}, 69 {"Ext. Speaker", NULL, "LOUT2"},
130 {"Speaker", NULL, "ROUT2"}, 70 {"Ext. Speaker", NULL, "ROUT2"},
131};
132 71
133static const char *jack_function[] = {"Headphone", "Off"}; 72 /* mic connected to MIC1 */
134static const char *spk_function[] = {"On", "Off"}; 73 {"Ext. Microphone", NULL, "MIC1"},
135static const struct soc_enum palm27x_enum[] = {
136 SOC_ENUM_SINGLE_EXT(2, jack_function),
137 SOC_ENUM_SINGLE_EXT(2, spk_function),
138}; 74};
139 75
140static const struct snd_kcontrol_new palm27x_controls[] = { 76static struct snd_soc_card palm27x_asoc;
141 SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
142 palm27x_set_jack),
143 SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
144 palm27x_set_spk),
145};
146 77
147static int palm27x_ac97_init(struct snd_soc_codec *codec) 78static int palm27x_ac97_init(struct snd_soc_codec *codec)
148{ 79{
149 int err; 80 int err;
150 81
82 /* add palm27x specific widgets */
83 err = snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
84 ARRAY_SIZE(palm27x_dapm_widgets));
85 if (err)
86 return err;
87
88 /* set up palm27x specific audio path audio_map */
89 err = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
90 if (err)
91 return err;
92
93 /* connected pins */
94 if (machine_is_palmld())
95 snd_soc_dapm_enable_pin(codec, "MIC1");
96 snd_soc_dapm_enable_pin(codec, "HPOUTL");
97 snd_soc_dapm_enable_pin(codec, "HPOUTR");
98 snd_soc_dapm_enable_pin(codec, "LOUT2");
99 snd_soc_dapm_enable_pin(codec, "ROUT2");
100
101 /* not connected pins */
151 snd_soc_dapm_nc_pin(codec, "OUT3"); 102 snd_soc_dapm_nc_pin(codec, "OUT3");
152 snd_soc_dapm_nc_pin(codec, "MONOOUT"); 103 snd_soc_dapm_nc_pin(codec, "MONOOUT");
104 snd_soc_dapm_nc_pin(codec, "LINEINL");
105 snd_soc_dapm_nc_pin(codec, "LINEINR");
106 snd_soc_dapm_nc_pin(codec, "PCBEEP");
107 snd_soc_dapm_nc_pin(codec, "PHONE");
108 snd_soc_dapm_nc_pin(codec, "MIC2");
109
110 err = snd_soc_dapm_sync(codec);
111 if (err)
112 return err;
153 113
154 /* add palm27x specific controls */ 114 /* Jack detection API stuff */
155 err = snd_soc_add_controls(codec, palm27x_controls, 115 err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack",
156 ARRAY_SIZE(palm27x_controls)); 116 SND_JACK_HEADPHONE, &hs_jack);
157 if (err < 0) 117 if (err)
158 return err; 118 return err;
159 119
160 /* add palm27x specific widgets */ 120 err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
161 snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, 121 hs_jack_pins);
162 ARRAY_SIZE(palm27x_dapm_widgets)); 122 if (err)
123 return err;
163 124
164 /* set up palm27x specific audio path audio_map */ 125 err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
165 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 126 hs_jack_gpios);
166 127
167 snd_soc_dapm_sync(codec); 128 return err;
168 return 0;
169} 129}
170 130
171static struct snd_soc_dai_link palm27x_dai[] = { 131static struct snd_soc_dai_link palm27x_dai[] = {
@@ -175,14 +135,12 @@ static struct snd_soc_dai_link palm27x_dai[] = {
175 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 135 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
176 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 136 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
177 .init = palm27x_ac97_init, 137 .init = palm27x_ac97_init,
178 .ops = &palm27x_ops,
179}, 138},
180{ 139{
181 .name = "AC97 Aux", 140 .name = "AC97 Aux",
182 .stream_name = "AC97 Aux", 141 .stream_name = "AC97 Aux",
183 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 142 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
184 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 143 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
185 .ops = &palm27x_ops,
186}, 144},
187}; 145};
188 146
@@ -208,27 +166,17 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
208 machine_is_palmld() || machine_is_palmte2())) 166 machine_is_palmld() || machine_is_palmte2()))
209 return -ENODEV; 167 return -ENODEV;
210 168
211 if (pdev->dev.platform_data) 169 if (!pdev->dev.platform_data) {
212 palm27x_ep_gpio = ((struct palm27x_asoc_info *) 170 dev_err(&pdev->dev, "please supply platform_data\n");
213 (pdev->dev.platform_data))->jack_gpio; 171 return -ENODEV;
214 172 }
215 ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
216 if (ret)
217 return ret;
218 ret = gpio_direction_input(palm27x_ep_gpio);
219 if (ret)
220 goto err_alloc;
221 173
222 if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt, 174 hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *)
223 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 175 (pdev->dev.platform_data))->jack_gpio;
224 "Headphone jack", NULL))
225 goto err_alloc;
226 176
227 palm27x_snd_device = platform_device_alloc("soc-audio", -1); 177 palm27x_snd_device = platform_device_alloc("soc-audio", -1);
228 if (!palm27x_snd_device) { 178 if (!palm27x_snd_device)
229 ret = -ENOMEM; 179 return -ENOMEM;
230 goto err_dev;
231 }
232 180
233 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); 181 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
234 palm27x_snd_devdata.dev = &palm27x_snd_device->dev; 182 palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
@@ -241,18 +189,12 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
241 189
242put_device: 190put_device:
243 platform_device_put(palm27x_snd_device); 191 platform_device_put(palm27x_snd_device);
244err_dev:
245 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
246err_alloc:
247 gpio_free(palm27x_ep_gpio);
248 192
249 return ret; 193 return ret;
250} 194}
251 195
252static int __devexit palm27x_asoc_remove(struct platform_device *pdev) 196static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
253{ 197{
254 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
255 gpio_free(palm27x_ep_gpio);
256 platform_device_unregister(palm27x_snd_device); 198 platform_device_unregister(palm27x_snd_device);
257 return 0; 199 return 0;
258} 200}
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 19c45409d94c..e22c5cef8fec 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -457,31 +457,27 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
457 return -EINVAL; 457 return -EINVAL;
458 } 458 }
459 459
460 ssp_write_reg(ssp, SSCR0, sscr0); 460 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
461 ssp_write_reg(ssp, SSCR1, sscr1); 461 case SND_SOC_DAIFMT_NB_NF:
462 ssp_write_reg(ssp, SSPSP, sspsp); 462 sspsp |= SSPSP_SFRMP;
463 break;
464 case SND_SOC_DAIFMT_NB_IF:
465 break;
466 case SND_SOC_DAIFMT_IB_IF:
467 sspsp |= SSPSP_SCMODE(2);
468 break;
469 case SND_SOC_DAIFMT_IB_NF:
470 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
471 break;
472 default:
473 return -EINVAL;
474 }
463 475
464 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 476 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
465 case SND_SOC_DAIFMT_I2S: 477 case SND_SOC_DAIFMT_I2S:
466 sscr0 |= SSCR0_PSP; 478 sscr0 |= SSCR0_PSP;
467 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; 479 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
468
469 /* See hw_params() */ 480 /* See hw_params() */
470 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
471 case SND_SOC_DAIFMT_NB_NF:
472 sspsp |= SSPSP_SFRMP;
473 break;
474 case SND_SOC_DAIFMT_NB_IF:
475 break;
476 case SND_SOC_DAIFMT_IB_IF:
477 sspsp |= SSPSP_SCMODE(2);
478 break;
479 case SND_SOC_DAIFMT_IB_NF:
480 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
481 break;
482 default:
483 return -EINVAL;
484 }
485 break; 481 break;
486 482
487 case SND_SOC_DAIFMT_DSP_A: 483 case SND_SOC_DAIFMT_DSP_A:
@@ -489,22 +485,6 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
489 case SND_SOC_DAIFMT_DSP_B: 485 case SND_SOC_DAIFMT_DSP_B:
490 sscr0 |= SSCR0_MOD | SSCR0_PSP; 486 sscr0 |= SSCR0_MOD | SSCR0_PSP;
491 sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; 487 sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
492
493 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
494 case SND_SOC_DAIFMT_NB_NF:
495 sspsp |= SSPSP_SFRMP;
496 break;
497 case SND_SOC_DAIFMT_NB_IF:
498 break;
499 case SND_SOC_DAIFMT_IB_IF:
500 sspsp |= SSPSP_SCMODE(2);
501 break;
502 case SND_SOC_DAIFMT_IB_NF:
503 sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
504 break;
505 default:
506 return -EINVAL;
507 }
508 break; 488 break;
509 489
510 default: 490 default:
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index df494d1e346f..808de5c5caa7 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -38,6 +38,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753
38 Say Y if you want to add support for SoC audio on smdk2440 38 Say Y if you want to add support for SoC audio on smdk2440
39 with the WM8753. 39 with the WM8753.
40 40
41config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
42 tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
43 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
44 select SND_S3C24XX_SOC_I2S
45 select SND_SOC_WM8753
46 help
47 This driver provides audio support for the Openmoko Neo FreeRunner
48 smartphone.
49
41config SND_S3C24XX_SOC_JIVE_WM8750 50config SND_S3C24XX_SOC_JIVE_WM8750
42 tristate "SoC I2S Audio support for Jive" 51 tristate "SoC I2S Audio support for Jive"
43 depends on SND_S3C24XX_SOC && MACH_JIVE 52 depends on SND_S3C24XX_SOC && MACH_JIVE
@@ -57,7 +66,7 @@ config SND_S3C24XX_SOC_SMDK2443_WM9710
57 66
58config SND_S3C24XX_SOC_LN2440SBC_ALC650 67config SND_S3C24XX_SOC_LN2440SBC_ALC650
59 tristate "SoC AC97 Audio support for LN2440SBC - ALC650" 68 tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
60 depends on SND_S3C24XX_SOC 69 depends on SND_S3C24XX_SOC && ARCH_S3C2410
61 select SND_S3C2443_SOC_AC97 70 select SND_S3C2443_SOC_AC97
62 select SND_SOC_AC97_CODEC 71 select SND_SOC_AC97_CODEC
63 help 72 help
@@ -66,7 +75,7 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
66 75
67config SND_S3C24XX_SOC_S3C24XX_UDA134X 76config SND_S3C24XX_SOC_S3C24XX_UDA134X
68 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" 77 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
69 depends on SND_S3C24XX_SOC 78 depends on SND_S3C24XX_SOC && ARCH_S3C2410
70 select SND_S3C24XX_SOC_I2S 79 select SND_S3C24XX_SOC_I2S
71 select SND_SOC_L3 80 select SND_SOC_L3
72 select SND_SOC_UDA134X 81 select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 07a93a2ebe5f..eb219b016499 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -16,12 +16,14 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
16# S3C24XX Machine Support 16# S3C24XX Machine Support
17snd-soc-jive-wm8750-objs := jive_wm8750.o 17snd-soc-jive-wm8750-objs := jive_wm8750.o
18snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o 18snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
19snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
19snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o 20snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
20snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o 21snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
21snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o 22snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
22 23
23obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 24obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
24obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 25obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
26obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
25obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o 27obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
26obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o 28obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
27obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o 29obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
new file mode 100644
index 000000000000..0c52e36ddd87
--- /dev/null
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -0,0 +1,498 @@
1/*
2 * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02)
3 *
4 * Copyright 2007 Openmoko Inc
5 * Author: Graeme Gregory <graeme@openmoko.org>
6 * Copyright 2007 Wolfson Microelectronics PLC.
7 * Author: Graeme Gregory <linux@wolfsonmicro.com>
8 * Copyright 2009 Wolfson Microelectronics
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/module.h>
17#include <linux/moduleparam.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/gpio.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28
29#include <plat/regs-iis.h>
30
31#include <mach/regs-clock.h>
32#include <asm/io.h>
33#include <mach/gta02.h>
34#include "../codecs/wm8753.h"
35#include "s3c24xx-pcm.h"
36#include "s3c24xx-i2s.h"
37
38static struct snd_soc_card neo1973_gta02;
39
40static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params)
42{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
45 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
46 unsigned int pll_out = 0, bclk = 0;
47 int ret = 0;
48 unsigned long iis_clkrate;
49
50 iis_clkrate = s3c24xx_i2s_get_clockrate();
51
52 switch (params_rate(params)) {
53 case 8000:
54 case 16000:
55 pll_out = 12288000;
56 break;
57 case 48000:
58 bclk = WM8753_BCLK_DIV_4;
59 pll_out = 12288000;
60 break;
61 case 96000:
62 bclk = WM8753_BCLK_DIV_2;
63 pll_out = 12288000;
64 break;
65 case 11025:
66 bclk = WM8753_BCLK_DIV_16;
67 pll_out = 11289600;
68 break;
69 case 22050:
70 bclk = WM8753_BCLK_DIV_8;
71 pll_out = 11289600;
72 break;
73 case 44100:
74 bclk = WM8753_BCLK_DIV_4;
75 pll_out = 11289600;
76 break;
77 case 88200:
78 bclk = WM8753_BCLK_DIV_2;
79 pll_out = 11289600;
80 break;
81 }
82
83 /* set codec DAI configuration */
84 ret = snd_soc_dai_set_fmt(codec_dai,
85 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
86 SND_SOC_DAIFMT_CBM_CFM);
87 if (ret < 0)
88 return ret;
89
90 /* set cpu DAI configuration */
91 ret = snd_soc_dai_set_fmt(cpu_dai,
92 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
93 SND_SOC_DAIFMT_CBM_CFM);
94 if (ret < 0)
95 return ret;
96
97 /* set the codec system clock for DAC and ADC */
98 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
99 SND_SOC_CLOCK_IN);
100 if (ret < 0)
101 return ret;
102
103 /* set MCLK division for sample rate */
104 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
105 S3C2410_IISMOD_32FS);
106 if (ret < 0)
107 return ret;
108
109 /* set codec BCLK division for sample rate */
110 ret = snd_soc_dai_set_clkdiv(codec_dai,
111 WM8753_BCLKDIV, bclk);
112 if (ret < 0)
113 return ret;
114
115 /* set prescaler division for sample rate */
116 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
117 S3C24XX_PRESCALE(4, 4));
118 if (ret < 0)
119 return ret;
120
121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
123 iis_clkrate / 4, pll_out);
124 if (ret < 0)
125 return ret;
126
127 return 0;
128}
129
130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
134
135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
137}
138
139/*
140 * Neo1973 WM8753 HiFi DAI opserations.
141 */
142static struct snd_soc_ops neo1973_gta02_hifi_ops = {
143 .hw_params = neo1973_gta02_hifi_hw_params,
144 .hw_free = neo1973_gta02_hifi_hw_free,
145};
146
147static int neo1973_gta02_voice_hw_params(
148 struct snd_pcm_substream *substream,
149 struct snd_pcm_hw_params *params)
150{
151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
152 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
153 unsigned int pcmdiv = 0;
154 int ret = 0;
155 unsigned long iis_clkrate;
156
157 iis_clkrate = s3c24xx_i2s_get_clockrate();
158
159 if (params_rate(params) != 8000)
160 return -EINVAL;
161 if (params_channels(params) != 1)
162 return -EINVAL;
163
164 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
165
166 /* todo: gg check mode (DSP_B) against CSR datasheet */
167 /* set codec DAI configuration */
168 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
169 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
170 if (ret < 0)
171 return ret;
172
173 /* set the codec system clock for DAC and ADC */
174 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
175 12288000, SND_SOC_CLOCK_IN);
176 if (ret < 0)
177 return ret;
178
179 /* set codec PCM division for sample rate */
180 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
181 pcmdiv);
182 if (ret < 0)
183 return ret;
184
185 /* configue and enable PLL for 12.288MHz output */
186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
187 iis_clkrate / 4, 12288000);
188 if (ret < 0)
189 return ret;
190
191 return 0;
192}
193
194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
195{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
198
199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
201}
202
203static struct snd_soc_ops neo1973_gta02_voice_ops = {
204 .hw_params = neo1973_gta02_voice_hw_params,
205 .hw_free = neo1973_gta02_voice_hw_free,
206};
207
208#define LM4853_AMP 1
209#define LM4853_SPK 2
210
211static u8 lm4853_state;
212
213/* This has no effect, it exists only to maintain compatibility with
214 * existing ALSA state files.
215 */
216static int lm4853_set_state(struct snd_kcontrol *kcontrol,
217 struct snd_ctl_elem_value *ucontrol)
218{
219 int val = ucontrol->value.integer.value[0];
220
221 if (val)
222 lm4853_state |= LM4853_AMP;
223 else
224 lm4853_state &= ~LM4853_AMP;
225
226 return 0;
227}
228
229static int lm4853_get_state(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_value *ucontrol)
231{
232 ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
233
234 return 0;
235}
236
237static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
238 struct snd_ctl_elem_value *ucontrol)
239{
240 int val = ucontrol->value.integer.value[0];
241
242 if (val) {
243 lm4853_state |= LM4853_SPK;
244 gpio_set_value(GTA02_GPIO_HP_IN, 0);
245 } else {
246 lm4853_state &= ~LM4853_SPK;
247 gpio_set_value(GTA02_GPIO_HP_IN, 1);
248 }
249
250 return 0;
251}
252
253static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
255{
256 ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
257
258 return 0;
259}
260
261static int lm4853_event(struct snd_soc_dapm_widget *w,
262 struct snd_kcontrol *k,
263 int event)
264{
265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value));
266
267 return 0;
268}
269
270static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
271 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
272 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
273 SND_SOC_DAPM_LINE("GSM Line In", NULL),
274 SND_SOC_DAPM_MIC("Headset Mic", NULL),
275 SND_SOC_DAPM_MIC("Handset Mic", NULL),
276 SND_SOC_DAPM_SPK("Handset Spk", NULL),
277};
278
279
280/* example machine audio_mapnections */
281static const struct snd_soc_dapm_route audio_map[] = {
282
283 /* Connections to the lm4853 amp */
284 {"Stereo Out", NULL, "LOUT1"},
285 {"Stereo Out", NULL, "ROUT1"},
286
287 /* Connections to the GSM Module */
288 {"GSM Line Out", NULL, "MONO1"},
289 {"GSM Line Out", NULL, "MONO2"},
290 {"RXP", NULL, "GSM Line In"},
291 {"RXN", NULL, "GSM Line In"},
292
293 /* Connections to Headset */
294 {"MIC1", NULL, "Mic Bias"},
295 {"Mic Bias", NULL, "Headset Mic"},
296
297 /* Call Mic */
298 {"MIC2", NULL, "Mic Bias"},
299 {"MIC2N", NULL, "Mic Bias"},
300 {"Mic Bias", NULL, "Handset Mic"},
301
302 /* Call Speaker */
303 {"Handset Spk", NULL, "LOUT2"},
304 {"Handset Spk", NULL, "ROUT2"},
305
306 /* Connect the ALC pins */
307 {"ACIN", NULL, "ACOP"},
308};
309
310static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
311 SOC_DAPM_PIN_SWITCH("Stereo Out"),
312 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
313 SOC_DAPM_PIN_SWITCH("GSM Line In"),
314 SOC_DAPM_PIN_SWITCH("Headset Mic"),
315 SOC_DAPM_PIN_SWITCH("Handset Mic"),
316 SOC_DAPM_PIN_SWITCH("Handset Spk"),
317
318 /* This has no effect, it exists only to maintain compatibility with
319 * existing ALSA state files.
320 */
321 SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
322 lm4853_get_state,
323 lm4853_set_state),
324 SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
325 lm4853_get_spk,
326 lm4853_set_spk),
327};
328
329/*
330 * This is an example machine initialisation for a wm8753 connected to a
331 * neo1973 GTA02.
332 */
333static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
334{
335 int err;
336
337 /* set up NC codec pins */
338 snd_soc_dapm_nc_pin(codec, "OUT3");
339 snd_soc_dapm_nc_pin(codec, "OUT4");
340 snd_soc_dapm_nc_pin(codec, "LINE1");
341 snd_soc_dapm_nc_pin(codec, "LINE2");
342
343 /* Add neo1973 gta02 specific widgets */
344 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
345 ARRAY_SIZE(wm8753_dapm_widgets));
346
347 /* add neo1973 gta02 specific controls */
348 err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
349 ARRAY_SIZE(wm8753_neo1973_gta02_controls));
350
351 if (err < 0)
352 return err;
353
354 /* set up neo1973 gta02 specific audio path audio_map */
355 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
356
357 /* set endpoints to default off mode */
358 snd_soc_dapm_disable_pin(codec, "Stereo Out");
359 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
360 snd_soc_dapm_disable_pin(codec, "GSM Line In");
361 snd_soc_dapm_disable_pin(codec, "Headset Mic");
362 snd_soc_dapm_disable_pin(codec, "Handset Mic");
363 snd_soc_dapm_disable_pin(codec, "Handset Spk");
364
365 snd_soc_dapm_sync(codec);
366
367 return 0;
368}
369
370/*
371 * BT Codec DAI
372 */
373static struct snd_soc_dai bt_dai = {
374 .name = "Bluetooth",
375 .id = 0,
376 .playback = {
377 .channels_min = 1,
378 .channels_max = 1,
379 .rates = SNDRV_PCM_RATE_8000,
380 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
381 .capture = {
382 .channels_min = 1,
383 .channels_max = 1,
384 .rates = SNDRV_PCM_RATE_8000,
385 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
386};
387
388static struct snd_soc_dai_link neo1973_gta02_dai[] = {
389{ /* Hifi Playback - for similatious use with voice below */
390 .name = "WM8753",
391 .stream_name = "WM8753 HiFi",
392 .cpu_dai = &s3c24xx_i2s_dai,
393 .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
394 .init = neo1973_gta02_wm8753_init,
395 .ops = &neo1973_gta02_hifi_ops,
396},
397{ /* Voice via BT */
398 .name = "Bluetooth",
399 .stream_name = "Voice",
400 .cpu_dai = &bt_dai,
401 .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
402 .ops = &neo1973_gta02_voice_ops,
403},
404};
405
406static struct snd_soc_card neo1973_gta02 = {
407 .name = "neo1973-gta02",
408 .platform = &s3c24xx_soc_platform,
409 .dai_link = neo1973_gta02_dai,
410 .num_links = ARRAY_SIZE(neo1973_gta02_dai),
411};
412
413static struct snd_soc_device neo1973_gta02_snd_devdata = {
414 .card = &neo1973_gta02,
415 .codec_dev = &soc_codec_dev_wm8753,
416};
417
418static struct platform_device *neo1973_gta02_snd_device;
419
420static int __init neo1973_gta02_init(void)
421{
422 int ret;
423
424 if (!machine_is_neo1973_gta02()) {
425 printk(KERN_INFO
426 "Only GTA02 is supported by this ASoC driver\n");
427 return -ENODEV;
428 }
429
430 /* register bluetooth DAI here */
431 ret = snd_soc_register_dai(&bt_dai);
432 if (ret)
433 return ret;
434
435 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
436 if (!neo1973_gta02_snd_device)
437 return -ENOMEM;
438
439 platform_set_drvdata(neo1973_gta02_snd_device,
440 &neo1973_gta02_snd_devdata);
441 neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev;
442 ret = platform_device_add(neo1973_gta02_snd_device);
443
444 if (ret) {
445 platform_device_put(neo1973_gta02_snd_device);
446 return ret;
447 }
448
449 /* Initialise GPIOs used by amp */
450 ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
451 if (ret) {
452 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
453 goto err_unregister_device;
454 }
455
456 ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1);
457 if (ret) {
458 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
459 goto err_free_gpio_hp_in;
460 }
461
462 ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
463 if (ret) {
464 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
465 goto err_free_gpio_hp_in;
466 }
467
468 ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
469 if (ret) {
470 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
471 goto err_free_gpio_amp_shut;
472 }
473
474 return 0;
475
476err_free_gpio_amp_shut:
477 gpio_free(GTA02_GPIO_AMP_SHUT);
478err_free_gpio_hp_in:
479 gpio_free(GTA02_GPIO_HP_IN);
480err_unregister_device:
481 platform_device_unregister(neo1973_gta02_snd_device);
482 return ret;
483}
484module_init(neo1973_gta02_init);
485
486static void __exit neo1973_gta02_exit(void)
487{
488 snd_soc_unregister_dai(&bt_dai);
489 platform_device_unregister(neo1973_gta02_snd_device);
490 gpio_free(GTA02_GPIO_HP_IN);
491 gpio_free(GTA02_GPIO_AMP_SHUT);
492}
493module_exit(neo1973_gta02_exit);
494
495/* Module information */
496MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
497MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
498MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1d70829464ef..fb8d7a766155 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -28,6 +28,7 @@
28#include <linux/bitops.h> 28#include <linux/bitops.h>
29#include <linux/debugfs.h> 29#include <linux/debugfs.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <sound/ac97_codec.h>
31#include <sound/core.h> 32#include <sound/core.h>
32#include <sound/pcm.h> 33#include <sound/pcm.h>
33#include <sound/pcm_params.h> 34#include <sound/pcm_params.h>
@@ -619,8 +620,9 @@ static struct snd_pcm_ops soc_pcm_ops = {
619 620
620#ifdef CONFIG_PM 621#ifdef CONFIG_PM
621/* powers down audio subsystem for suspend */ 622/* powers down audio subsystem for suspend */
622static int soc_suspend(struct platform_device *pdev, pm_message_t state) 623static int soc_suspend(struct device *dev)
623{ 624{
625 struct platform_device *pdev = to_platform_device(dev);
624 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 626 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
625 struct snd_soc_card *card = socdev->card; 627 struct snd_soc_card *card = socdev->card;
626 struct snd_soc_platform *platform = card->platform; 628 struct snd_soc_platform *platform = card->platform;
@@ -656,7 +658,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
656 snd_pcm_suspend_all(card->dai_link[i].pcm); 658 snd_pcm_suspend_all(card->dai_link[i].pcm);
657 659
658 if (card->suspend_pre) 660 if (card->suspend_pre)
659 card->suspend_pre(pdev, state); 661 card->suspend_pre(pdev, PMSG_SUSPEND);
660 662
661 for (i = 0; i < card->num_links; i++) { 663 for (i = 0; i < card->num_links; i++) {
662 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 664 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
@@ -682,7 +684,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
682 } 684 }
683 685
684 if (codec_dev->suspend) 686 if (codec_dev->suspend)
685 codec_dev->suspend(pdev, state); 687 codec_dev->suspend(pdev, PMSG_SUSPEND);
686 688
687 for (i = 0; i < card->num_links; i++) { 689 for (i = 0; i < card->num_links; i++) {
688 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 690 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
@@ -691,7 +693,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
691 } 693 }
692 694
693 if (card->suspend_post) 695 if (card->suspend_post)
694 card->suspend_post(pdev, state); 696 card->suspend_post(pdev, PMSG_SUSPEND);
695 697
696 return 0; 698 return 0;
697} 699}
@@ -765,8 +767,9 @@ static void soc_resume_deferred(struct work_struct *work)
765} 767}
766 768
767/* powers up audio subsystem after a suspend */ 769/* powers up audio subsystem after a suspend */
768static int soc_resume(struct platform_device *pdev) 770static int soc_resume(struct device *dev)
769{ 771{
772 struct platform_device *pdev = to_platform_device(dev);
770 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 773 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
771 struct snd_soc_card *card = socdev->card; 774 struct snd_soc_card *card = socdev->card;
772 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; 775 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
@@ -788,6 +791,44 @@ static int soc_resume(struct platform_device *pdev)
788 return 0; 791 return 0;
789} 792}
790 793
794/**
795 * snd_soc_suspend_device: Notify core of device suspend
796 *
797 * @dev: Device being suspended.
798 *
799 * In order to ensure that the entire audio subsystem is suspended in a
800 * coordinated fashion ASoC devices should suspend themselves when
801 * called by ASoC. When the standard kernel suspend process asks the
802 * device to suspend it should call this function to initiate a suspend
803 * of the entire ASoC card.
804 *
805 * \note Currently this function is stubbed out.
806 */
807int snd_soc_suspend_device(struct device *dev)
808{
809 return 0;
810}
811EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
812
813/**
814 * snd_soc_resume_device: Notify core of device resume
815 *
816 * @dev: Device being resumed.
817 *
818 * In order to ensure that the entire audio subsystem is resumed in a
819 * coordinated fashion ASoC devices should resume themselves when called
820 * by ASoC. When the standard kernel resume process asks the device
821 * to resume it should call this function. Once all the components of
822 * the card have notified that they are ready to be resumed the card
823 * will be resumed.
824 *
825 * \note Currently this function is stubbed out.
826 */
827int snd_soc_resume_device(struct device *dev)
828{
829 return 0;
830}
831EXPORT_SYMBOL_GPL(snd_soc_resume_device);
791#else 832#else
792#define soc_suspend NULL 833#define soc_suspend NULL
793#define soc_resume NULL 834#define soc_resume NULL
@@ -981,16 +1022,39 @@ static int soc_remove(struct platform_device *pdev)
981 return 0; 1022 return 0;
982} 1023}
983 1024
1025static int soc_poweroff(struct device *dev)
1026{
1027 struct platform_device *pdev = to_platform_device(dev);
1028 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1029 struct snd_soc_card *card = socdev->card;
1030
1031 if (!card->instantiated)
1032 return 0;
1033
1034 /* Flush out pmdown_time work - we actually do want to run it
1035 * now, we're shutting down so no imminent restart. */
1036 run_delayed_work(&card->delayed_work);
1037
1038 snd_soc_dapm_shutdown(socdev);
1039
1040 return 0;
1041}
1042
1043static struct dev_pm_ops soc_pm_ops = {
1044 .suspend = soc_suspend,
1045 .resume = soc_resume,
1046 .poweroff = soc_poweroff,
1047};
1048
984/* ASoC platform driver */ 1049/* ASoC platform driver */
985static struct platform_driver soc_driver = { 1050static struct platform_driver soc_driver = {
986 .driver = { 1051 .driver = {
987 .name = "soc-audio", 1052 .name = "soc-audio",
988 .owner = THIS_MODULE, 1053 .owner = THIS_MODULE,
1054 .pm = &soc_pm_ops,
989 }, 1055 },
990 .probe = soc_probe, 1056 .probe = soc_probe,
991 .remove = soc_remove, 1057 .remove = soc_remove,
992 .suspend = soc_suspend,
993 .resume = soc_resume,
994}; 1058};
995 1059
996/* create a new pcm */ 1060/* create a new pcm */
@@ -1062,6 +1126,23 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1062 return ret; 1126 return ret;
1063} 1127}
1064 1128
1129/**
1130 * snd_soc_codec_volatile_register: Report if a register is volatile.
1131 *
1132 * @codec: CODEC to query.
1133 * @reg: Register to query.
1134 *
1135 * Boolean function indiciating if a CODEC register is volatile.
1136 */
1137int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1138{
1139 if (codec->volatile_register)
1140 return codec->volatile_register(reg);
1141 else
1142 return 0;
1143}
1144EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1145
1065/* codec register dump */ 1146/* codec register dump */
1066static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) 1147static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1067{ 1148{
@@ -1075,6 +1156,9 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1075 1156
1076 count += sprintf(buf, "%s registers\n", codec->name); 1157 count += sprintf(buf, "%s registers\n", codec->name);
1077 for (i = 0; i < codec->reg_cache_size; i += step) { 1158 for (i = 0; i < codec->reg_cache_size; i += step) {
1159 if (codec->readable_register && !codec->readable_register(i))
1160 continue;
1161
1078 count += sprintf(buf + count, "%2x: ", i); 1162 count += sprintf(buf + count, "%2x: ", i);
1079 if (count >= PAGE_SIZE - 1) 1163 if (count >= PAGE_SIZE - 1)
1080 break; 1164 break;
@@ -1264,10 +1348,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
1264 * Returns 1 for change else 0. 1348 * Returns 1 for change else 0.
1265 */ 1349 */
1266int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, 1350int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
1267 unsigned short mask, unsigned short value) 1351 unsigned int mask, unsigned int value)
1268{ 1352{
1269 int change; 1353 int change;
1270 unsigned short old, new; 1354 unsigned int old, new;
1271 1355
1272 mutex_lock(&io_mutex); 1356 mutex_lock(&io_mutex);
1273 old = snd_soc_read(codec, reg); 1357 old = snd_soc_read(codec, reg);
@@ -1294,10 +1378,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1294 * Returns 1 for change else 0. 1378 * Returns 1 for change else 0.
1295 */ 1379 */
1296int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, 1380int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1297 unsigned short mask, unsigned short value) 1381 unsigned int mask, unsigned int value)
1298{ 1382{
1299 int change; 1383 int change;
1300 unsigned short old, new; 1384 unsigned int old, new;
1301 1385
1302 mutex_lock(&io_mutex); 1386 mutex_lock(&io_mutex);
1303 old = snd_soc_read(codec, reg); 1387 old = snd_soc_read(codec, reg);
@@ -1381,8 +1465,11 @@ int snd_soc_init_card(struct snd_soc_device *socdev)
1381 continue; 1465 continue;
1382 } 1466 }
1383 } 1467 }
1384 if (card->dai_link[i].codec_dai->ac97_control) 1468 if (card->dai_link[i].codec_dai->ac97_control) {
1385 ac97 = 1; 1469 ac97 = 1;
1470 snd_ac97_dev_add_pdata(codec->ac97,
1471 card->dai_link[i].cpu_dai->ac97_pdata);
1472 }
1386 } 1473 }
1387 snprintf(codec->card->shortname, sizeof(codec->card->shortname), 1474 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1388 "%s", card->name); 1475 "%s", card->name);
@@ -1586,7 +1673,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1586{ 1673{
1587 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1674 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1588 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1675 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1589 unsigned short val, bitmask; 1676 unsigned int val, bitmask;
1590 1677
1591 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1678 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1592 ; 1679 ;
@@ -1615,8 +1702,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1615{ 1702{
1616 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1703 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1617 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1704 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1618 unsigned short val; 1705 unsigned int val;
1619 unsigned short mask, bitmask; 1706 unsigned int mask, bitmask;
1620 1707
1621 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1708 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1622 ; 1709 ;
@@ -1652,7 +1739,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
1652{ 1739{
1653 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1740 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1654 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1741 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1655 unsigned short reg_val, val, mux; 1742 unsigned int reg_val, val, mux;
1656 1743
1657 reg_val = snd_soc_read(codec, e->reg); 1744 reg_val = snd_soc_read(codec, e->reg);
1658 val = (reg_val >> e->shift_l) & e->mask; 1745 val = (reg_val >> e->shift_l) & e->mask;
@@ -1691,8 +1778,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
1691{ 1778{
1692 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1779 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1693 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1780 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1694 unsigned short val; 1781 unsigned int val;
1695 unsigned short mask; 1782 unsigned int mask;
1696 1783
1697 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1784 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1698 return -EINVAL; 1785 return -EINVAL;
@@ -1852,7 +1939,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1852 int max = mc->max; 1939 int max = mc->max;
1853 unsigned int mask = (1 << fls(max)) - 1; 1940 unsigned int mask = (1 << fls(max)) - 1;
1854 unsigned int invert = mc->invert; 1941 unsigned int invert = mc->invert;
1855 unsigned short val, val2, val_mask; 1942 unsigned int val, val2, val_mask;
1856 1943
1857 val = (ucontrol->value.integer.value[0] & mask); 1944 val = (ucontrol->value.integer.value[0] & mask);
1858 if (invert) 1945 if (invert)
@@ -1918,7 +2005,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
1918 unsigned int reg2 = mc->rreg; 2005 unsigned int reg2 = mc->rreg;
1919 unsigned int shift = mc->shift; 2006 unsigned int shift = mc->shift;
1920 int max = mc->max; 2007 int max = mc->max;
1921 unsigned int mask = (1<<fls(max))-1; 2008 unsigned int mask = (1 << fls(max)) - 1;
1922 unsigned int invert = mc->invert; 2009 unsigned int invert = mc->invert;
1923 2010
1924 ucontrol->value.integer.value[0] = 2011 ucontrol->value.integer.value[0] =
@@ -1958,7 +2045,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1958 unsigned int mask = (1 << fls(max)) - 1; 2045 unsigned int mask = (1 << fls(max)) - 1;
1959 unsigned int invert = mc->invert; 2046 unsigned int invert = mc->invert;
1960 int err; 2047 int err;
1961 unsigned short val, val2, val_mask; 2048 unsigned int val, val2, val_mask;
1962 2049
1963 val_mask = mask << shift; 2050 val_mask = mask << shift;
1964 val = (ucontrol->value.integer.value[0] & mask); 2051 val = (ucontrol->value.integer.value[0] & mask);
@@ -2050,7 +2137,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2050 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2137 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2051 unsigned int reg = mc->reg; 2138 unsigned int reg = mc->reg;
2052 int min = mc->min; 2139 int min = mc->min;
2053 unsigned short val; 2140 unsigned int val;
2054 2141
2055 val = (ucontrol->value.integer.value[0]+min) & 0xff; 2142 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2056 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; 2143 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 21c69074aa17..c68c204a48ad 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -52,19 +52,37 @@
52 52
53/* dapm power sequences - make this per codec in the future */ 53/* dapm power sequences - make this per codec in the future */
54static int dapm_up_seq[] = { 54static int dapm_up_seq[] = {
55 snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias, 55 [snd_soc_dapm_pre] = 0,
56 snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, 56 [snd_soc_dapm_supply] = 1,
57 snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, 57 [snd_soc_dapm_micbias] = 2,
58 snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 58 [snd_soc_dapm_mic] = 3,
59 snd_soc_dapm_post 59 [snd_soc_dapm_mux] = 4,
60 [snd_soc_dapm_value_mux] = 4,
61 [snd_soc_dapm_dac] = 5,
62 [snd_soc_dapm_mixer] = 6,
63 [snd_soc_dapm_mixer_named_ctl] = 6,
64 [snd_soc_dapm_pga] = 7,
65 [snd_soc_dapm_adc] = 8,
66 [snd_soc_dapm_hp] = 9,
67 [snd_soc_dapm_spk] = 10,
68 [snd_soc_dapm_post] = 11,
60}; 69};
61 70
62static int dapm_down_seq[] = { 71static int dapm_down_seq[] = {
63 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 72 [snd_soc_dapm_pre] = 0,
64 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, 73 [snd_soc_dapm_adc] = 1,
65 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, 74 [snd_soc_dapm_hp] = 2,
66 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply, 75 [snd_soc_dapm_spk] = 3,
67 snd_soc_dapm_post 76 [snd_soc_dapm_pga] = 4,
77 [snd_soc_dapm_mixer_named_ctl] = 5,
78 [snd_soc_dapm_mixer] = 5,
79 [snd_soc_dapm_dac] = 6,
80 [snd_soc_dapm_mic] = 7,
81 [snd_soc_dapm_micbias] = 8,
82 [snd_soc_dapm_mux] = 9,
83 [snd_soc_dapm_value_mux] = 9,
84 [snd_soc_dapm_supply] = 10,
85 [snd_soc_dapm_post] = 11,
68}; 86};
69 87
70static void pop_wait(u32 pop_time) 88static void pop_wait(u32 pop_time)
@@ -268,7 +286,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec,
268static int dapm_update_bits(struct snd_soc_dapm_widget *widget) 286static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
269{ 287{
270 int change, power; 288 int change, power;
271 unsigned short old, new; 289 unsigned int old, new;
272 struct snd_soc_codec *codec = widget->codec; 290 struct snd_soc_codec *codec = widget->codec;
273 291
274 /* check for valid widgets */ 292 /* check for valid widgets */
@@ -689,53 +707,211 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
689 return power; 707 return power;
690} 708}
691 709
692/* 710static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
693 * Scan a single DAPM widget for a complete audio path and update the 711 struct snd_soc_dapm_widget *b,
694 * power status appropriately. 712 int sort[])
695 */
696static int dapm_power_widget(struct snd_soc_codec *codec, int event,
697 struct snd_soc_dapm_widget *w)
698{ 713{
699 int ret; 714 if (sort[a->id] != sort[b->id])
715 return sort[a->id] - sort[b->id];
716 if (a->reg != b->reg)
717 return a->reg - b->reg;
700 718
701 switch (w->id) { 719 return 0;
702 case snd_soc_dapm_pre: 720}
703 if (!w->event)
704 return 0;
705 721
706 if (event == SND_SOC_DAPM_STREAM_START) { 722/* Insert a widget in order into a DAPM power sequence. */
707 ret = w->event(w, 723static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
708 NULL, SND_SOC_DAPM_PRE_PMU); 724 struct list_head *list,
725 int sort[])
726{
727 struct snd_soc_dapm_widget *w;
728
729 list_for_each_entry(w, list, power_list)
730 if (dapm_seq_compare(new_widget, w, sort) < 0) {
731 list_add_tail(&new_widget->power_list, &w->power_list);
732 return;
733 }
734
735 list_add_tail(&new_widget->power_list, list);
736}
737
738/* Apply the coalesced changes from a DAPM sequence */
739static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
740 struct list_head *pending)
741{
742 struct snd_soc_dapm_widget *w;
743 int reg, power, ret;
744 unsigned int value = 0;
745 unsigned int mask = 0;
746 unsigned int cur_mask;
747
748 reg = list_first_entry(pending, struct snd_soc_dapm_widget,
749 power_list)->reg;
750
751 list_for_each_entry(w, pending, power_list) {
752 cur_mask = 1 << w->shift;
753 BUG_ON(reg != w->reg);
754
755 if (w->invert)
756 power = !w->power;
757 else
758 power = w->power;
759
760 mask |= cur_mask;
761 if (power)
762 value |= cur_mask;
763
764 pop_dbg(codec->pop_time,
765 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
766 w->name, reg, value, mask);
767
768 /* power up pre event */
769 if (w->power && w->event &&
770 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
771 pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n",
772 w->name);
773 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
709 if (ret < 0) 774 if (ret < 0)
710 return ret; 775 pr_err("%s: pre event failed: %d\n",
711 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 776 w->name, ret);
712 ret = w->event(w, 777 }
713 NULL, SND_SOC_DAPM_PRE_PMD); 778
779 /* power down pre event */
780 if (!w->power && w->event &&
781 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
782 pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n",
783 w->name);
784 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
714 if (ret < 0) 785 if (ret < 0)
715 return ret; 786 pr_err("%s: pre event failed: %d\n",
787 w->name, ret);
716 } 788 }
717 return 0;
718 789
719 case snd_soc_dapm_post: 790 /* Lower PGA volume to reduce pops */
720 if (!w->event) 791 if (w->id == snd_soc_dapm_pga && !w->power)
721 return 0; 792 dapm_set_pga(w, w->power);
793 }
722 794
723 if (event == SND_SOC_DAPM_STREAM_START) { 795 if (reg >= 0) {
796 pop_dbg(codec->pop_time,
797 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
798 value, mask, reg, codec->pop_time);
799 pop_wait(codec->pop_time);
800 snd_soc_update_bits(codec, reg, mask, value);
801 }
802
803 list_for_each_entry(w, pending, power_list) {
804 /* Raise PGA volume to reduce pops */
805 if (w->id == snd_soc_dapm_pga && w->power)
806 dapm_set_pga(w, w->power);
807
808 /* power up post event */
809 if (w->power && w->event &&
810 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
811 pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n",
812 w->name);
724 ret = w->event(w, 813 ret = w->event(w,
725 NULL, SND_SOC_DAPM_POST_PMU); 814 NULL, SND_SOC_DAPM_POST_PMU);
726 if (ret < 0) 815 if (ret < 0)
727 return ret; 816 pr_err("%s: post event failed: %d\n",
728 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 817 w->name, ret);
729 ret = w->event(w, 818 }
730 NULL, SND_SOC_DAPM_POST_PMD); 819
820 /* power down post event */
821 if (!w->power && w->event &&
822 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
823 pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n",
824 w->name);
825 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
731 if (ret < 0) 826 if (ret < 0)
732 return ret; 827 pr_err("%s: post event failed: %d\n",
828 w->name, ret);
733 } 829 }
734 return 0; 830 }
831}
735 832
736 default: 833/* Apply a DAPM power sequence.
737 return dapm_generic_apply_power(w); 834 *
835 * We walk over a pre-sorted list of widgets to apply power to. In
836 * order to minimise the number of writes to the device required
837 * multiple widgets will be updated in a single write where possible.
838 * Currently anything that requires more than a single write is not
839 * handled.
840 */
841static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
842 int event, int sort[])
843{
844 struct snd_soc_dapm_widget *w, *n;
845 LIST_HEAD(pending);
846 int cur_sort = -1;
847 int cur_reg = SND_SOC_NOPM;
848 int ret;
849
850 list_for_each_entry_safe(w, n, list, power_list) {
851 ret = 0;
852
853 /* Do we need to apply any queued changes? */
854 if (sort[w->id] != cur_sort || w->reg != cur_reg) {
855 if (!list_empty(&pending))
856 dapm_seq_run_coalesced(codec, &pending);
857
858 INIT_LIST_HEAD(&pending);
859 cur_sort = -1;
860 cur_reg = SND_SOC_NOPM;
861 }
862
863 switch (w->id) {
864 case snd_soc_dapm_pre:
865 if (!w->event)
866 list_for_each_entry_safe_continue(w, n, list,
867 power_list);
868
869 if (event == SND_SOC_DAPM_STREAM_START)
870 ret = w->event(w,
871 NULL, SND_SOC_DAPM_PRE_PMU);
872 else if (event == SND_SOC_DAPM_STREAM_STOP)
873 ret = w->event(w,
874 NULL, SND_SOC_DAPM_PRE_PMD);
875 break;
876
877 case snd_soc_dapm_post:
878 if (!w->event)
879 list_for_each_entry_safe_continue(w, n, list,
880 power_list);
881
882 if (event == SND_SOC_DAPM_STREAM_START)
883 ret = w->event(w,
884 NULL, SND_SOC_DAPM_POST_PMU);
885 else if (event == SND_SOC_DAPM_STREAM_STOP)
886 ret = w->event(w,
887 NULL, SND_SOC_DAPM_POST_PMD);
888 break;
889
890 case snd_soc_dapm_input:
891 case snd_soc_dapm_output:
892 case snd_soc_dapm_hp:
893 case snd_soc_dapm_mic:
894 case snd_soc_dapm_line:
895 case snd_soc_dapm_spk:
896 /* No register support currently */
897 ret = dapm_generic_apply_power(w);
898 break;
899
900 default:
901 /* Queue it up for application */
902 cur_sort = sort[w->id];
903 cur_reg = w->reg;
904 list_move(&w->power_list, &pending);
905 break;
906 }
907
908 if (ret < 0)
909 pr_err("Failed to apply widget power: %d\n",
910 ret);
738 } 911 }
912
913 if (!list_empty(&pending))
914 dapm_seq_run_coalesced(codec, &pending);
739} 915}
740 916
741/* 917/*
@@ -751,23 +927,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
751{ 927{
752 struct snd_soc_device *socdev = codec->socdev; 928 struct snd_soc_device *socdev = codec->socdev;
753 struct snd_soc_dapm_widget *w; 929 struct snd_soc_dapm_widget *w;
930 LIST_HEAD(up_list);
931 LIST_HEAD(down_list);
754 int ret = 0; 932 int ret = 0;
755 int i, power; 933 int power;
756 int sys_power = 0; 934 int sys_power = 0;
757 935
758 INIT_LIST_HEAD(&codec->up_list);
759 INIT_LIST_HEAD(&codec->down_list);
760
761 /* Check which widgets we need to power and store them in 936 /* Check which widgets we need to power and store them in
762 * lists indicating if they should be powered up or down. 937 * lists indicating if they should be powered up or down.
763 */ 938 */
764 list_for_each_entry(w, &codec->dapm_widgets, list) { 939 list_for_each_entry(w, &codec->dapm_widgets, list) {
765 switch (w->id) { 940 switch (w->id) {
766 case snd_soc_dapm_pre: 941 case snd_soc_dapm_pre:
767 list_add_tail(&codec->down_list, &w->power_list); 942 dapm_seq_insert(w, &down_list, dapm_down_seq);
768 break; 943 break;
769 case snd_soc_dapm_post: 944 case snd_soc_dapm_post:
770 list_add_tail(&codec->up_list, &w->power_list); 945 dapm_seq_insert(w, &up_list, dapm_up_seq);
771 break; 946 break;
772 947
773 default: 948 default:
@@ -782,10 +957,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
782 continue; 957 continue;
783 958
784 if (power) 959 if (power)
785 list_add_tail(&w->power_list, &codec->up_list); 960 dapm_seq_insert(w, &up_list, dapm_up_seq);
786 else 961 else
787 list_add_tail(&w->power_list, 962 dapm_seq_insert(w, &down_list, dapm_down_seq);
788 &codec->down_list);
789 963
790 w->power = power; 964 w->power = power;
791 break; 965 break;
@@ -802,32 +976,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
802 } 976 }
803 977
804 /* Power down widgets first; try to avoid amplifying pops. */ 978 /* Power down widgets first; try to avoid amplifying pops. */
805 for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { 979 dapm_seq_run(codec, &down_list, event, dapm_down_seq);
806 list_for_each_entry(w, &codec->down_list, power_list) {
807 /* is widget in stream order */
808 if (w->id != dapm_down_seq[i])
809 continue;
810
811 ret = dapm_power_widget(codec, event, w);
812 if (ret != 0)
813 pr_err("Failed to power down %s: %d\n",
814 w->name, ret);
815 }
816 }
817 980
818 /* Now power up. */ 981 /* Now power up. */
819 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) { 982 dapm_seq_run(codec, &up_list, event, dapm_up_seq);
820 list_for_each_entry(w, &codec->up_list, power_list) {
821 /* is widget in stream order */
822 if (w->id != dapm_up_seq[i])
823 continue;
824
825 ret = dapm_power_widget(codec, event, w);
826 if (ret != 0)
827 pr_err("Failed to power up %s: %d\n",
828 w->name, ret);
829 }
830 }
831 983
832 /* If we just powered the last thing off drop to standby bias */ 984 /* If we just powered the last thing off drop to standby bias */
833 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { 985 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
@@ -845,6 +997,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
845 pr_err("Failed to apply active bias: %d\n", ret); 997 pr_err("Failed to apply active bias: %d\n", ret);
846 } 998 }
847 999
1000 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n",
1001 codec->pop_time);
1002
848 return 0; 1003 return 0;
849} 1004}
850 1005
@@ -1138,8 +1293,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1138 if (wsink->id == snd_soc_dapm_input) { 1293 if (wsink->id == snd_soc_dapm_input) {
1139 if (wsource->id == snd_soc_dapm_micbias || 1294 if (wsource->id == snd_soc_dapm_micbias ||
1140 wsource->id == snd_soc_dapm_mic || 1295 wsource->id == snd_soc_dapm_mic ||
1141 wsink->id == snd_soc_dapm_line || 1296 wsource->id == snd_soc_dapm_line ||
1142 wsink->id == snd_soc_dapm_output) 1297 wsource->id == snd_soc_dapm_output)
1143 wsink->ext = 1; 1298 wsink->ext = 1;
1144 } 1299 }
1145 if (wsource->id == snd_soc_dapm_output) { 1300 if (wsource->id == snd_soc_dapm_output) {
@@ -1372,7 +1527,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1372 int max = mc->max; 1527 int max = mc->max;
1373 unsigned int mask = (1 << fls(max)) - 1; 1528 unsigned int mask = (1 << fls(max)) - 1;
1374 unsigned int invert = mc->invert; 1529 unsigned int invert = mc->invert;
1375 unsigned short val, val2, val_mask; 1530 unsigned int val, val2, val_mask;
1376 int ret; 1531 int ret;
1377 1532
1378 val = (ucontrol->value.integer.value[0] & mask); 1533 val = (ucontrol->value.integer.value[0] & mask);
@@ -1436,7 +1591,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1436{ 1591{
1437 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1592 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1438 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1593 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1439 unsigned short val, bitmask; 1594 unsigned int val, bitmask;
1440 1595
1441 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1596 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1442 ; 1597 ;
@@ -1464,8 +1619,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1464{ 1619{
1465 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1620 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1466 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1621 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1467 unsigned short val, mux; 1622 unsigned int val, mux;
1468 unsigned short mask, bitmask; 1623 unsigned int mask, bitmask;
1469 int ret = 0; 1624 int ret = 0;
1470 1625
1471 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1626 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
@@ -1523,7 +1678,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
1523{ 1678{
1524 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1679 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1525 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1680 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1526 unsigned short reg_val, val, mux; 1681 unsigned int reg_val, val, mux;
1527 1682
1528 reg_val = snd_soc_read(widget->codec, e->reg); 1683 reg_val = snd_soc_read(widget->codec, e->reg);
1529 val = (reg_val >> e->shift_l) & e->mask; 1684 val = (reg_val >> e->shift_l) & e->mask;
@@ -1563,8 +1718,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1563{ 1718{
1564 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1719 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1565 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1720 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1566 unsigned short val, mux; 1721 unsigned int val, mux;
1567 unsigned short mask; 1722 unsigned int mask;
1568 int ret = 0; 1723 int ret = 0;
1569 1724
1570 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1725 if (ucontrol->value.enumerated.item[0] > e->max - 1)
@@ -1880,6 +2035,36 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
1880} 2035}
1881EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 2036EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1882 2037
2038/*
2039 * snd_soc_dapm_shutdown - callback for system shutdown
2040 */
2041void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2042{
2043 struct snd_soc_codec *codec = socdev->card->codec;
2044 struct snd_soc_dapm_widget *w;
2045 LIST_HEAD(down_list);
2046 int powerdown = 0;
2047
2048 list_for_each_entry(w, &codec->dapm_widgets, list) {
2049 if (w->power) {
2050 dapm_seq_insert(w, &down_list, dapm_down_seq);
2051 w->power = 0;
2052 powerdown = 1;
2053 }
2054 }
2055
2056 /* If there were no widgets to power down we're already in
2057 * standby.
2058 */
2059 if (powerdown) {
2060 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE);
2061 dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
2062 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY);
2063 }
2064
2065 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
2066}
2067
1883/* Module information */ 2068/* Module information */
1884MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); 2069MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1885MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 2070MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 28346fb2e70c..1d455ab79490 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -73,14 +73,15 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
73 oldstatus = jack->status; 73 oldstatus = jack->status;
74 74
75 jack->status &= ~mask; 75 jack->status &= ~mask;
76 jack->status |= status; 76 jack->status |= status & mask;
77 77
78 /* The DAPM sync is expensive enough to be worth skipping */ 78 /* The DAPM sync is expensive enough to be worth skipping.
79 if (jack->status == oldstatus) 79 * However, empty mask means pin synchronization is desired. */
80 if (mask && (jack->status == oldstatus))
80 goto out; 81 goto out;
81 82
82 list_for_each_entry(pin, &jack->pins, list) { 83 list_for_each_entry(pin, &jack->pins, list) {
83 enable = pin->mask & status; 84 enable = pin->mask & jack->status;
84 85
85 if (pin->invert) 86 if (pin->invert)
86 enable = !enable; 87 enable = !enable;
@@ -220,6 +221,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
220 if (ret) 221 if (ret)
221 goto err; 222 goto err;
222 223
224 INIT_WORK(&gpios[i].work, gpio_work);
225 gpios[i].jack = jack;
226
223 ret = request_irq(gpio_to_irq(gpios[i].gpio), 227 ret = request_irq(gpio_to_irq(gpios[i].gpio),
224 gpio_handler, 228 gpio_handler,
225 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 229 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
@@ -228,8 +232,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
228 if (ret) 232 if (ret)
229 goto err; 233 goto err;
230 234
231 INIT_WORK(&gpios[i].work, gpio_work); 235#ifdef CONFIG_GPIO_SYSFS
232 gpios[i].jack = jack; 236 /* Expose GPIO value over sysfs for diagnostic purposes */
237 gpio_export(gpios[i].gpio, false);
238#endif
239
240 /* Update initial jack status */
241 snd_soc_jack_gpio_detect(&gpios[i]);
233 } 242 }
234 243
235 return 0; 244 return 0;
@@ -258,6 +267,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
258 int i; 267 int i;
259 268
260 for (i = 0; i < count; i++) { 269 for (i = 0; i < count; i++) {
270#ifdef CONFIG_GPIO_SYSFS
271 gpio_unexport(gpios[i].gpio);
272#endif
261 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); 273 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
262 gpio_free(gpios[i].gpio); 274 gpio_free(gpios[i].gpio);
263 gpios[i].jack = NULL; 275 gpios[i].jack = NULL;
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 938a58a5a244..efed64b8b026 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -297,15 +297,17 @@ static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
297static bool filter(struct dma_chan *chan, void *param) 297static bool filter(struct dma_chan *chan, void *param)
298{ 298{
299 struct txx9aclc_dmadata *dmadata = param; 299 struct txx9aclc_dmadata *dmadata = param;
300 char devname[20 + 2]; /* FIXME: old BUS_ID_SIZE + 2 */ 300 char *devname;
301 bool found = false;
301 302
302 snprintf(devname, sizeof(devname), "%s.%d", dmadata->dma_res->name, 303 devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name,
303 (int)dmadata->dma_res->start); 304 (int)dmadata->dma_res->start);
304 if (strcmp(dev_name(chan->device->dev), devname) == 0) { 305 if (strcmp(dev_name(chan->device->dev), devname) == 0) {
305 chan->private = &dmadata->dma_slave; 306 chan->private = &dmadata->dma_slave;
306 return true; 307 found = true;
307 } 308 }
308 return false; 309 kfree(devname);
310 return found;
309} 311}
310 312
311static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, 313static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,