blob: 40e285df9ae5c669aba0dcd37a8690a76b47d8d3 [file] [log] [blame]
Vinod Koul4dc69be2011-01-04 20:16:07 +05301/*
2 * sn95031.c - TI sn95031 Codec driver
3 *
4 * Copyright (C) 2010 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * Author: Harsha Priya <priya.harsha@intel.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 as published by
11 * the Free Software Foundation; version 2 of the License.
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 along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 *
25 */
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <asm/intel_scu_ipc.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/initval.h>
Harsha Priyafd94eee2011-01-28 22:26:53 +053036#include <sound/tlv.h>
Vinod Koul4dc69be2011-01-04 20:16:07 +053037#include "sn95031.h"
38
39#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
40#define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
41
42/*
43 * todo:
44 * capture paths
45 * jack detection
46 * PM functions
47 */
48
49static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
50 unsigned int reg)
51{
52 u8 value = 0;
53 int ret;
54
55 ret = intel_scu_ipc_ioread8(reg, &value);
56 if (ret)
57 pr_err("read of %x failed, err %d\n", reg, ret);
58 return value;
59
60}
61
62static inline int sn95031_write(struct snd_soc_codec *codec,
63 unsigned int reg, unsigned int value)
64{
65 int ret;
66
67 ret = intel_scu_ipc_iowrite8(reg, value);
68 if (ret)
69 pr_err("write of %x failed, err %d\n", reg, ret);
70 return ret;
71}
72
73static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
74 enum snd_soc_bias_level level)
75{
76 switch (level) {
77 case SND_SOC_BIAS_ON:
78 break;
79
80 case SND_SOC_BIAS_PREPARE:
81 if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
82 pr_debug("vaud_bias powering up pll\n");
83 /* power up the pll */
84 snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5));
85 /* enable pcm 2 */
86 snd_soc_update_bits(codec, SN95031_PCM2C2,
87 BIT(0), BIT(0));
88 }
89 break;
90
91 case SND_SOC_BIAS_STANDBY:
92 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
93 pr_debug("vaud_bias power up rail\n");
94 /* power up the rail */
95 snd_soc_write(codec, SN95031_VAUD,
96 BIT(2)|BIT(1)|BIT(0));
97 msleep(1);
98 } else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) {
99 /* turn off pcm */
100 pr_debug("vaud_bias power dn pcm\n");
101 snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0);
102 snd_soc_write(codec, SN95031_AUDPLLCTRL, 0);
103 }
104 break;
105
106
107 case SND_SOC_BIAS_OFF:
108 pr_debug("vaud_bias _OFF doing rail shutdown\n");
109 snd_soc_write(codec, SN95031_VAUD, BIT(3));
110 break;
111 }
112
113 codec->dapm.bias_level = level;
114 return 0;
115}
116
117static int sn95031_vhs_event(struct snd_soc_dapm_widget *w,
118 struct snd_kcontrol *kcontrol, int event)
119{
120 if (SND_SOC_DAPM_EVENT_ON(event)) {
121 pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
122 /* power up the rail */
123 snd_soc_write(w->codec, SN95031_VHSP, 0x3D);
124 snd_soc_write(w->codec, SN95031_VHSN, 0x3F);
125 msleep(1);
126 } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
127 pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
128 snd_soc_write(w->codec, SN95031_VHSP, 0xC4);
129 snd_soc_write(w->codec, SN95031_VHSN, 0x04);
130 }
131 return 0;
132}
133
134static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
135 struct snd_kcontrol *kcontrol, int event)
136{
137 if (SND_SOC_DAPM_EVENT_ON(event)) {
138 pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
139 /* power up the rail */
140 snd_soc_write(w->codec, SN95031_VIHF, 0x27);
141 msleep(1);
142 } else if (SND_SOC_DAPM_EVENT_OFF(event)) {
143 pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
144 snd_soc_write(w->codec, SN95031_VIHF, 0x24);
145 }
146 return 0;
147}
148
Harsha Priyafd94eee2011-01-28 22:26:53 +0530149static 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
Vinod Koul4dc69be2011-01-04 20:16:07 +0530272/* DAPM widgets */
273static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
274
275 /* all end points mic, hs etc */
276 SND_SOC_DAPM_OUTPUT("HPOUTL"),
277 SND_SOC_DAPM_OUTPUT("HPOUTR"),
278 SND_SOC_DAPM_OUTPUT("EPOUT"),
279 SND_SOC_DAPM_OUTPUT("IHFOUTL"),
280 SND_SOC_DAPM_OUTPUT("IHFOUTR"),
281 SND_SOC_DAPM_OUTPUT("LINEOUTL"),
282 SND_SOC_DAPM_OUTPUT("LINEOUTR"),
283 SND_SOC_DAPM_OUTPUT("VIB1OUT"),
284 SND_SOC_DAPM_OUTPUT("VIB2OUT"),
285
Harsha Priyafd94eee2011-01-28 22:26:53 +0530286 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
Vinod Koul4dc69be2011-01-04 20:16:07 +0530316 SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0,
317 sn95031_vhs_event,
318 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
319 SND_SOC_DAPM_SUPPLY("Speaker Rail", SND_SOC_NOPM, 0, 0,
320 sn95031_vihf_event,
321 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
322
323 /* playback path driver enables */
324 SND_SOC_DAPM_PGA("Headset Left Playback",
325 SN95031_DRIVEREN, 0, 0, NULL, 0),
326 SND_SOC_DAPM_PGA("Headset Right Playback",
327 SN95031_DRIVEREN, 1, 0, NULL, 0),
328 SND_SOC_DAPM_PGA("Speaker Left Playback",
329 SN95031_DRIVEREN, 2, 0, NULL, 0),
330 SND_SOC_DAPM_PGA("Speaker Right Playback",
331 SN95031_DRIVEREN, 3, 0, NULL, 0),
332 SND_SOC_DAPM_PGA("Vibra1 Playback",
333 SN95031_DRIVEREN, 4, 0, NULL, 0),
334 SND_SOC_DAPM_PGA("Vibra2 Playback",
335 SN95031_DRIVEREN, 5, 0, NULL, 0),
336 SND_SOC_DAPM_PGA("Earpiece Playback",
337 SN95031_DRIVEREN, 6, 0, NULL, 0),
338 SND_SOC_DAPM_PGA("Lineout Left Playback",
339 SN95031_LOCTL, 0, 0, NULL, 0),
340 SND_SOC_DAPM_PGA("Lineout Right Playback",
341 SN95031_LOCTL, 4, 0, NULL, 0),
342
343 /* playback path filter enable */
344 SND_SOC_DAPM_PGA("Headset Left Filter",
345 SN95031_HSEPRXCTRL, 4, 0, NULL, 0),
346 SND_SOC_DAPM_PGA("Headset Right Filter",
347 SN95031_HSEPRXCTRL, 5, 0, NULL, 0),
348 SND_SOC_DAPM_PGA("Speaker Left Filter",
349 SN95031_IHFRXCTRL, 0, 0, NULL, 0),
350 SND_SOC_DAPM_PGA("Speaker Right Filter",
351 SN95031_IHFRXCTRL, 1, 0, NULL, 0),
352
353 /* DACs */
354 SND_SOC_DAPM_DAC("HSDAC Left", "Headset",
355 SN95031_DACCONFIG, 0, 0),
356 SND_SOC_DAPM_DAC("HSDAC Right", "Headset",
357 SN95031_DACCONFIG, 1, 0),
358 SND_SOC_DAPM_DAC("IHFDAC Left", "Speaker",
359 SN95031_DACCONFIG, 2, 0),
360 SND_SOC_DAPM_DAC("IHFDAC Right", "Speaker",
361 SN95031_DACCONFIG, 3, 0),
362 SND_SOC_DAPM_DAC("Vibra1 DAC", "Vibra1",
363 SN95031_VIB1C5, 1, 0),
364 SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2",
365 SN95031_VIB2C5, 1, 0),
Harsha Priyafd94eee2011-01-28 22:26:53 +0530366
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
Vinod Koul4dc69be2011-01-04 20:16:07 +0530400};
401
402static const struct snd_soc_dapm_route sn95031_audio_map[] = {
403 /* headset and earpiece map */
404 { "HPOUTL", NULL, "Headset Left Playback" },
405 { "HPOUTR", NULL, "Headset Right Playback" },
406 { "EPOUT", NULL, "Earpiece Playback" },
407 { "Headset Left Playback", NULL, "Headset Left Filter"},
408 { "Headset Right Playback", NULL, "Headset Right Filter"},
409 { "Earpiece Playback", NULL, "Headset Left Filter"},
410 { "Headset Left Filter", NULL, "HSDAC Left"},
411 { "Headset Right Filter", NULL, "HSDAC Right"},
412 { "HSDAC Left", NULL, "Headset Rail"},
413 { "HSDAC Right", NULL, "Headset Rail"},
414
415 /* speaker map */
416 { "IHFOUTL", "NULL", "Speaker Left Playback"},
417 { "IHFOUTR", "NULL", "Speaker Right Playback"},
418 { "Speaker Left Playback", NULL, "Speaker Left Filter"},
419 { "Speaker Right Playback", NULL, "Speaker Right Filter"},
420 { "Speaker Left Filter", NULL, "IHFDAC Left"},
421 { "Speaker Right Filter", NULL, "IHFDAC Right"},
422 { "IHFDAC Left", NULL, "Speaker Rail"},
423 { "IHFDAC Right", NULL, "Speaker Rail"},
424
425 /* vibra map */
Vinod Koulb22dab82011-01-07 16:20:28 +0530426 { "VIB1OUT", NULL, "Vibra1 Playback"},
427 { "Vibra1 Playback", NULL, "Vibra1 DAC"},
Vinod Koul4dc69be2011-01-04 20:16:07 +0530428
Vinod Koulb22dab82011-01-07 16:20:28 +0530429 { "VIB2OUT", NULL, "Vibra2 Playback"},
430 { "Vibra2 Playback", NULL, "Vibra2 DAC"},
Vinod Koul4dc69be2011-01-04 20:16:07 +0530431
432 /* lineout */
Vinod Koulb22dab82011-01-07 16:20:28 +0530433 { "LINEOUTL", NULL, "Lineout Left Playback"},
434 { "LINEOUTR", NULL, "Lineout Right Playback"},
435 { "Lineout Left Playback", NULL, "Headset Left Filter"},
436 { "Lineout Left Playback", NULL, "Speaker Left Filter"},
437 { "Lineout Left Playback", NULL, "Vibra1 DAC"},
438 { "Lineout Right Playback", NULL, "Headset Right Filter"},
439 { "Lineout Right Playback", NULL, "Speaker Right Filter"},
440 { "Lineout Right Playback", NULL, "Vibra2 DAC"},
Harsha Priyafd94eee2011-01-28 22:26:53 +0530441
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
Vinod Koul4dc69be2011-01-04 20:16:07 +0530522};
523
524/* speaker and headset mutes, for audio pops and clicks */
525static int sn95031_pcm_hs_mute(struct snd_soc_dai *dai, int mute)
526{
527 snd_soc_update_bits(dai->codec,
528 SN95031_HSLVOLCTRL, BIT(7), (!mute << 7));
529 snd_soc_update_bits(dai->codec,
530 SN95031_HSRVOLCTRL, BIT(7), (!mute << 7));
531 return 0;
532}
533
534static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute)
535{
536 snd_soc_update_bits(dai->codec,
537 SN95031_IHFLVOLCTRL, BIT(7), (!mute << 7));
538 snd_soc_update_bits(dai->codec,
539 SN95031_IHFRVOLCTRL, BIT(7), (!mute << 7));
540 return 0;
541}
542
543int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
544 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
545{
546 unsigned int format, rate;
547
548 switch (params_format(params)) {
549 case SNDRV_PCM_FORMAT_S16_LE:
550 format = BIT(4)|BIT(5);
551 break;
552
553 case SNDRV_PCM_FORMAT_S24_LE:
554 format = 0;
555 break;
556 default:
557 return -EINVAL;
558 }
559 snd_soc_update_bits(dai->codec, SN95031_PCM2C2,
560 BIT(4)|BIT(5), format);
561
562 switch (params_rate(params)) {
563 case 48000:
564 pr_debug("RATE_48000\n");
565 rate = 0;
566 break;
567
568 case 44100:
569 pr_debug("RATE_44100\n");
570 rate = BIT(7);
571 break;
572
573 default:
574 pr_err("ERR rate %d\n", params_rate(params));
575 return -EINVAL;
576 }
577 snd_soc_update_bits(dai->codec, SN95031_PCM1C1, BIT(7), rate);
578
579 return 0;
580}
581
582/* Codec DAI section */
583static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
584 .digital_mute = sn95031_pcm_hs_mute,
585 .hw_params = sn95031_pcm_hw_params,
586};
587
588static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
589 .digital_mute = sn95031_pcm_spkr_mute,
590 .hw_params = sn95031_pcm_hw_params,
591};
592
593static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
594 .hw_params = sn95031_pcm_hw_params,
595};
596
597static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
598 .hw_params = sn95031_pcm_hw_params,
599};
600
601struct snd_soc_dai_driver sn95031_dais[] = {
602{
603 .name = "SN95031 Headset",
604 .playback = {
605 .stream_name = "Headset",
606 .channels_min = 2,
607 .channels_max = 2,
608 .rates = SN95031_RATES,
609 .formats = SN95031_FORMATS,
610 },
Harsha Priyafd94eee2011-01-28 22:26:53 +0530611 .capture = {
612 .stream_name = "Capture",
613 .channels_min = 1,
614 .channels_max = 5,
615 .rates = SN95031_RATES,
616 .formats = SN95031_FORMATS,
617 },
Vinod Koul4dc69be2011-01-04 20:16:07 +0530618 .ops = &sn95031_headset_dai_ops,
619},
620{ .name = "SN95031 Speaker",
621 .playback = {
622 .stream_name = "Speaker",
623 .channels_min = 2,
624 .channels_max = 2,
625 .rates = SN95031_RATES,
626 .formats = SN95031_FORMATS,
627 },
628 .ops = &sn95031_speaker_dai_ops,
629},
630{ .name = "SN95031 Vibra1",
631 .playback = {
632 .stream_name = "Vibra1",
633 .channels_min = 1,
634 .channels_max = 1,
635 .rates = SN95031_RATES,
636 .formats = SN95031_FORMATS,
637 },
638 .ops = &sn95031_vib1_dai_ops,
639},
640{ .name = "SN95031 Vibra2",
641 .playback = {
642 .stream_name = "Vibra2",
643 .channels_min = 1,
644 .channels_max = 1,
645 .rates = SN95031_RATES,
646 .formats = SN95031_FORMATS,
647 },
648 .ops = &sn95031_vib2_dai_ops,
649},
650};
651
652/* codec registration */
653static int sn95031_codec_probe(struct snd_soc_codec *codec)
654{
655 int ret;
656
657 pr_debug("codec_probe called\n");
658
659 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
660 codec->dapm.idle_bias_off = 1;
661
662 /* PCM interface config
663 * This sets the pcm rx slot conguration to max 6 slots
664 * for max 4 dais (2 stereo and 2 mono)
665 */
666 snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10);
667 snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32);
668 snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54);
Harsha Priyafd94eee2011-01-28 22:26:53 +0530669 snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10);
670 snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32);
Vinod Koul4dc69be2011-01-04 20:16:07 +0530671 /* pcm port setting
672 * This sets the pcm port to slave and clock at 19.2Mhz which
673 * can support 6slots, sampling rate set per stream in hw-params
674 */
675 snd_soc_write(codec, SN95031_PCM1C1, 0x00);
676 snd_soc_write(codec, SN95031_PCM2C1, 0x01);
677 snd_soc_write(codec, SN95031_PCM2C2, 0x0A);
678 snd_soc_write(codec, SN95031_HSMIXER, BIT(0)|BIT(4));
679 /* vendor vibra workround, the vibras are muted by
680 * custom register so unmute them
681 */
682 snd_soc_write(codec, SN95031_SSR5, 0x80);
683 snd_soc_write(codec, SN95031_SSR6, 0x80);
684 snd_soc_write(codec, SN95031_VIB1C5, 0x00);
685 snd_soc_write(codec, SN95031_VIB2C5, 0x00);
686 /* configure vibras for pcm port */
687 snd_soc_write(codec, SN95031_VIB1C3, 0x00);
688 snd_soc_write(codec, SN95031_VIB2C3, 0x00);
689
690 /* soft mute ramp time */
691 snd_soc_write(codec, SN95031_SOFTMUTE, 0x3);
692 /* fix the initial volume at 1dB,
693 * default in +9dB,
694 * 1dB give optimal swing on DAC, amps
695 */
696 snd_soc_write(codec, SN95031_HSLVOLCTRL, 0x08);
697 snd_soc_write(codec, SN95031_HSRVOLCTRL, 0x08);
698 snd_soc_write(codec, SN95031_IHFLVOLCTRL, 0x08);
699 snd_soc_write(codec, SN95031_IHFRVOLCTRL, 0x08);
700 /* dac mode and lineout workaround */
701 snd_soc_write(codec, SN95031_SSR2, 0x10);
702 snd_soc_write(codec, SN95031_SSR3, 0x40);
703
Harsha Priyafd94eee2011-01-28 22:26:53 +0530704 snd_soc_add_controls(codec, sn95031_snd_controls,
705 ARRAY_SIZE(sn95031_snd_controls));
706
Vinod Koul4dc69be2011-01-04 20:16:07 +0530707 ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets,
708 ARRAY_SIZE(sn95031_dapm_widgets));
709 if (ret)
710 pr_err("soc_dapm_new_control failed %d", ret);
711 ret = snd_soc_dapm_add_routes(&codec->dapm, sn95031_audio_map,
712 ARRAY_SIZE(sn95031_audio_map));
713 if (ret)
714 pr_err("soc_dapm_add_routes failed %d", ret);
715
716 return ret;
717}
718
719static int sn95031_codec_remove(struct snd_soc_codec *codec)
720{
721 pr_debug("codec_remove called\n");
722 sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF);
723
724 return 0;
725}
726
727struct snd_soc_codec_driver sn95031_codec = {
Vinod Koulb22dab82011-01-07 16:20:28 +0530728 .probe = sn95031_codec_probe,
729 .remove = sn95031_codec_remove,
Vinod Koul4dc69be2011-01-04 20:16:07 +0530730 .read = sn95031_read,
731 .write = sn95031_write,
732 .set_bias_level = sn95031_set_vaud_bias,
733};
734
735static int __devinit sn95031_device_probe(struct platform_device *pdev)
736{
737 pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
738 return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
739 sn95031_dais, ARRAY_SIZE(sn95031_dais));
740}
741
742static int __devexit sn95031_device_remove(struct platform_device *pdev)
743{
744 pr_debug("codec device remove called\n");
745 snd_soc_unregister_codec(&pdev->dev);
746 return 0;
747}
748
749static struct platform_driver sn95031_codec_driver = {
750 .driver = {
751 .name = "sn95031",
752 .owner = THIS_MODULE,
753 },
754 .probe = sn95031_device_probe,
755 .remove = sn95031_device_remove,
756};
757
758static int __init sn95031_init(void)
759{
760 pr_debug("driver init called\n");
761 return platform_driver_register(&sn95031_codec_driver);
762}
763module_init(sn95031_init);
764
765static void __exit sn95031_exit(void)
766{
767 pr_debug("driver exit called\n");
768 platform_driver_unregister(&sn95031_codec_driver);
769}
770module_exit(sn95031_exit);
771
Vinod Koulb22dab82011-01-07 16:20:28 +0530772MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
Vinod Koul4dc69be2011-01-04 20:16:07 +0530773MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
774MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
775MODULE_LICENSE("GPL v2");
776MODULE_ALIAS("platform:sn95031");