aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/sn95031.c
diff options
context:
space:
mode:
authorHarsha Priya <priya.harsha@intel.com>2011-01-28 11:56:53 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-01-31 07:10:00 -0500
commitfd94eeef06ed4abc08f58e42f46341d0bc4f7793 (patch)
tree37b5bdcef9d6e7c132675f0761f731a61eda7b15 /sound/soc/codecs/sn95031.c
parent1166f985d3b6b4ef8a48a13f56520870d86085c3 (diff)
ASoC: sn95031: add capture support
This patch adds the support for capture path in sn95031 codec. This codec supports upto 6DMICs, 2 AMICs and Linein. The linein and AMICs are connected through a MUX to ADC. The TX paths can be assigned to any of the ADCs or DMICs. Signed-off-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Harsha Priya <priya.harsha@intel.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/sn95031.c')
-rw-r--r--sound/soc/codecs/sn95031.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 593632cf791d..40e285df9ae5 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -33,6 +33,7 @@
33#include <sound/soc.h> 33#include <sound/soc.h>
34#include <sound/soc-dapm.h> 34#include <sound/soc-dapm.h>
35#include <sound/initval.h> 35#include <sound/initval.h>
36#include <sound/tlv.h>
36#include "sn95031.h" 37#include "sn95031.h"
37 38
38#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100) 39#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
@@ -145,6 +146,129 @@ static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
145 return 0; 146 return 0;
146} 147}
147 148
149static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w,
150 struct snd_kcontrol *k, int event)
151{
152 unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
153
154 if (SND_SOC_DAPM_EVENT_ON(event)) {
155 ldo = BIT(5)|BIT(4);
156 clk_dir = BIT(0);
157 data_dir = BIT(7);
158 }
159 /* program DMIC LDO, clock and set clock */
160 snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
161 snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir);
162 snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir);
163 return 0;
164}
165
166static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w,
167 struct snd_kcontrol *k, int event)
168{
169 unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
170
171 if (SND_SOC_DAPM_EVENT_ON(event)) {
172 ldo = BIT(5)|BIT(4);
173 clk_dir = BIT(2);
174 data_dir = BIT(1);
175 }
176 /* program DMIC LDO, clock and set clock */
177 snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
178 snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir);
179 snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir);
180 return 0;
181}
182
183static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w,
184 struct snd_kcontrol *k, int event)
185{
186 unsigned int ldo = 0;
187
188 if (SND_SOC_DAPM_EVENT_ON(event))
189 ldo = BIT(7)|BIT(6);
190
191 /* program DMIC LDO */
192 snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo);
193 return 0;
194}
195
196/* mux controls */
197static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" };
198
199static const struct soc_enum sn95031_micl_enum =
200 SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts);
201
202static const struct snd_kcontrol_new sn95031_micl_mux_control =
203 SOC_DAPM_ENUM("Route", sn95031_micl_enum);
204
205static const struct soc_enum sn95031_micr_enum =
206 SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts);
207
208static const struct snd_kcontrol_new sn95031_micr_mux_control =
209 SOC_DAPM_ENUM("Route", sn95031_micr_enum);
210
211static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3",
212 "DMIC4", "DMIC5", "DMIC6",
213 "ADC Left", "ADC Right" };
214
215static const struct soc_enum sn95031_input1_enum =
216 SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts);
217
218static const struct snd_kcontrol_new sn95031_input1_mux_control =
219 SOC_DAPM_ENUM("Route", sn95031_input1_enum);
220
221static const struct soc_enum sn95031_input2_enum =
222 SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts);
223
224static const struct snd_kcontrol_new sn95031_input2_mux_control =
225 SOC_DAPM_ENUM("Route", sn95031_input2_enum);
226
227static const struct soc_enum sn95031_input3_enum =
228 SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts);
229
230static const struct snd_kcontrol_new sn95031_input3_mux_control =
231 SOC_DAPM_ENUM("Route", sn95031_input3_enum);
232
233static const struct soc_enum sn95031_input4_enum =
234 SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts);
235
236static const struct snd_kcontrol_new sn95031_input4_mux_control =
237 SOC_DAPM_ENUM("Route", sn95031_input4_enum);
238
239/* capture path controls */
240
241static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"};
242
243/* 0dB to 30dB in 10dB steps */
244static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 30);
245
246static const struct soc_enum sn95031_micmode1_enum =
247 SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text);
248static const struct soc_enum sn95031_micmode2_enum =
249 SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text);
250
251static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"};
252
253static const struct soc_enum sn95031_dmic12_cfg_enum =
254 SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text);
255static const struct soc_enum sn95031_dmic34_cfg_enum =
256 SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text);
257static const struct soc_enum sn95031_dmic56_cfg_enum =
258 SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text);
259
260static const struct snd_kcontrol_new sn95031_snd_controls[] = {
261 SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum),
262 SOC_ENUM("Mic2Mode Capture Route", sn95031_micmode2_enum),
263 SOC_ENUM("DMIC12 Capture Route", sn95031_dmic12_cfg_enum),
264 SOC_ENUM("DMIC34 Capture Route", sn95031_dmic34_cfg_enum),
265 SOC_ENUM("DMIC56 Capture Route", sn95031_dmic56_cfg_enum),
266 SOC_SINGLE_TLV("Mic1 Capture Volume", SN95031_MICAMP1,
267 2, 4, 0, mic_tlv),
268 SOC_SINGLE_TLV("Mic2 Capture Volume", SN95031_MICAMP2,
269 2, 4, 0, mic_tlv),
270};
271
148/* DAPM widgets */ 272/* DAPM widgets */
149static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { 273static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
150 274
@@ -159,6 +283,36 @@ static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
159 SND_SOC_DAPM_OUTPUT("VIB1OUT"), 283 SND_SOC_DAPM_OUTPUT("VIB1OUT"),
160 SND_SOC_DAPM_OUTPUT("VIB2OUT"), 284 SND_SOC_DAPM_OUTPUT("VIB2OUT"),
161 285
286 SND_SOC_DAPM_INPUT("AMIC1"), /* headset mic */
287 SND_SOC_DAPM_INPUT("AMIC2"),
288 SND_SOC_DAPM_INPUT("DMIC1"),
289 SND_SOC_DAPM_INPUT("DMIC2"),
290 SND_SOC_DAPM_INPUT("DMIC3"),
291 SND_SOC_DAPM_INPUT("DMIC4"),
292 SND_SOC_DAPM_INPUT("DMIC5"),
293 SND_SOC_DAPM_INPUT("DMIC6"),
294 SND_SOC_DAPM_INPUT("LINEINL"),
295 SND_SOC_DAPM_INPUT("LINEINR"),
296
297 SND_SOC_DAPM_MICBIAS("AMIC1Bias", SN95031_MICBIAS, 2, 0),
298 SND_SOC_DAPM_MICBIAS("AMIC2Bias", SN95031_MICBIAS, 3, 0),
299 SND_SOC_DAPM_MICBIAS("DMIC12Bias", SN95031_DMICMUX, 3, 0),
300 SND_SOC_DAPM_MICBIAS("DMIC34Bias", SN95031_DMICMUX, 4, 0),
301 SND_SOC_DAPM_MICBIAS("DMIC56Bias", SN95031_DMICMUX, 5, 0),
302
303 SND_SOC_DAPM_SUPPLY("DMIC12supply", SN95031_DMICLK, 0, 0,
304 sn95031_dmic12_event,
305 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
306 SND_SOC_DAPM_SUPPLY("DMIC34supply", SN95031_DMICLK, 1, 0,
307 sn95031_dmic34_event,
308 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
309 SND_SOC_DAPM_SUPPLY("DMIC56supply", SN95031_DMICLK, 2, 0,
310 sn95031_dmic56_event,
311 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
312
313 SND_SOC_DAPM_AIF_OUT("PCM_Out", "Capture", 0,
314 SND_SOC_NOPM, 0, 0),
315
162 SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0, 316 SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0,
163 sn95031_vhs_event, 317 sn95031_vhs_event,
164 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 318 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -209,6 +363,40 @@ static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
209 SN95031_VIB1C5, 1, 0), 363 SN95031_VIB1C5, 1, 0),
210 SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2", 364 SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2",
211 SN95031_VIB2C5, 1, 0), 365 SN95031_VIB2C5, 1, 0),
366
367 /* capture widgets */
368 SND_SOC_DAPM_PGA("LineIn Enable Left", SN95031_MICAMP1,
369 7, 0, NULL, 0),
370 SND_SOC_DAPM_PGA("LineIn Enable Right", SN95031_MICAMP2,
371 7, 0, NULL, 0),
372
373 SND_SOC_DAPM_PGA("MIC1 Enable", SN95031_MICAMP1, 0, 0, NULL, 0),
374 SND_SOC_DAPM_PGA("MIC2 Enable", SN95031_MICAMP2, 0, 0, NULL, 0),
375 SND_SOC_DAPM_PGA("TX1 Enable", SN95031_AUDIOTXEN, 2, 0, NULL, 0),
376 SND_SOC_DAPM_PGA("TX2 Enable", SN95031_AUDIOTXEN, 3, 0, NULL, 0),
377 SND_SOC_DAPM_PGA("TX3 Enable", SN95031_AUDIOTXEN, 4, 0, NULL, 0),
378 SND_SOC_DAPM_PGA("TX4 Enable", SN95031_AUDIOTXEN, 5, 0, NULL, 0),
379
380 /* ADC have null stream as they will be turned ON by TX path */
381 SND_SOC_DAPM_ADC("ADC Left", NULL,
382 SN95031_ADCCONFIG, 0, 0),
383 SND_SOC_DAPM_ADC("ADC Right", NULL,
384 SN95031_ADCCONFIG, 2, 0),
385
386 SND_SOC_DAPM_MUX("Mic_InputL Capture Route",
387 SND_SOC_NOPM, 0, 0, &sn95031_micl_mux_control),
388 SND_SOC_DAPM_MUX("Mic_InputR Capture Route",
389 SND_SOC_NOPM, 0, 0, &sn95031_micr_mux_control),
390
391 SND_SOC_DAPM_MUX("Txpath1 Capture Route",
392 SND_SOC_NOPM, 0, 0, &sn95031_input1_mux_control),
393 SND_SOC_DAPM_MUX("Txpath2 Capture Route",
394 SND_SOC_NOPM, 0, 0, &sn95031_input2_mux_control),
395 SND_SOC_DAPM_MUX("Txpath3 Capture Route",
396 SND_SOC_NOPM, 0, 0, &sn95031_input3_mux_control),
397 SND_SOC_DAPM_MUX("Txpath4 Capture Route",
398 SND_SOC_NOPM, 0, 0, &sn95031_input4_mux_control),
399
212}; 400};
213 401
214static const struct snd_soc_dapm_route sn95031_audio_map[] = { 402static const struct snd_soc_dapm_route sn95031_audio_map[] = {
@@ -250,6 +438,87 @@ static const struct snd_soc_dapm_route sn95031_audio_map[] = {
250 { "Lineout Right Playback", NULL, "Headset Right Filter"}, 438 { "Lineout Right Playback", NULL, "Headset Right Filter"},
251 { "Lineout Right Playback", NULL, "Speaker Right Filter"}, 439 { "Lineout Right Playback", NULL, "Speaker Right Filter"},
252 { "Lineout Right Playback", NULL, "Vibra2 DAC"}, 440 { "Lineout Right Playback", NULL, "Vibra2 DAC"},
441
442 /* Headset (AMIC1) mic */
443 { "AMIC1Bias", NULL, "AMIC1"},
444 { "MIC1 Enable", NULL, "AMIC1Bias"},
445 { "Mic_InputL Capture Route", "AMIC", "MIC1 Enable"},
446
447 /* AMIC2 */
448 { "AMIC2Bias", NULL, "AMIC2"},
449 { "MIC2 Enable", NULL, "AMIC2Bias"},
450 { "Mic_InputR Capture Route", "AMIC", "MIC2 Enable"},
451
452
453 /* Linein */
454 { "LineIn Enable Left", NULL, "LINEINL"},
455 { "LineIn Enable Right", NULL, "LINEINR"},
456 { "Mic_InputL Capture Route", "LineIn", "LineIn Enable Left"},
457 { "Mic_InputR Capture Route", "LineIn", "LineIn Enable Right"},
458
459 /* ADC connection */
460 { "ADC Left", NULL, "Mic_InputL Capture Route"},
461 { "ADC Right", NULL, "Mic_InputR Capture Route"},
462
463 /*DMIC connections */
464 { "DMIC1", NULL, "DMIC12supply"},
465 { "DMIC2", NULL, "DMIC12supply"},
466 { "DMIC3", NULL, "DMIC34supply"},
467 { "DMIC4", NULL, "DMIC34supply"},
468 { "DMIC5", NULL, "DMIC56supply"},
469 { "DMIC6", NULL, "DMIC56supply"},
470
471 { "DMIC12Bias", NULL, "DMIC1"},
472 { "DMIC12Bias", NULL, "DMIC2"},
473 { "DMIC34Bias", NULL, "DMIC3"},
474 { "DMIC34Bias", NULL, "DMIC4"},
475 { "DMIC56Bias", NULL, "DMIC5"},
476 { "DMIC56Bias", NULL, "DMIC6"},
477
478 /*TX path inputs*/
479 { "Txpath1 Capture Route", "ADC Left", "ADC Left"},
480 { "Txpath2 Capture Route", "ADC Left", "ADC Left"},
481 { "Txpath3 Capture Route", "ADC Left", "ADC Left"},
482 { "Txpath4 Capture Route", "ADC Left", "ADC Left"},
483 { "Txpath1 Capture Route", "ADC Right", "ADC Right"},
484 { "Txpath2 Capture Route", "ADC Right", "ADC Right"},
485 { "Txpath3 Capture Route", "ADC Right", "ADC Right"},
486 { "Txpath4 Capture Route", "ADC Right", "ADC Right"},
487 { "Txpath1 Capture Route", NULL, "DMIC1"},
488 { "Txpath2 Capture Route", NULL, "DMIC1"},
489 { "Txpath3 Capture Route", NULL, "DMIC1"},
490 { "Txpath4 Capture Route", NULL, "DMIC1"},
491 { "Txpath1 Capture Route", NULL, "DMIC2"},
492 { "Txpath2 Capture Route", NULL, "DMIC2"},
493 { "Txpath3 Capture Route", NULL, "DMIC2"},
494 { "Txpath4 Capture Route", NULL, "DMIC2"},
495 { "Txpath1 Capture Route", NULL, "DMIC3"},
496 { "Txpath2 Capture Route", NULL, "DMIC3"},
497 { "Txpath3 Capture Route", NULL, "DMIC3"},
498 { "Txpath4 Capture Route", NULL, "DMIC3"},
499 { "Txpath1 Capture Route", NULL, "DMIC4"},
500 { "Txpath2 Capture Route", NULL, "DMIC4"},
501 { "Txpath3 Capture Route", NULL, "DMIC4"},
502 { "Txpath4 Capture Route", NULL, "DMIC4"},
503 { "Txpath1 Capture Route", NULL, "DMIC5"},
504 { "Txpath2 Capture Route", NULL, "DMIC5"},
505 { "Txpath3 Capture Route", NULL, "DMIC5"},
506 { "Txpath4 Capture Route", NULL, "DMIC5"},
507 { "Txpath1 Capture Route", NULL, "DMIC6"},
508 { "Txpath2 Capture Route", NULL, "DMIC6"},
509 { "Txpath3 Capture Route", NULL, "DMIC6"},
510 { "Txpath4 Capture Route", NULL, "DMIC6"},
511
512 /* tx path */
513 { "TX1 Enable", NULL, "Txpath1 Capture Route"},
514 { "TX2 Enable", NULL, "Txpath2 Capture Route"},
515 { "TX3 Enable", NULL, "Txpath3 Capture Route"},
516 { "TX4 Enable", NULL, "Txpath4 Capture Route"},
517 { "PCM_Out", NULL, "TX1 Enable"},
518 { "PCM_Out", NULL, "TX2 Enable"},
519 { "PCM_Out", NULL, "TX3 Enable"},
520 { "PCM_Out", NULL, "TX4 Enable"},
521
253}; 522};
254 523
255/* speaker and headset mutes, for audio pops and clicks */ 524/* speaker and headset mutes, for audio pops and clicks */
@@ -339,6 +608,13 @@ struct snd_soc_dai_driver sn95031_dais[] = {
339 .rates = SN95031_RATES, 608 .rates = SN95031_RATES,
340 .formats = SN95031_FORMATS, 609 .formats = SN95031_FORMATS,
341 }, 610 },
611 .capture = {
612 .stream_name = "Capture",
613 .channels_min = 1,
614 .channels_max = 5,
615 .rates = SN95031_RATES,
616 .formats = SN95031_FORMATS,
617 },
342 .ops = &sn95031_headset_dai_ops, 618 .ops = &sn95031_headset_dai_ops,
343}, 619},
344{ .name = "SN95031 Speaker", 620{ .name = "SN95031 Speaker",
@@ -390,6 +666,8 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
390 snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10); 666 snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10);
391 snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32); 667 snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32);
392 snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54); 668 snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54);
669 snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10);
670 snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32);
393 /* pcm port setting 671 /* pcm port setting
394 * This sets the pcm port to slave and clock at 19.2Mhz which 672 * This sets the pcm port to slave and clock at 19.2Mhz which
395 * can support 6slots, sampling rate set per stream in hw-params 673 * can support 6slots, sampling rate set per stream in hw-params
@@ -423,6 +701,9 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
423 snd_soc_write(codec, SN95031_SSR2, 0x10); 701 snd_soc_write(codec, SN95031_SSR2, 0x10);
424 snd_soc_write(codec, SN95031_SSR3, 0x40); 702 snd_soc_write(codec, SN95031_SSR3, 0x40);
425 703
704 snd_soc_add_controls(codec, sn95031_snd_controls,
705 ARRAY_SIZE(sn95031_snd_controls));
706
426 ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets, 707 ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets,
427 ARRAY_SIZE(sn95031_dapm_widgets)); 708 ARRAY_SIZE(sn95031_dapm_widgets));
428 if (ret) 709 if (ret)