blob: c8ef4193b8071f1f3e9a8c447171225cd24a2aea [file] [log] [blame]
Joonwoo Park0976d012011-12-22 11:48:18 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/gpio.h>
16#include <linux/mfd/pm8xxx/pm8921.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h>
19#include <linux/mfd/pm8xxx/pm8921.h>
Joonwoo Park0976d012011-12-22 11:48:18 -080020#include <linux/slab.h>
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080021#include <sound/core.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/soc-dsp.h>
25#include <sound/pcm.h>
26#include <sound/jack.h>
27#include <asm/mach-types.h>
28#include <mach/socinfo.h>
29#include "msm-pcm-routing.h"
30#include "../codecs/wcd9310.h"
31
32/* 8064 machine driver */
33
34#define PM8921_GPIO_BASE NR_GPIO_IRQS
35#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
36
37#define MSM8064_SPK_ON 1
38#define MSM8064_SPK_OFF 0
39
40#define MSM_SLIM_0_RX_MAX_CHANNELS 2
41#define MSM_SLIM_0_TX_MAX_CHANNELS 4
42
43#define BTSCO_RATE_8KHZ 8000
44#define BTSCO_RATE_16KHZ 16000
45
46#define BOTTOM_SPK_AMP_POS 0x1
47#define BOTTOM_SPK_AMP_NEG 0x2
48#define TOP_SPK_AMP_POS 0x4
49#define TOP_SPK_AMP_NEG 0x8
50
51#define GPIO_AUX_PCM_DOUT 43
52#define GPIO_AUX_PCM_DIN 44
53#define GPIO_AUX_PCM_SYNC 45
54#define GPIO_AUX_PCM_CLK 46
55
Joonwoo Park0976d012011-12-22 11:48:18 -080056#define TABLA_EXT_CLK_RATE 12288000
57
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -080058#define TABLA_MBHC_DEF_BUTTONS 8
Joonwoo Park0976d012011-12-22 11:48:18 -080059#define TABLA_MBHC_DEF_RLOADS 5
60
Neema Shetty3c9d2862012-03-11 01:25:32 -080061/* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
62enum {
63 SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
64 SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
Neema Shetty74131ac2012-05-09 13:35:26 -070065 SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
66 SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
67 SLIM_3_TX_1 = 147, /* HDMI RX */
Helen Zeng8f925502012-03-05 16:50:17 -080068 SLIM_4_TX_1 = 148, /* In-call recording RX */
69 SLIM_4_TX_2 = 149, /* In-call recording RX */
70 SLIM_4_RX_1 = 150, /* In-call music delivery TX */
71};
72
73enum {
74 INCALL_REC_MONO,
75 INCALL_REC_STEREO,
Neema Shetty3c9d2862012-03-11 01:25:32 -080076};
77
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080078static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
79static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
80static int msm_spk_control;
81static int msm_ext_bottom_spk_pamp;
82static int msm_ext_top_spk_pamp;
83static int msm_slim_0_rx_ch = 1;
84static int msm_slim_0_tx_ch = 1;
Neema Shetty74131ac2012-05-09 13:35:26 -070085static int msm_slim_3_rx_ch = 1;
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080086
87static int msm_btsco_rate = BTSCO_RATE_8KHZ;
88static int msm_btsco_ch = 1;
89
Helen Zeng8f925502012-03-05 16:50:17 -080090static int rec_mode = INCALL_REC_MONO;
91
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080092static struct clk *codec_clk;
93static int clk_users;
94
95static int msm_headset_gpios_configured;
96
97static struct snd_soc_jack hs_jack;
98static struct snd_soc_jack button_jack;
99
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700100static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
101 bool dapm);
102
103static struct tabla_mbhc_config mbhc_cfg = {
104 .headset_jack = &hs_jack,
105 .button_jack = &button_jack,
106 .read_fw_bin = false,
107 .calibration = NULL,
108 .micbias = TABLA_MICBIAS2,
109 .mclk_cb_fn = msm_enable_codec_ext_clk,
110 .mclk_rate = TABLA_EXT_CLK_RATE,
111 .gpio = 0, /* MBHC GPIO is not configured */
112 .gpio_irq = 0,
113 .gpio_level_insert = 1,
114};
Joonwoo Park0976d012011-12-22 11:48:18 -0800115
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800116static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
117{
118 int ret = 0;
119
120 struct pm_gpio param = {
121 .direction = PM_GPIO_DIR_OUT,
122 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
123 .output_value = 1,
124 .pull = PM_GPIO_PULL_NO,
125 .vin_sel = PM_GPIO_VIN_S4,
126 .out_strength = PM_GPIO_STRENGTH_MED,
127 .
128 function = PM_GPIO_FUNC_NORMAL,
129 };
130
131 if (spk_amp_gpio == bottom_spk_pamp_gpio) {
132
133 ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
134 if (ret) {
135 pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
136 __func__, bottom_spk_pamp_gpio);
137 return;
138 }
139 ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
140 if (ret)
141 pr_err("%s: Failed to configure Bottom Spk Ampl"
142 " gpio %u\n", __func__, bottom_spk_pamp_gpio);
143 else {
144 pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
145 gpio_direction_output(bottom_spk_pamp_gpio, 1);
146 }
147
148 } else if (spk_amp_gpio == top_spk_pamp_gpio) {
149
150 ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
151 if (ret) {
152 pr_err("%s: Error requesting GPIO %d\n", __func__,
153 top_spk_pamp_gpio);
154 return;
155 }
156 ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
157 if (ret)
158 pr_err("%s: Failed to configure Top Spk Ampl"
159 " gpio %u\n", __func__, top_spk_pamp_gpio);
160 else {
161 pr_debug("%s: enable Top spkr amp gpio\n", __func__);
162 gpio_direction_output(top_spk_pamp_gpio, 1);
163 }
164 } else {
165 pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
166 " gpio = %u\n", __func__, spk_amp_gpio);
167 return;
168 }
169}
170
171static void msm_ext_spk_power_amp_on(u32 spk)
172{
173 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
174
175 if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
176 (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
177
178 pr_debug("%s() External Bottom Speaker Ampl already "
179 "turned on. spk = 0x%08x\n", __func__, spk);
180 return;
181 }
182
183 msm_ext_bottom_spk_pamp |= spk;
184
185 if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
186 (msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
187
188 msm_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
189 pr_debug("%s: slepping 4 ms after turning on external "
190 " Bottom Speaker Ampl\n", __func__);
191 usleep_range(4000, 4000);
192 }
193
194 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
195
196 if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
197 (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
198
199 pr_debug("%s() External Top Speaker Ampl already"
200 "turned on. spk = 0x%08x\n", __func__, spk);
201 return;
202 }
203
204 msm_ext_top_spk_pamp |= spk;
205
206 if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
207 (msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
208
209 msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
210 pr_debug("%s: sleeping 4 ms after turning on "
211 " external Top Speaker Ampl\n", __func__);
212 usleep_range(4000, 4000);
213 }
214 } else {
215
216 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
217 __func__, spk);
218 return;
219 }
220}
221
222static void msm_ext_spk_power_amp_off(u32 spk)
223{
224 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
225
226 if (!msm_ext_bottom_spk_pamp)
227 return;
228
229 gpio_direction_output(bottom_spk_pamp_gpio, 0);
230 gpio_free(bottom_spk_pamp_gpio);
231 msm_ext_bottom_spk_pamp = 0;
232
233 pr_debug("%s: sleeping 4 ms after turning off external Bottom"
234 " Speaker Ampl\n", __func__);
235
236 usleep_range(4000, 4000);
237
238 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
239
240 if (!msm_ext_top_spk_pamp)
241 return;
242
243 gpio_direction_output(top_spk_pamp_gpio, 0);
244 gpio_free(top_spk_pamp_gpio);
245 msm_ext_top_spk_pamp = 0;
246
247 pr_debug("%s: sleeping 4 ms after turning off external Top"
248 " Spkaker Ampl\n", __func__);
249
250 usleep_range(4000, 4000);
251 } else {
252
253 pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
254 __func__, spk);
255 return;
256 }
257}
258
259static void msm_ext_control(struct snd_soc_codec *codec)
260{
261 struct snd_soc_dapm_context *dapm = &codec->dapm;
262
263 pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
264 if (msm_spk_control == MSM8064_SPK_ON) {
265 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
266 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
267 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
268 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
269 } else {
270 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
271 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
272 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
273 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
274 }
275
276 snd_soc_dapm_sync(dapm);
277}
278
279static int msm_get_spk(struct snd_kcontrol *kcontrol,
280 struct snd_ctl_elem_value *ucontrol)
281{
282 pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
283 ucontrol->value.integer.value[0] = msm_spk_control;
284 return 0;
285}
286static int msm_set_spk(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_value *ucontrol)
288{
289 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
290
291 pr_debug("%s()\n", __func__);
292 if (msm_spk_control == ucontrol->value.integer.value[0])
293 return 0;
294
295 msm_spk_control = ucontrol->value.integer.value[0];
296 msm_ext_control(codec);
297 return 1;
298}
299static int msm_spkramp_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *k, int event)
301{
302 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
303
304 if (SND_SOC_DAPM_EVENT_ON(event)) {
305 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
306 msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
307 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
308 msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
309 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
310 msm_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
311 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
312 msm_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
313 else {
314 pr_err("%s() Invalid Speaker Widget = %s\n",
315 __func__, w->name);
316 return -EINVAL;
317 }
318
319 } else {
320 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
321 msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
322 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
323 msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
324 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
325 msm_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
326 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
327 msm_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
328 else {
329 pr_err("%s() Invalid Speaker Widget = %s\n",
330 __func__, w->name);
331 return -EINVAL;
332 }
333 }
334 return 0;
335}
336
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700337static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
338 bool dapm)
Joonwoo Park0976d012011-12-22 11:48:18 -0800339{
340 pr_debug("%s: enable = %d\n", __func__, enable);
341 if (enable) {
342 clk_users++;
343 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
344 if (clk_users != 1)
345 return 0;
346
Joonwoo Park0976d012011-12-22 11:48:18 -0800347 if (codec_clk) {
348 clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530349 clk_prepare_enable(codec_clk);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700350 tabla_mclk_enable(codec, 1, dapm);
Joonwoo Park0976d012011-12-22 11:48:18 -0800351 } else {
352 pr_err("%s: Error setting Tabla MCLK\n", __func__);
353 clk_users--;
354 return -EINVAL;
355 }
356 } else {
357 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
358 if (clk_users == 0)
359 return 0;
360 clk_users--;
361 if (!clk_users) {
362 pr_debug("%s: disabling MCLK. clk_users = %d\n",
363 __func__, clk_users);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700364 tabla_mclk_enable(codec, 0, dapm);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530365 clk_disable_unprepare(codec_clk);
Joonwoo Park0976d012011-12-22 11:48:18 -0800366 }
367 }
368 return 0;
369}
370
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800371static int msm_mclk_event(struct snd_soc_dapm_widget *w,
372 struct snd_kcontrol *kcontrol, int event)
373{
374 pr_debug("%s: event = %d\n", __func__, event);
375
376 switch (event) {
377 case SND_SOC_DAPM_PRE_PMU:
378
379 clk_users++;
380 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
381
382 if (clk_users != 1)
383 return 0;
384
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800385 if (codec_clk) {
386 clk_set_rate(codec_clk, 12288000);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530387 clk_prepare_enable(codec_clk);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700388 tabla_mclk_enable(w->codec, 1, true);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800389
390 } else {
391 pr_err("%s: Error setting Tabla MCLK\n", __func__);
392 clk_users--;
393 return -EINVAL;
394 }
395 break;
396 case SND_SOC_DAPM_POST_PMD:
397
398 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
399
400 if (clk_users == 0)
401 return 0;
402
403 clk_users--;
404
405 if (!clk_users) {
406 pr_debug("%s: disabling MCLK. clk_users = %d\n",
407 __func__, clk_users);
408
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700409 tabla_mclk_enable(w->codec, 0, true);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530410 clk_disable_unprepare(codec_clk);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800411 }
412 break;
413 }
414 return 0;
415}
416
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700417static const struct snd_soc_dapm_widget apq8064_dapm_widgets[] = {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800418
419 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
420 msm_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
421
422 SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm_spkramp_event),
423 SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm_spkramp_event),
424
425 SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm_spkramp_event),
426 SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm_spkramp_event),
427
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700428 /************ Analog MICs ************/
429 /**
430 * Analog mic7 (Front Top) on Liquid.
431 * Used as Handset mic on CDP.
432 */
433 SND_SOC_DAPM_MIC("Analog mic7", NULL),
434
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800435 SND_SOC_DAPM_MIC("Headset Mic", NULL),
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800436 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
437 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
438
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700439 /*********** Digital Mics ***************/
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800440 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
441 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
442 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
443 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
444 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
445 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800446};
447
Kiran Kandi323d7102012-04-18 19:56:14 -0700448static const struct snd_soc_dapm_route apq8064_common_audio_map[] = {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800449
450 {"RX_BIAS", NULL, "MCLK"},
451 {"LDO_H", NULL, "MCLK"},
452
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700453 {"HEADPHONE", NULL, "LDO_H"},
454
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800455 /* Speaker path */
456 {"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
457 {"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
458
459 {"Ext Spk Top Pos", NULL, "LINEOUT2"},
460 {"Ext Spk Top Neg", NULL, "LINEOUT4"},
461
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700462 /************ Analog MIC Paths ************/
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800463
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700464 /* Headset Mic */
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800465 {"AMIC2", NULL, "MIC BIAS2 External"},
466 {"MIC BIAS2 External", NULL, "Headset Mic"},
467
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700468 /* Headset ANC microphones */
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800469 {"AMIC3", NULL, "MIC BIAS3 Internal1"},
470 {"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
471
472 {"AMIC4", NULL, "MIC BIAS1 Internal2"},
473 {"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
Kiran Kandi323d7102012-04-18 19:56:14 -0700474};
475
476static const struct snd_soc_dapm_route apq8064_mtp_audio_map[] = {
477
478 /************ Digital MIC Paths ************/
479
480 /*
481 * Digital Mic1 (Front bottom Left) on MTP.
482 * Conncted to DMIC1 Input on Tabla codec.
483 */
484 {"DMIC1", NULL, "MIC BIAS1 External"},
485 {"MIC BIAS1 External", NULL, "Digital Mic1"},
486
487 /**
488 * Digital Mic2 (Front bottom right) on MTP.
489 * Conncted to DMIC2 Input on Tabla codec.
490 */
491 {"DMIC2", NULL, "MIC BIAS1 External"},
492 {"MIC BIAS1 External", NULL, "Digital Mic2"},
493
494 /**
495 * Digital Mic3 (Back bottom) on MTP.
496 * Conncted to DMIC3 Input on Tabla codec.
497 */
498 {"DMIC3", NULL, "MIC BIAS3 External"},
499 {"MIC BIAS3 External", NULL, "Digital Mic3"},
500
501 /**
502 * Digital Mic4 (Back top) on MTP.
503 * Conncted to DMIC4 Input on Tabla codec.
504 */
505 {"DMIC4", NULL, "MIC BIAS3 External"},
506 {"MIC BIAS3 External", NULL, "Digital Mic4"},
507
508 /**
509 * Digital Mic5 (Top front Mic) on MTP.
510 * Conncted to DMIC6 Input on Tabla codec.
511 */
512 {"DMIC6", NULL, "MIC BIAS4 External"},
513 {"MIC BIAS4 External", NULL, "Digital Mic5"},
514
515};
516
517static const struct snd_soc_dapm_route apq8064_liquid_cdp_audio_map[] = {
518
519 /************ Analog MIC Paths ************/
520 /**
521 * Analog mic7 (Front Top Mic) on Liquid.
522 * Used as Handset mic on CDP.
523 * Not there on MTP.
524 */
525 {"AMIC1", NULL, "MIC BIAS1 External"},
526 {"MIC BIAS1 External", NULL, "Analog mic7"},
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800527
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800528
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700529 /************ Digital MIC Paths ************/
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800530 /**
531 * The digital Mic routes are setup considering
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700532 * Liquid as default device.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800533 */
534
535 /**
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700536 * Digital Mic1 (Front bottom left corner) on Liquid.
537 * Digital Mic2 (Front bottom right) on MTP.
538 * Digital Mic GM1 on CDP mainboard.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800539 * Conncted to DMIC2 Input on Tabla codec.
540 */
541 {"DMIC2", NULL, "MIC BIAS1 External"},
542 {"MIC BIAS1 External", NULL, "Digital Mic1"},
543
544 /**
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700545 * Digital Mic2 (Front left side) on Liquid.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800546 * Digital Mic GM2 on CDP mainboard.
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700547 * Not there on MTP.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800548 * Conncted to DMIC3 Input on Tabla codec.
549 */
550 {"DMIC3", NULL, "MIC BIAS3 External"},
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700551 {"MIC BIAS3 External", NULL, "Digital Mic2"},
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800552
553 /**
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700554 * Digital Mic3. Front bottom left of middle on Liquid.
555 * Digital Mic5 (Top front Mic) on MTP.
556 * Digital Mic GM5 on CDP mainboard.
557 * Conncted to DMIC6 Input on Tabla codec.
558 */
559 {"DMIC6", NULL, "MIC BIAS4 External"},
560 {"MIC BIAS4 External", NULL, "Digital Mic3"},
561
562 /**
563 * Digital Mic4. Back bottom on Liquid.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800564 * Digital Mic GM3 on CDP mainboard.
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700565 * Top Front Mic on MTP.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800566 * Conncted to DMIC5 Input on Tabla codec.
567 */
568 {"DMIC5", NULL, "MIC BIAS4 External"},
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700569 {"MIC BIAS4 External", NULL, "Digital Mic4"},
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800570
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700571 /**
572 * Digital Mic5. Front bottom right of middle on Liquid.
573 * Digital Mic GM6 on CDP mainboard.
574 * Not there on MTP.
575 * Conncted to DMIC4 Input on Tabla codec.
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800576 */
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700577 {"DMIC4", NULL, "MIC BIAS3 External"},
578 {"MIC BIAS3 External", NULL, "Digital Mic5"},
579
580 /* Digital Mic6 (Front bottom right corner) on Liquid.
581 * Digital Mic1 (Front bottom Left) on MTP.
582 * Digital Mic GM4 on CDP.
583 * Conncted to DMIC1 Input on Tabla codec.
584 */
585 {"DMIC1", NULL, "MIC BIAS1 External"},
586 {"MIC BIAS1 External", NULL, "Digital Mic6"},
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800587};
588
589static const char *spk_function[] = {"Off", "On"};
590static const char *slim0_rx_ch_text[] = {"One", "Two"};
591static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
592
593static const struct soc_enum msm_enum[] = {
594 SOC_ENUM_SINGLE_EXT(2, spk_function),
595 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
596 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
597};
598
599static const char *btsco_rate_text[] = {"8000", "16000"};
600static const struct soc_enum msm_btsco_enum[] = {
601 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
602};
603
604static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
605 struct snd_ctl_elem_value *ucontrol)
606{
607 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
608 msm_slim_0_rx_ch);
609 ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
610 return 0;
611}
612
613static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
614 struct snd_ctl_elem_value *ucontrol)
615{
616 msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
617
618 pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
619 msm_slim_0_rx_ch);
620 return 1;
621}
622
623static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
624 struct snd_ctl_elem_value *ucontrol)
625{
626 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
627 msm_slim_0_tx_ch);
628 ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
629 return 0;
630}
631
632static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
633 struct snd_ctl_elem_value *ucontrol)
634{
635 msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
636
637 pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
638 msm_slim_0_tx_ch);
639 return 1;
640}
641
Neema Shetty74131ac2012-05-09 13:35:26 -0700642static int msm_slim_3_rx_ch_get(struct snd_kcontrol *kcontrol,
643 struct snd_ctl_elem_value *ucontrol)
644{
645 pr_debug("%s: msm_slim_3_rx_ch = %d\n", __func__,
646 msm_slim_3_rx_ch);
647 ucontrol->value.integer.value[0] = msm_slim_3_rx_ch - 1;
648 return 0;
649}
650
651static int msm_slim_3_rx_ch_put(struct snd_kcontrol *kcontrol,
652 struct snd_ctl_elem_value *ucontrol)
653{
654 msm_slim_3_rx_ch = ucontrol->value.integer.value[0] + 1;
655
656 pr_debug("%s: msm_slim_3_rx_ch = %d\n", __func__,
657 msm_slim_3_rx_ch);
658 return 1;
659}
660
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800661static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
662 struct snd_ctl_elem_value *ucontrol)
663{
664 pr_debug("%s: msm_btsco_rate = %d", __func__,
665 msm_btsco_rate);
666 ucontrol->value.integer.value[0] = msm_btsco_rate;
667 return 0;
668}
669
670static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
671 struct snd_ctl_elem_value *ucontrol)
672{
673 switch (ucontrol->value.integer.value[0]) {
674 case 0:
675 msm_btsco_rate = BTSCO_RATE_8KHZ;
676 break;
677 case 1:
678 msm_btsco_rate = BTSCO_RATE_16KHZ;
679 break;
680 default:
681 msm_btsco_rate = BTSCO_RATE_8KHZ;
682 break;
683 }
684 pr_debug("%s: msm_btsco_rate = %d\n", __func__,
685 msm_btsco_rate);
686 return 0;
687}
688
Helen Zeng8f925502012-03-05 16:50:17 -0800689static int msm_incall_rec_mode_get(struct snd_kcontrol *kcontrol,
690 struct snd_ctl_elem_value *ucontrol)
691{
692 ucontrol->value.integer.value[0] = rec_mode;
693 return 0;
694}
695
696static int msm_incall_rec_mode_put(struct snd_kcontrol *kcontrol,
697 struct snd_ctl_elem_value *ucontrol)
698{
699
700 rec_mode = ucontrol->value.integer.value[0];
701 pr_debug("%s: rec_mode:%d\n", __func__, rec_mode);
702
703 return 0;
704}
705
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800706static const struct snd_kcontrol_new tabla_msm_controls[] = {
707 SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
708 msm_set_spk),
709 SOC_ENUM_EXT("SLIM_0_RX Channels", msm_enum[1],
710 msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
711 SOC_ENUM_EXT("SLIM_0_TX Channels", msm_enum[2],
712 msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
713};
714
715static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
716 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
717 msm_btsco_rate_get, msm_btsco_rate_put),
718};
719
Helen Zeng8f925502012-03-05 16:50:17 -0800720static const struct snd_kcontrol_new incall_rec_mode_mixer_controls[] = {
721 SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
722 msm_incall_rec_mode_get, msm_incall_rec_mode_put),
723};
724
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -0800725static int msm_btsco_init(struct snd_soc_pcm_runtime *rtd)
726{
727 int err = 0;
728 struct snd_soc_platform *platform = rtd->platform;
729
730 err = snd_soc_add_platform_controls(platform,
731 int_btsco_rate_mixer_controls,
732 ARRAY_SIZE(int_btsco_rate_mixer_controls));
733 if (err < 0)
734 return err;
735 return 0;
736}
737
Neema Shetty74131ac2012-05-09 13:35:26 -0700738static const struct snd_kcontrol_new slim_3_mixer_controls[] = {
739 SOC_ENUM_EXT("SLIM_3_RX Channels", msm_enum[1],
740 msm_slim_3_rx_ch_get, msm_slim_3_rx_ch_put),
741};
742
743static int msm_slim_3_init(struct snd_soc_pcm_runtime *rtd)
744{
745 int err = 0;
746 struct snd_soc_platform *platform = rtd->platform;
747
748 err = snd_soc_add_platform_controls(platform,
749 slim_3_mixer_controls,
750 ARRAY_SIZE(slim_3_mixer_controls));
751 if (err < 0)
752 return err;
753 return 0;
754}
755
Helen Zeng8f925502012-03-05 16:50:17 -0800756static int msm_incall_rec_init(struct snd_soc_pcm_runtime *rtd)
757{
758 int err = 0;
759 struct snd_soc_platform *platform = rtd->platform;
760
761 err = snd_soc_add_platform_controls(platform,
762 incall_rec_mode_mixer_controls,
763 ARRAY_SIZE(incall_rec_mode_mixer_controls));
764 if (err < 0)
765 return err;
766 return 0;
767}
768
Joonwoo Park0976d012011-12-22 11:48:18 -0800769static void *def_tabla_mbhc_cal(void)
770{
771 void *tabla_cal;
772 struct tabla_mbhc_btn_detect_cfg *btn_cfg;
773 u16 *btn_low, *btn_high;
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800774 u8 *n_ready, *n_cic, *gain;
Joonwoo Park0976d012011-12-22 11:48:18 -0800775
776 tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
777 TABLA_MBHC_DEF_RLOADS),
778 GFP_KERNEL);
779 if (!tabla_cal) {
780 pr_err("%s: out of memory\n", __func__);
781 return NULL;
782 }
783
784#define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
785 S(t_ldoh, 100);
786 S(t_bg_fast_settle, 100);
787 S(t_shutdown_plug_rem, 255);
788 S(mbhc_nsa, 4);
789 S(mbhc_navg, 4);
790#undef S
791#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
792 S(mic_current, TABLA_PID_MIC_5_UA);
793 S(hph_current, TABLA_PID_MIC_5_UA);
794 S(t_mic_pid, 100);
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800795 S(t_ins_complete, 250);
Joonwoo Park0976d012011-12-22 11:48:18 -0800796 S(t_ins_retry, 200);
797#undef S
798#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
799 S(v_no_mic, 30);
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800800 S(v_hs_max, 1550);
Joonwoo Park0976d012011-12-22 11:48:18 -0800801#undef S
802#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800803 S(c[0], 62);
804 S(c[1], 124);
805 S(nc, 1);
806 S(n_meas, 3);
Joonwoo Park0976d012011-12-22 11:48:18 -0800807 S(mbhc_nsc, 11);
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800808 S(n_btn_meas, 1);
809 S(n_btn_con, 2);
Joonwoo Park0976d012011-12-22 11:48:18 -0800810 S(num_btn, TABLA_MBHC_DEF_BUTTONS);
811 S(v_btn_press_delta_sta, 100);
812 S(v_btn_press_delta_cic, 50);
813#undef S
814 btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
815 btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
816 btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800817 btn_low[0] = -50;
818 btn_high[0] = 10;
819 btn_low[1] = 11;
820 btn_high[1] = 38;
821 btn_low[2] = 39;
822 btn_high[2] = 64;
823 btn_low[3] = 65;
824 btn_high[3] = 91;
825 btn_low[4] = 92;
826 btn_high[4] = 115;
827 btn_low[5] = 116;
828 btn_high[5] = 141;
829 btn_low[6] = 142;
830 btn_high[6] = 163;
831 btn_low[7] = 164;
832 btn_high[7] = 250;
833 n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
834 n_ready[0] = 48;
835 n_ready[1] = 38;
Joonwoo Park0976d012011-12-22 11:48:18 -0800836 n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -0800837 n_cic[0] = 60;
838 n_cic[1] = 47;
Joonwoo Park0976d012011-12-22 11:48:18 -0800839 gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
840 gain[0] = 11;
841 gain[1] = 9;
842
843 return tabla_cal;
844}
845
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800846static int msm_hw_params(struct snd_pcm_substream *substream,
847 struct snd_pcm_hw_params *params)
848{
849 struct snd_soc_pcm_runtime *rtd = substream->private_data;
850 struct snd_soc_dai *codec_dai = rtd->codec_dai;
851 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
852 int ret = 0;
853 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
854 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700855 unsigned int user_set_tx_ch = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800856
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700857
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800858 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700859
860 pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch);
861
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800862 ret = snd_soc_dai_get_channel_map(codec_dai,
863 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
864 if (ret < 0) {
865 pr_err("%s: failed to get codec chan map\n", __func__);
866 goto end;
867 }
868
869 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
870 msm_slim_0_rx_ch, rx_ch);
871 if (ret < 0) {
872 pr_err("%s: failed to set cpu chan map\n", __func__);
873 goto end;
874 }
875 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
876 msm_slim_0_rx_ch, rx_ch);
877 if (ret < 0) {
878 pr_err("%s: failed to set codec channel map\n",
879 __func__);
880 goto end;
881 }
882 } else {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700883
884 if (codec_dai->id == 2)
885 user_set_tx_ch = msm_slim_0_tx_ch;
886 else if (codec_dai->id == 4)
887 user_set_tx_ch = params_channels(params);
Neema Shettye5cae8e2012-04-27 18:07:37 -0700888 else if (codec_dai->id == 5) {
889 /* DAI 5 is used for external EC reference from codec.
890 * Since Rx is fed as reference for EC, the config of
891 * this DAI is based on that of the Rx path.
892 */
893 user_set_tx_ch = msm_slim_0_rx_ch;
894 }
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700895
896 pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
897 codec_dai->name, codec_dai->id, user_set_tx_ch);
898
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800899 ret = snd_soc_dai_get_channel_map(codec_dai,
900 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
901 if (ret < 0) {
902 pr_err("%s: failed to get codec chan map\n", __func__);
903 goto end;
904 }
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700905
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800906 ret = snd_soc_dai_set_channel_map(cpu_dai,
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700907 user_set_tx_ch, tx_ch, 0 , 0);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800908 if (ret < 0) {
909 pr_err("%s: failed to set cpu chan map\n", __func__);
910 goto end;
911 }
912 ret = snd_soc_dai_set_channel_map(codec_dai,
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700913 user_set_tx_ch, tx_ch, 0, 0);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800914 if (ret < 0) {
915 pr_err("%s: failed to set codec channel map\n",
916 __func__);
917 goto end;
918 }
919
920
921 }
922end:
923 return ret;
924}
925
Helen Zengf3b17fb2012-02-28 15:07:38 -0800926static int msm_stubrx_init(struct snd_soc_pcm_runtime *rtd)
927{
928 rtd->pmdown_time = 0;
929
930 return 0;
931}
932
Neema Shetty3c9d2862012-03-11 01:25:32 -0800933static int msm_slimbus_1_hw_params(struct snd_pcm_substream *substream,
934 struct snd_pcm_hw_params *params)
935{
936 struct snd_soc_pcm_runtime *rtd = substream->private_data;
937 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
938 int ret = 0;
939 unsigned int rx_ch = SLIM_1_RX_1, tx_ch = SLIM_1_TX_1;
940
941 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
942 pr_debug("%s: APQ BT/USB TX -> SLIMBUS_1_RX -> MDM TX shared ch %d\n",
943 __func__, rx_ch);
944
945 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
946 if (ret < 0) {
947 pr_err("%s: Erorr %d setting SLIM_1 RX channel map\n",
948 __func__, ret);
949
950 goto end;
951 }
952 } else {
953 pr_debug("%s: MDM RX -> SLIMBUS_1_TX -> APQ BT/USB Rx shared ch %d\n",
954 __func__, tx_ch);
955
956 ret = snd_soc_dai_set_channel_map(cpu_dai, 1, &tx_ch, 0, 0);
957 if (ret < 0) {
958 pr_err("%s: Erorr %d setting SLIM_1 TX channel map\n",
959 __func__, ret);
960
961 goto end;
962 }
963 }
964
965end:
966 return ret;
967}
968
Neema Shetty74131ac2012-05-09 13:35:26 -0700969static int msm_slimbus_3_hw_params(struct snd_pcm_substream *substream,
970 struct snd_pcm_hw_params *params)
971{
972 struct snd_soc_pcm_runtime *rtd = substream->private_data;
973 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
974 int ret = 0;
975 unsigned int rx_ch[2] = {SLIM_3_RX_1, SLIM_3_RX_2};
976
977 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
978 pr_debug("%s: slim_3_rx_ch %d, sch %d %d\n",
979 __func__, msm_slim_3_rx_ch,
980 rx_ch[0], rx_ch[1]);
981
982 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
983 msm_slim_3_rx_ch, rx_ch);
984 if (ret < 0) {
985 pr_err("%s: Erorr %d setting SLIM_3 RX channel map\n",
986 __func__, ret);
987
988 goto end;
989 }
990 } else {
991 pr_err("%s: SLIMBUS_3_TX not defined for this DAI\n", __func__);
992 }
993
994end:
995 return ret;
996}
997
Helen Zeng8f925502012-03-05 16:50:17 -0800998static int msm_slimbus_4_hw_params(struct snd_pcm_substream *substream,
999 struct snd_pcm_hw_params *params)
1000{
1001 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1002 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1003 int ret = 0;
1004 unsigned int rx_ch = SLIM_4_RX_1, tx_ch[2];
1005
1006 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1007 pr_debug("%s: APQ Incall Playback SLIMBUS_4_RX -> MDM TX shared ch %d\n",
1008 __func__, rx_ch);
1009
1010 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0, 1, &rx_ch);
1011 if (ret < 0) {
1012 pr_err("%s: Erorr %d setting SLIM_4 RX channel map\n",
1013 __func__, ret);
1014
1015 }
1016 } else {
1017 if (rec_mode == INCALL_REC_STEREO) {
1018 tx_ch[0] = SLIM_4_TX_1;
1019 tx_ch[1] = SLIM_4_TX_2;
1020 ret = snd_soc_dai_set_channel_map(cpu_dai, 2,
1021 tx_ch, 0, 0);
1022 } else {
1023 tx_ch[0] = SLIM_4_TX_1;
1024 ret = snd_soc_dai_set_channel_map(cpu_dai, 1,
1025 tx_ch, 0, 0);
1026 }
1027 pr_debug("%s: Incall Record shared tx_ch[0]:%d, tx_ch[1]:%d\n",
1028 __func__, tx_ch[0], tx_ch[1]);
1029
1030 if (ret < 0) {
1031 pr_err("%s: Erorr %d setting SLIM_4 TX channel map\n",
1032 __func__, ret);
1033
1034 }
1035 }
1036
1037 return ret;
1038}
1039
1040
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001041static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
1042{
1043 int err;
1044 struct snd_soc_codec *codec = rtd->codec;
1045 struct snd_soc_dapm_context *dapm = &codec->dapm;
Kuirong Wanga9c3acc2012-02-09 17:00:45 -08001046 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001047
Kuirong Wanga9c3acc2012-02-09 17:00:45 -08001048 pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001049
1050 /*if (machine_is_msm_liquid()) {
1051 top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
1052 bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
1053 }*/
1054
1055 rtd->pmdown_time = 0;
1056
1057 err = snd_soc_add_controls(codec, tabla_msm_controls,
1058 ARRAY_SIZE(tabla_msm_controls));
1059 if (err < 0)
1060 return err;
1061
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001062 snd_soc_dapm_new_controls(dapm, apq8064_dapm_widgets,
1063 ARRAY_SIZE(apq8064_dapm_widgets));
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001064
Kiran Kandi323d7102012-04-18 19:56:14 -07001065 snd_soc_dapm_add_routes(dapm, apq8064_common_audio_map,
1066 ARRAY_SIZE(apq8064_common_audio_map));
1067
1068 if (machine_is_apq8064_mtp()) {
1069 snd_soc_dapm_add_routes(dapm, apq8064_mtp_audio_map,
1070 ARRAY_SIZE(apq8064_mtp_audio_map));
1071 } else {
1072 snd_soc_dapm_add_routes(dapm, apq8064_liquid_cdp_audio_map,
1073 ARRAY_SIZE(apq8064_liquid_cdp_audio_map));
1074 }
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001075
1076 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
1077 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
1078 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
1079 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
1080
1081 snd_soc_dapm_sync(dapm);
1082
1083 err = snd_soc_jack_new(codec, "Headset Jack",
1084 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
1085 &hs_jack);
1086 if (err) {
1087 pr_err("failed to create new jack\n");
1088 return err;
1089 }
1090
1091 err = snd_soc_jack_new(codec, "Button Jack",
Swaminathan Sathappan4ea7f1a02012-02-29 12:55:55 -08001092 TABLA_JACK_BUTTON_MASK, &button_jack);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001093 if (err) {
1094 pr_err("failed to create new jack\n");
1095 return err;
1096 }
1097
Kuirong Wanga9c3acc2012-02-09 17:00:45 -08001098 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
1099
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001100 err = tabla_hs_detect(codec, &mbhc_cfg);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001101
Joonwoo Park03324832012-03-19 19:36:16 -07001102 return err;
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001103}
1104
1105static struct snd_soc_dsp_link lpa_fe_media = {
1106 .playback = true,
1107 .trigger = {
1108 SND_SOC_DSP_TRIGGER_POST,
1109 SND_SOC_DSP_TRIGGER_POST
1110 },
1111};
1112
1113static struct snd_soc_dsp_link fe_media = {
1114 .playback = true,
1115 .capture = true,
1116 .trigger = {
1117 SND_SOC_DSP_TRIGGER_POST,
1118 SND_SOC_DSP_TRIGGER_POST
1119 },
1120};
1121
1122static struct snd_soc_dsp_link slimbus0_hl_media = {
1123 .playback = true,
1124 .capture = true,
1125 .trigger = {
1126 SND_SOC_DSP_TRIGGER_POST,
1127 SND_SOC_DSP_TRIGGER_POST
1128 },
1129};
1130
1131static struct snd_soc_dsp_link int_fm_hl_media = {
1132 .playback = true,
1133 .capture = true,
1134 .trigger = {
1135 SND_SOC_DSP_TRIGGER_POST,
1136 SND_SOC_DSP_TRIGGER_POST
1137 },
1138};
1139
1140static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1141 struct snd_pcm_hw_params *params)
1142{
1143 struct snd_interval *rate = hw_param_interval(params,
1144 SNDRV_PCM_HW_PARAM_RATE);
1145
1146 struct snd_interval *channels = hw_param_interval(params,
1147 SNDRV_PCM_HW_PARAM_CHANNELS);
1148
1149 pr_debug("%s()\n", __func__);
1150 rate->min = rate->max = 48000;
1151 channels->min = channels->max = msm_slim_0_rx_ch;
1152
1153 return 0;
1154}
1155
1156static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1157 struct snd_pcm_hw_params *params)
1158{
1159 struct snd_interval *rate = hw_param_interval(params,
1160 SNDRV_PCM_HW_PARAM_RATE);
1161
1162 struct snd_interval *channels = hw_param_interval(params,
1163 SNDRV_PCM_HW_PARAM_CHANNELS);
1164
1165 pr_debug("%s()\n", __func__);
1166 rate->min = rate->max = 48000;
1167 channels->min = channels->max = msm_slim_0_tx_ch;
1168
1169 return 0;
1170}
1171
Neema Shetty74131ac2012-05-09 13:35:26 -07001172static int msm_slim_3_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1173 struct snd_pcm_hw_params *params)
1174{
1175 struct snd_interval *rate = hw_param_interval(params,
1176 SNDRV_PCM_HW_PARAM_RATE);
1177
1178 struct snd_interval *channels = hw_param_interval(params,
1179 SNDRV_PCM_HW_PARAM_CHANNELS);
1180
1181 pr_debug("%s()\n", __func__);
1182 rate->min = rate->max = 48000;
1183 channels->min = channels->max = msm_slim_3_rx_ch;
1184
1185 return 0;
1186}
1187
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001188static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1189 struct snd_pcm_hw_params *params)
1190{
1191 struct snd_interval *rate = hw_param_interval(params,
1192 SNDRV_PCM_HW_PARAM_RATE);
1193
1194 pr_debug("%s()\n", __func__);
1195 rate->min = rate->max = 48000;
1196
1197 return 0;
1198}
1199
Swaminathan Sathappanfd9dbad2012-02-15 16:56:44 -08001200static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1201 struct snd_pcm_hw_params *params)
1202{
1203 struct snd_interval *rate = hw_param_interval(params,
1204 SNDRV_PCM_HW_PARAM_RATE);
1205
1206 struct snd_interval *channels = hw_param_interval(params,
1207 SNDRV_PCM_HW_PARAM_CHANNELS);
1208
1209 pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
1210 channels->min, channels->max);
1211
1212 rate->min = rate->max = 48000;
1213
1214 return 0;
1215}
1216
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001217static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1218 struct snd_pcm_hw_params *params)
1219{
1220 struct snd_interval *rate = hw_param_interval(params,
1221 SNDRV_PCM_HW_PARAM_RATE);
1222
1223 struct snd_interval *channels = hw_param_interval(params,
1224 SNDRV_PCM_HW_PARAM_CHANNELS);
1225
1226 rate->min = rate->max = msm_btsco_rate;
1227 channels->min = channels->max = msm_btsco_ch;
1228
1229 return 0;
1230}
1231static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
1232 struct snd_pcm_hw_params *params)
1233{
1234 struct snd_interval *rate = hw_param_interval(params,
1235 SNDRV_PCM_HW_PARAM_RATE);
1236
1237 struct snd_interval *channels = hw_param_interval(params,
1238 SNDRV_PCM_HW_PARAM_CHANNELS);
1239
1240 /* PCM only supports mono output with 8khz sample rate */
1241 rate->min = rate->max = 8000;
1242 channels->min = channels->max = 1;
1243
1244 return 0;
1245}
Neema Shetty3c9d2862012-03-11 01:25:32 -08001246
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001247static int msm_aux_pcm_get_gpios(void)
1248{
1249 int ret = 0;
1250
1251 pr_debug("%s\n", __func__);
1252
1253 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
1254 if (ret < 0) {
1255 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
1256 __func__, GPIO_AUX_PCM_DOUT);
1257 goto fail_dout;
1258 }
1259
1260 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
1261 if (ret < 0) {
1262 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
1263 __func__, GPIO_AUX_PCM_DIN);
1264 goto fail_din;
1265 }
1266
1267 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
1268 if (ret < 0) {
1269 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
1270 __func__, GPIO_AUX_PCM_SYNC);
1271 goto fail_sync;
1272 }
1273 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
1274 if (ret < 0) {
1275 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
1276 __func__, GPIO_AUX_PCM_CLK);
1277 goto fail_clk;
1278 }
1279
1280 return 0;
1281
1282fail_clk:
1283 gpio_free(GPIO_AUX_PCM_SYNC);
1284fail_sync:
1285 gpio_free(GPIO_AUX_PCM_DIN);
1286fail_din:
1287 gpio_free(GPIO_AUX_PCM_DOUT);
1288fail_dout:
1289
1290 return ret;
1291}
1292
1293static int msm_aux_pcm_free_gpios(void)
1294{
1295 gpio_free(GPIO_AUX_PCM_DIN);
1296 gpio_free(GPIO_AUX_PCM_DOUT);
1297 gpio_free(GPIO_AUX_PCM_SYNC);
1298 gpio_free(GPIO_AUX_PCM_CLK);
1299
1300 return 0;
1301}
1302static int msm_startup(struct snd_pcm_substream *substream)
1303{
1304 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1305 substream->name, substream->stream);
1306 return 0;
1307}
1308
1309static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
1310{
1311 int ret = 0;
1312
1313 pr_debug("%s(): substream = %s\n", __func__, substream->name);
1314 ret = msm_aux_pcm_get_gpios();
1315 if (ret < 0) {
1316 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
1317 return -EINVAL;
1318 }
1319 return 0;
1320}
1321
1322static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
1323{
1324
1325 pr_debug("%s(): substream = %s\n", __func__, substream->name);
1326 msm_aux_pcm_free_gpios();
1327}
1328
1329static void msm_shutdown(struct snd_pcm_substream *substream)
1330{
1331 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1332 substream->name, substream->stream);
1333}
1334
1335static struct snd_soc_ops msm_be_ops = {
1336 .startup = msm_startup,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001337 .hw_params = msm_hw_params,
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001338 .shutdown = msm_shutdown,
1339};
1340
1341static struct snd_soc_ops msm_auxpcm_be_ops = {
1342 .startup = msm_auxpcm_startup,
1343 .shutdown = msm_auxpcm_shutdown,
1344};
1345
Neema Shetty3c9d2862012-03-11 01:25:32 -08001346static struct snd_soc_ops msm_slimbus_1_be_ops = {
1347 .startup = msm_startup,
1348 .hw_params = msm_slimbus_1_hw_params,
1349 .shutdown = msm_shutdown,
1350};
1351
Neema Shetty74131ac2012-05-09 13:35:26 -07001352static struct snd_soc_ops msm_slimbus_3_be_ops = {
1353 .startup = msm_startup,
1354 .hw_params = msm_slimbus_3_hw_params,
1355 .shutdown = msm_shutdown,
1356};
1357
Helen Zeng8f925502012-03-05 16:50:17 -08001358static struct snd_soc_ops msm_slimbus_4_be_ops = {
1359 .startup = msm_startup,
1360 .hw_params = msm_slimbus_4_hw_params,
1361 .shutdown = msm_shutdown,
1362};
1363
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001364/* Digital audio interface glue - connects codec <---> CPU */
1365static struct snd_soc_dai_link msm_dai[] = {
1366 /* FrontEnd DAI Links */
1367 {
1368 .name = "MSM8960 Media1",
1369 .stream_name = "MultiMedia1",
1370 .cpu_dai_name = "MultiMedia1",
1371 .platform_name = "msm-pcm-dsp",
1372 .dynamic = 1,
1373 .dsp_link = &fe_media,
1374 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1375 },
1376 {
1377 .name = "MSM8960 Media2",
1378 .stream_name = "MultiMedia2",
1379 .cpu_dai_name = "MultiMedia2",
1380 .platform_name = "msm-pcm-dsp",
1381 .dynamic = 1,
1382 .dsp_link = &fe_media,
1383 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1384 },
1385 {
1386 .name = "Circuit-Switch Voice",
1387 .stream_name = "CS-Voice",
1388 .cpu_dai_name = "CS-VOICE",
1389 .platform_name = "msm-pcm-voice",
1390 .dynamic = 1,
1391 .dsp_link = &fe_media,
1392 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1393 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1394 .ignore_suspend = 1,
1395 },
1396 {
1397 .name = "MSM VoIP",
1398 .stream_name = "VoIP",
1399 .cpu_dai_name = "VoIP",
1400 .platform_name = "msm-voip-dsp",
1401 .dynamic = 1,
1402 .dsp_link = &fe_media,
1403 .be_id = MSM_FRONTEND_DAI_VOIP,
1404 },
1405 {
1406 .name = "MSM8960 LPA",
1407 .stream_name = "LPA",
1408 .cpu_dai_name = "MultiMedia3",
1409 .platform_name = "msm-pcm-lpa",
1410 .dynamic = 1,
1411 .dsp_link = &lpa_fe_media,
1412 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1413 },
1414 /* Hostless PMC purpose */
1415 {
1416 .name = "SLIMBUS_0 Hostless",
1417 .stream_name = "SLIMBUS_0 Hostless",
1418 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1419 .platform_name = "msm-pcm-hostless",
1420 .dynamic = 1,
1421 .dsp_link = &slimbus0_hl_media,
1422 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1423 .ignore_suspend = 1,
1424 /* .be_id = do not care */
1425 },
1426 {
1427 .name = "INT_FM Hostless",
1428 .stream_name = "INT_FM Hostless",
1429 .cpu_dai_name = "INT_FM_HOSTLESS",
1430 .platform_name = "msm-pcm-hostless",
1431 .dynamic = 1,
1432 .dsp_link = &int_fm_hl_media,
1433 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1434 .ignore_suspend = 1,
1435 /* .be_id = do not care */
1436 },
1437 {
1438 .name = "MSM AFE-PCM RX",
1439 .stream_name = "AFE-PROXY RX",
1440 .cpu_dai_name = "msm-dai-q6.241",
1441 .codec_name = "msm-stub-codec.1",
1442 .codec_dai_name = "msm-stub-rx",
1443 .platform_name = "msm-pcm-afe",
1444 .ignore_suspend = 1,
1445 },
1446 {
1447 .name = "MSM AFE-PCM TX",
1448 .stream_name = "AFE-PROXY TX",
1449 .cpu_dai_name = "msm-dai-q6.240",
1450 .codec_name = "msm-stub-codec.1",
1451 .codec_dai_name = "msm-stub-tx",
1452 .platform_name = "msm-pcm-afe",
1453 .ignore_suspend = 1,
1454 },
Neema Shettyb9451242012-02-16 15:37:59 -08001455 {
1456 .name = "Voice Stub",
1457 .stream_name = "Voice Stub",
1458 .cpu_dai_name = "VOICE_STUB",
1459 .platform_name = "msm-pcm-hostless",
1460 .dynamic = 1,
1461 .dsp_link = &fe_media,
1462 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1463 .ignore_suspend = 1,
Neema Shetty3c9d2862012-03-11 01:25:32 -08001464 .be_id = MSM_FRONTEND_DAI_VOICE_STUB,
Neema Shettyb9451242012-02-16 15:37:59 -08001465 },
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001466 /* Backend DAI Links */
1467 {
1468 .name = LPASS_BE_SLIMBUS_0_RX,
1469 .stream_name = "Slimbus Playback",
1470 .cpu_dai_name = "msm-dai-q6.16384",
1471 .platform_name = "msm-pcm-routing",
1472 .codec_name = "tabla_codec",
1473 .codec_dai_name = "tabla_rx1",
1474 .no_pcm = 1,
1475 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1476 .init = &msm_audrx_init,
1477 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1478 .ops = &msm_be_ops,
1479 },
1480 {
1481 .name = LPASS_BE_SLIMBUS_0_TX,
1482 .stream_name = "Slimbus Capture",
1483 .cpu_dai_name = "msm-dai-q6.16385",
1484 .platform_name = "msm-pcm-routing",
1485 .codec_name = "tabla_codec",
1486 .codec_dai_name = "tabla_tx1",
1487 .no_pcm = 1,
1488 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1489 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1490 .ops = &msm_be_ops,
1491 },
1492 /* Backend BT/FM DAI Links */
1493 {
1494 .name = LPASS_BE_INT_BT_SCO_RX,
1495 .stream_name = "Internal BT-SCO Playback",
1496 .cpu_dai_name = "msm-dai-q6.12288",
1497 .platform_name = "msm-pcm-routing",
1498 .codec_name = "msm-stub-codec.1",
1499 .codec_dai_name = "msm-stub-rx",
1500 .init = &msm_btsco_init,
1501 .no_pcm = 1,
1502 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1503 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
1504 },
1505 {
1506 .name = LPASS_BE_INT_BT_SCO_TX,
1507 .stream_name = "Internal BT-SCO Capture",
1508 .cpu_dai_name = "msm-dai-q6.12289",
1509 .platform_name = "msm-pcm-routing",
1510 .codec_name = "msm-stub-codec.1",
1511 .codec_dai_name = "msm-stub-tx",
1512 .no_pcm = 1,
1513 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1514 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
1515 },
1516 {
1517 .name = LPASS_BE_INT_FM_RX,
1518 .stream_name = "Internal FM Playback",
1519 .cpu_dai_name = "msm-dai-q6.12292",
1520 .platform_name = "msm-pcm-routing",
1521 .codec_name = "msm-stub-codec.1",
1522 .codec_dai_name = "msm-stub-rx",
1523 .no_pcm = 1,
1524 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1525 .be_hw_params_fixup = msm_be_hw_params_fixup,
1526 },
1527 {
1528 .name = LPASS_BE_INT_FM_TX,
1529 .stream_name = "Internal FM Capture",
1530 .cpu_dai_name = "msm-dai-q6.12293",
1531 .platform_name = "msm-pcm-routing",
1532 .codec_name = "msm-stub-codec.1",
1533 .codec_dai_name = "msm-stub-tx",
1534 .no_pcm = 1,
1535 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1536 .be_hw_params_fixup = msm_be_hw_params_fixup,
1537 },
1538 /* HDMI BACK END DAI Link */
1539 {
1540 .name = LPASS_BE_HDMI,
1541 .stream_name = "HDMI Playback",
Swaminathan Sathappanfd9dbad2012-02-15 16:56:44 -08001542 .cpu_dai_name = "msm-dai-q6-hdmi.8",
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001543 .platform_name = "msm-pcm-routing",
1544 .codec_name = "msm-stub-codec.1",
1545 .codec_dai_name = "msm-stub-rx",
1546 .no_pcm = 1,
1547 .no_codec = 1,
1548 .be_id = MSM_BACKEND_DAI_HDMI_RX,
Swaminathan Sathappanfd9dbad2012-02-15 16:56:44 -08001549 .be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001550 },
1551 /* Backend AFE DAI Links */
1552 {
1553 .name = LPASS_BE_AFE_PCM_RX,
1554 .stream_name = "AFE Playback",
1555 .cpu_dai_name = "msm-dai-q6.224",
1556 .platform_name = "msm-pcm-routing",
1557 .codec_name = "msm-stub-codec.1",
1558 .codec_dai_name = "msm-stub-rx",
1559 .no_codec = 1,
1560 .no_pcm = 1,
1561 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
1562 },
1563 {
1564 .name = LPASS_BE_AFE_PCM_TX,
1565 .stream_name = "AFE Capture",
1566 .cpu_dai_name = "msm-dai-q6.225",
1567 .platform_name = "msm-pcm-routing",
1568 .codec_name = "msm-stub-codec.1",
1569 .codec_dai_name = "msm-stub-tx",
1570 .no_codec = 1,
1571 .no_pcm = 1,
1572 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
1573 },
1574 /* AUX PCM Backend DAI Links */
1575 {
1576 .name = LPASS_BE_AUXPCM_RX,
1577 .stream_name = "AUX PCM Playback",
1578 .cpu_dai_name = "msm-dai-q6.2",
1579 .platform_name = "msm-pcm-routing",
1580 .codec_name = "msm-stub-codec.1",
1581 .codec_dai_name = "msm-stub-rx",
1582 .no_pcm = 1,
1583 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1584 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
1585 .ops = &msm_auxpcm_be_ops,
1586 },
1587 {
1588 .name = LPASS_BE_AUXPCM_TX,
1589 .stream_name = "AUX PCM Capture",
1590 .cpu_dai_name = "msm-dai-q6.3",
1591 .platform_name = "msm-pcm-routing",
1592 .codec_name = "msm-stub-codec.1",
1593 .codec_dai_name = "msm-stub-tx",
1594 .no_pcm = 1,
1595 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1596 .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
1597 },
Neema Shettyb9451242012-02-16 15:37:59 -08001598 {
1599 .name = LPASS_BE_STUB_RX,
1600 .stream_name = "Stub Playback",
1601 .cpu_dai_name = "msm-dai-stub",
1602 .platform_name = "msm-pcm-routing",
1603 .codec_name = "tabla_codec",
1604 .codec_dai_name = "tabla_rx2",
1605 .no_pcm = 1,
Neema Shettye5cae8e2012-04-27 18:07:37 -07001606 .be_id = MSM_BACKEND_DAI_EXTPROC_RX,
Neema Shettyb9451242012-02-16 15:37:59 -08001607 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
Helen Zengf3b17fb2012-02-28 15:07:38 -08001608 .init = &msm_stubrx_init,
Neema Shettyb9451242012-02-16 15:37:59 -08001609 .ops = &msm_be_ops,
1610 },
1611 {
1612 .name = LPASS_BE_STUB_TX,
1613 .stream_name = "Stub Capture",
1614 .cpu_dai_name = "msm-dai-stub",
1615 .platform_name = "msm-pcm-routing",
1616 .codec_name = "tabla_codec",
1617 .codec_dai_name = "tabla_tx1",
1618 .no_pcm = 1,
Neema Shettye5cae8e2012-04-27 18:07:37 -07001619 .be_id = MSM_BACKEND_DAI_EXTPROC_TX,
Neema Shettyb9451242012-02-16 15:37:59 -08001620 .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
1621 .ops = &msm_be_ops,
1622 },
Neema Shetty3c9d2862012-03-11 01:25:32 -08001623 {
1624 .name = LPASS_BE_SLIMBUS_1_RX,
1625 .stream_name = "Slimbus1 Playback",
1626 .cpu_dai_name = "msm-dai-q6.16386",
1627 .platform_name = "msm-pcm-routing",
1628 .codec_name = "msm-stub-codec.1",
1629 .codec_dai_name = "msm-stub-rx",
1630 .no_pcm = 1,
1631 .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
1632 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
1633 .ops = &msm_slimbus_1_be_ops,
1634
1635 },
1636 {
1637 .name = LPASS_BE_SLIMBUS_1_TX,
1638 .stream_name = "Slimbus1 Capture",
1639 .cpu_dai_name = "msm-dai-q6.16387",
1640 .platform_name = "msm-pcm-routing",
1641 .codec_name = "msm-stub-codec.1",
1642 .codec_dai_name = "msm-stub-tx",
1643 .no_pcm = 1,
1644 .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
1645 .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
1646 .ops = &msm_slimbus_1_be_ops,
1647 },
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001648 {
1649 .name = "SLIMBUS_2 Hostless",
1650 .stream_name = "SLIMBUS_2 Hostless",
1651 .cpu_dai_name = "msm-dai-q6.16389",
1652 .platform_name = "msm-pcm-hostless",
1653 .codec_name = "tabla_codec",
1654 .codec_dai_name = "tabla_tx2",
Swaminathan Sathappan630c5a42012-05-10 17:33:01 -07001655 .ignore_suspend = 1,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001656 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1657 .ops = &msm_be_ops,
1658 },
1659
Helen Zeng8f925502012-03-05 16:50:17 -08001660 /* Incall Music Back End DAI Link */
1661 {
1662 .name = LPASS_BE_SLIMBUS_4_RX,
1663 .stream_name = "Slimbus4 Playback",
1664 .cpu_dai_name = "msm-dai-q6.16392",
1665 .platform_name = "msm-pcm-routing",
1666 .codec_name = "msm-stub-codec.1",
1667 .codec_dai_name = "msm-stub-rx",
1668 .no_pcm = 1,
1669 .no_codec = 1,
1670 .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
1671 .be_hw_params_fixup = msm_be_hw_params_fixup,
1672 .ops = &msm_slimbus_4_be_ops,
1673 },
1674 /* Incall Record Back End DAI Link */
1675 {
1676 .name = LPASS_BE_SLIMBUS_4_TX,
1677 .stream_name = "Slimbus4 Capture",
1678 .cpu_dai_name = "msm-dai-q6.16393",
1679 .platform_name = "msm-pcm-routing",
1680 .codec_name = "msm-stub-codec.1",
1681 .codec_dai_name = "msm-stub-tx",
1682 .no_pcm = 1,
1683 .no_codec = 1,
1684 .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
1685 .be_hw_params_fixup = msm_be_hw_params_fixup,
1686 .init = &msm_incall_rec_init,
1687 .ops = &msm_slimbus_4_be_ops,
1688 },
Neema Shettye5cae8e2012-04-27 18:07:37 -07001689 {
1690 .name = LPASS_BE_STUB_1_TX,
1691 .stream_name = "Stub1 Capture",
1692 .cpu_dai_name = "msm-dai-stub",
1693 .platform_name = "msm-pcm-routing",
1694 .codec_name = "tabla_codec",
1695 .codec_dai_name = "tabla_tx3",
1696 .no_pcm = 1,
1697 .be_id = MSM_BACKEND_DAI_EXTPROC_EC_TX,
1698 /* This BE is used for external EC reference from codec. Since
1699 * Rx is fed as reference for EC, the config of this DAI is
1700 * based on that of the Rx path.
1701 */
1702 .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
1703 .ops = &msm_be_ops,
1704 },
Neema Shetty74131ac2012-05-09 13:35:26 -07001705 {
1706
1707 .name = LPASS_BE_SLIMBUS_3_RX,
1708 .stream_name = "Slimbus3 Playback",
1709 .cpu_dai_name = "msm-dai-q6.16390",
1710 .platform_name = "msm-pcm-routing",
1711 .codec_name = "msm-stub-codec.1",
1712 .codec_dai_name = "msm-stub-rx",
1713 .init = &msm_slim_3_init,
1714 .no_pcm = 1,
1715 .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
1716 .be_hw_params_fixup = msm_slim_3_rx_be_hw_params_fixup,
1717 .ops = &msm_slimbus_3_be_ops,
1718 },
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001719};
1720
1721struct snd_soc_card snd_soc_card_msm = {
Swaminathan Sathappanc165a3a2012-02-29 12:44:31 -08001722 .name = "apq8064-tabla-snd-card",
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001723 .dai_link = msm_dai,
1724 .num_links = ARRAY_SIZE(msm_dai),
1725};
1726
1727static struct platform_device *msm_snd_device;
1728
1729static int msm_configure_headset_mic_gpios(void)
1730{
1731 int ret;
1732 struct pm_gpio param = {
1733 .direction = PM_GPIO_DIR_OUT,
1734 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
1735 .output_value = 1,
1736 .pull = PM_GPIO_PULL_NO,
1737 .vin_sel = PM_GPIO_VIN_S4,
1738 .out_strength = PM_GPIO_STRENGTH_MED,
1739 .function = PM_GPIO_FUNC_NORMAL,
1740 };
1741
1742 ret = gpio_request(PM8921_GPIO_PM_TO_SYS(23), "AV_SWITCH");
1743 if (ret) {
1744 pr_err("%s: Failed to request gpio %d\n", __func__,
1745 PM8921_GPIO_PM_TO_SYS(23));
1746 return ret;
1747 }
1748
1749 ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(23), &param);
1750 if (ret)
1751 pr_err("%s: Failed to configure gpio %d\n", __func__,
1752 PM8921_GPIO_PM_TO_SYS(23));
1753 else
1754 gpio_direction_output(PM8921_GPIO_PM_TO_SYS(23), 0);
1755
1756 ret = gpio_request(PM8921_GPIO_PM_TO_SYS(35), "US_EURO_SWITCH");
1757 if (ret) {
1758 pr_err("%s: Failed to request gpio %d\n", __func__,
1759 PM8921_GPIO_PM_TO_SYS(35));
1760 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
1761 return ret;
1762 }
1763 ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(35), &param);
1764 if (ret)
1765 pr_err("%s: Failed to configure gpio %d\n", __func__,
1766 PM8921_GPIO_PM_TO_SYS(35));
1767 else
1768 gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 0);
1769
1770 return 0;
1771}
1772static void msm_free_headset_mic_gpios(void)
1773{
1774 if (msm_headset_gpios_configured) {
1775 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
1776 gpio_free(PM8921_GPIO_PM_TO_SYS(35));
1777 }
1778}
1779
1780static int __init msm_audio_init(void)
1781{
1782 int ret;
1783
Santosh Mardi911b27fd2012-04-04 03:09:01 +05301784 if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001785 pr_err("%s: Not the right machine type\n", __func__);
1786 return -ENODEV;
1787 }
1788
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001789 mbhc_cfg.calibration = def_tabla_mbhc_cal();
1790 if (!mbhc_cfg.calibration) {
Joonwoo Park0976d012011-12-22 11:48:18 -08001791 pr_err("Calibration data allocation failed\n");
1792 return -ENOMEM;
1793 }
1794
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001795 msm_snd_device = platform_device_alloc("soc-audio", 0);
1796 if (!msm_snd_device) {
1797 pr_err("Platform device allocation failed\n");
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001798 kfree(mbhc_cfg.calibration);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001799 return -ENOMEM;
1800 }
1801
1802 platform_set_drvdata(msm_snd_device, &snd_soc_card_msm);
1803 ret = platform_device_add(msm_snd_device);
1804 if (ret) {
1805 platform_device_put(msm_snd_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001806 kfree(mbhc_cfg.calibration);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001807 return ret;
1808 }
1809
1810 if (msm_configure_headset_mic_gpios()) {
1811 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1812 msm_headset_gpios_configured = 0;
1813 } else
1814 msm_headset_gpios_configured = 1;
1815
1816 return ret;
1817
1818}
1819module_init(msm_audio_init);
1820
1821static void __exit msm_audio_exit(void)
1822{
Santosh Mardi911b27fd2012-04-04 03:09:01 +05301823 if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001824 pr_err("%s: Not the right machine type\n", __func__);
1825 return ;
1826 }
1827 msm_free_headset_mic_gpios();
1828 platform_device_unregister(msm_snd_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001829 kfree(mbhc_cfg.calibration);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001830}
1831module_exit(msm_audio_exit);
1832
1833MODULE_DESCRIPTION("ALSA SoC msm");
1834MODULE_LICENSE("GPL v2");