blob: 8711f0863931df390c2e741a32aea89b31649702 [file] [log] [blame]
Laxminath Kasam852c7812013-03-07 20:03:37 +05301/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05302 *
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>
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080016#include <linux/mfd/pm8xxx/spk.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053017#include <linux/platform_device.h>
18#include <linux/gpio.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053019#include <linux/slab.h>
20#include <sound/core.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053023#include <sound/pcm.h>
24#include <sound/jack.h>
25#include <asm/mach-types.h>
26#include <mach/socinfo.h>
Laxminath Kasam852c7812013-03-07 20:03:37 +053027#include <linux/mfd/pm8xxx/pm8038.h>
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053028#include "msm-pcm-routing.h"
29#include "../codecs/wcd9304.h"
30
31/* 8930 machine driver */
32
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053033#define MSM8930_SPK_ON 1
34#define MSM8930_SPK_OFF 0
35
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053036#define BTSCO_RATE_8KHZ 8000
37#define BTSCO_RATE_16KHZ 16000
38
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080039#define SPK_AMP_POS 0x1
40#define SPK_AMP_NEG 0x2
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -070041#define SPKR_BOOST_GPIO 15
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -070042#define LEFT_SPKR_AMPL_GPIO 15
Bhalchandra Gajare97676792012-05-22 17:41:45 -070043#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053044#define SITAR_EXT_CLK_RATE 12288000
45
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070046#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053047#define SITAR_MBHC_DEF_RLOADS 5
48
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070049#define GPIO_AUX_PCM_DOUT 63
50#define GPIO_AUX_PCM_DIN 64
51#define GPIO_AUX_PCM_SYNC 65
52#define GPIO_AUX_PCM_CLK 66
53
Laxminath Kasam852c7812013-03-07 20:03:37 +053054#define GPIO_HS_SW_SEL 66
55#define GPIO_HS_DET 50
56
57#define PM8038_GPIO_BASE NR_GPIO_IRQS
58#define PM8038_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8038_GPIO_BASE)
59
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053060static int msm8930_spk_control;
61static int msm8930_slim_0_rx_ch = 1;
62static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070063static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053064
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080065static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053066static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
67static int msm8930_btsco_ch = 1;
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -080068static int hdmi_rate_variable;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053069static struct clk *codec_clk;
70static int clk_users;
71
72static int msm8930_headset_gpios_configured;
73
74static struct snd_soc_jack hs_jack;
75static struct snd_soc_jack button_jack;
Kuirong Wang892c9ad2012-09-20 11:43:17 -070076static atomic_t auxpcm_rsc_ref;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070077
78static int msm8930_enable_codec_ext_clk(
79 struct snd_soc_codec *codec, int enable,
80 bool dapm);
81
Laxminath Kasam852c7812013-03-07 20:03:37 +053082static u32 spkr_boost_enable_gpio = PM8038_GPIO_PM_TO_SYS(0x1);
83
84struct pm_gpio SPKR_ON = {
85 .direction = PM_GPIO_DIR_OUT,
86 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
87 .output_value = 1,
88 .pull = PM_GPIO_PULL_NO,
89 .vin_sel = PM_GPIO_VIN_S4,
90 .out_strength = PM_GPIO_STRENGTH_MED,
91 .function = PM_GPIO_FUNC_NORMAL,
92};
93struct pm_gpio SPKR_OFF = {
94 .direction = PM_GPIO_DIR_OUT,
95 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
96 .output_value = 0,
97 .pull = PM_GPIO_PULL_NO,
98 .vin_sel = PM_GPIO_VIN_S4,
99 .out_strength = PM_GPIO_STRENGTH_MED,
100 .function = PM_GPIO_FUNC_NORMAL,
101};
102
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700103static struct sitar_mbhc_config mbhc_cfg = {
104 .headset_jack = &hs_jack,
105 .button_jack = &button_jack,
106 .read_fw_bin = false,
107 .calibration = NULL,
108 .micbias = SITAR_MICBIAS2,
109 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
110 .mclk_rate = SITAR_EXT_CLK_RATE,
111 .gpio = 0,
112 .gpio_irq = 0,
113 .gpio_level_insert = 1,
114};
115
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530116static void msm8930_ext_control(struct snd_soc_codec *codec)
117{
118 struct snd_soc_dapm_context *dapm = &codec->dapm;
119
120 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
121 if (msm8930_spk_control == MSM8930_SPK_ON) {
122 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800123 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530124 } else {
125 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800126 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530127 }
128
129 snd_soc_dapm_sync(dapm);
130}
131
132static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
133 struct snd_ctl_elem_value *ucontrol)
134{
135 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
136 ucontrol->value.integer.value[0] = msm8930_spk_control;
137 return 0;
138}
139static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
140 struct snd_ctl_elem_value *ucontrol)
141{
142 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
143
144 pr_debug("%s()\n", __func__);
145 if (msm8930_spk_control == ucontrol->value.integer.value[0])
146 return 0;
147
148 msm8930_spk_control = ucontrol->value.integer.value[0];
149 msm8930_ext_control(codec);
150 return 1;
151}
152
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700153static int msm8930_cfg_spkr_gpio(int gpio,
154 int enable, const char *gpio_label)
155{
156 int ret = 0;
157
158 pr_debug("%s: Configure %s GPIO %u",
159 __func__, gpio_label, gpio);
160 ret = gpio_request(gpio, gpio_label);
161 if (ret)
162 return ret;
163
164 pr_debug("%s: Enable %s gpio %u\n",
165 __func__, gpio_label, gpio);
166 gpio_direction_output(gpio, enable);
167
168 return ret;
169}
170
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800171static void msm8960_ext_spk_power_amp_on(u32 spk)
172{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700173 int ret = 0;
174
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800175 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
176 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
177 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
178
179 pr_debug("%s() External Bottom Speaker Ampl already "
180 "turned on. spk = 0x%08x\n", __func__, spk);
181 return;
182 }
183
184 msm8930_ext_spk_pamp |= spk;
185
186 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
187 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
188
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700189 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
190 ret = msm8930_cfg_spkr_gpio(
191 LEFT_SPKR_AMPL_GPIO,
192 1, "LEFT_SPKR_AMPL");
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700193 if (ret) {
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700194 pr_err("%s: Failed to config ampl gpio %u\n",
195 __func__, LEFT_SPKR_AMPL_GPIO);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700196 return;
197 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700198 } else {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700199
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700200 if (machine_is_msm8930_mtp()
201 || machine_is_msm8930_fluid()) {
202 ret = msm8930_cfg_spkr_gpio(
203 SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
204 if (ret) {
205 pr_err("%s: Failure: spkr boost gpio %u\n",
206 __func__, SPKR_BOOST_GPIO);
207 return;
208 }
Laxminath Kasam852c7812013-03-07 20:03:37 +0530209 } else if (socinfo_get_platform_subtype() ==
210 PLATFORM_SUBTYPE_SGLTE) {
211 ret = pm8xxx_gpio_config(
212 spkr_boost_enable_gpio,
213 &SPKR_ON);
214 if (ret) {
215 pr_err("%s: Failure: spkr" \
216 "boost gpio ON %u\n",
217 __func__, spkr_boost_enable_gpio);
218 return;
219 } else {
220 pr_debug("%s:Config PMIC8038" \
221 "gpio for speaker ON successfully\n",
222 __func__);
223 }
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700224 }
225 pm8xxx_spk_enable(MSM8930_SPK_ON);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700226 }
227
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800228 pr_debug("%s: slepping 4 ms after turning on external "
229 " Left Speaker Ampl\n", __func__);
230 usleep_range(4000, 4000);
231 }
232
233 } else {
234
235 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
236 __func__, spk);
237 return;
238 }
239}
240
241static void msm8960_ext_spk_power_amp_off(u32 spk)
242{
Laxminath Kasam852c7812013-03-07 20:03:37 +0530243 int ret = 0;
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800244 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
245 if (!msm8930_ext_spk_pamp)
246 return;
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700247
248 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
249 gpio_free(LEFT_SPKR_AMPL_GPIO);
250 msm8930_ext_spk_pamp = 0;
251 return;
252 }
253
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700254 if (machine_is_msm8930_mtp()
255 || machine_is_msm8930_fluid()) {
256 pr_debug("%s: Free speaker boost gpio %u\n",
257 __func__, SPKR_BOOST_GPIO);
258 gpio_direction_output(SPKR_BOOST_GPIO, 0);
259 gpio_free(SPKR_BOOST_GPIO);
Laxminath Kasam852c7812013-03-07 20:03:37 +0530260 } else if (socinfo_get_platform_subtype() ==
261 PLATFORM_SUBTYPE_SGLTE) {
262 ret = pm8xxx_gpio_config(spkr_boost_enable_gpio,
263 &SPKR_OFF);
264 if (ret) {
265 pr_err("%s: Failure: spkr boost gpio OFF %u\n",
266 __func__, spkr_boost_enable_gpio);
267 return;
268 } else {
269 pr_debug("%s:Config PMIC8038 gpio for speaker" \
270 " OFF successfully\n", __func__);
271 }
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700272 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800273
274 pm8xxx_spk_enable(MSM8930_SPK_OFF);
275 msm8930_ext_spk_pamp = 0;
276 pr_debug("%s: slepping 4 ms after turning on external "
277 " Left Speaker Ampl\n", __func__);
278 usleep_range(4000, 4000);
279
280 } else {
281
282 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
283 __func__, spk);
284 return;
285 }
286}
287
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530288static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
289 struct snd_kcontrol *k, int event)
290{
291 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800292 if (SND_SOC_DAPM_EVENT_ON(event)) {
293 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
294 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
295 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
296 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
297 else {
298 pr_err("%s() Invalid Speaker Widget = %s\n",
299 __func__, w->name);
300 return -EINVAL;
301 }
302 } else {
303 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
304 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
305 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
306 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
307 else {
308 pr_err("%s() Invalid Speaker Widget = %s\n",
309 __func__, w->name);
310 return -EINVAL;
311 }
312 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530313 return 0;
314}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800315
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700316static int msm8930_enable_codec_ext_clk(
317 struct snd_soc_codec *codec, int enable,
318 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530319{
320 pr_debug("%s: enable = %d\n", __func__, enable);
321 if (enable) {
322 clk_users++;
323 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
324 if (clk_users != 1)
325 return 0;
326
327 if (codec_clk) {
328 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800329 clk_prepare_enable(codec_clk);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700330 sitar_mclk_enable(codec, 1, dapm);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530331 } else {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800332 pr_err("%s: Error setting Sitar MCLK\n", __func__);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530333 clk_users--;
334 return -EINVAL;
335 }
336 } else {
337 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
338 if (clk_users == 0)
339 return 0;
340 clk_users--;
341 if (!clk_users) {
342 pr_debug("%s: disabling MCLK. clk_users = %d\n",
343 __func__, clk_users);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700344 sitar_mclk_enable(codec, 0, dapm);
Bhalchandra Gajare2776af12012-04-27 16:59:39 -0700345 clk_disable_unprepare(codec_clk);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530346 }
347 }
348 return 0;
349}
350
351static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
352 struct snd_kcontrol *kcontrol, int event)
353{
354 pr_debug("%s: event = %d\n", __func__, event);
355
356 switch (event) {
357 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700358 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530359 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700360 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530361 }
362 return 0;
363}
364
365static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
366
367 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
368 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
369
370 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800371 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530372
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530373 SND_SOC_DAPM_MIC("Headset Mic", NULL),
374 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
375 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
376 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
377
378 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
379 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
380 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
381 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
382
383};
384
385static const struct snd_soc_dapm_route common_audio_map[] = {
386
387 {"RX_BIAS", NULL, "MCLK"},
388 {"LDO_H", NULL, "MCLK"},
389
390 {"MIC BIAS1 Internal1", NULL, "MCLK"},
391 {"MIC BIAS2 Internal1", NULL, "MCLK"},
392
393 /* Speaker path */
394 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800395 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530396
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800397 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700398 {"AMIC2", NULL, "MIC BIAS2 External"},
399 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530400
401 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700402 {"AMIC1", NULL, "MIC BIAS2 External"},
403 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800404
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700405 {"AMIC3", NULL, "MIC BIAS2 External"},
406 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530407
408 {"HEADPHONE", NULL, "LDO_H"},
409
410 /**
411 * The digital Mic routes are setup considering
412 * fluid as default device.
413 */
414
415 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700416 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530417 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700418 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530419 */
420 {"DMIC1", NULL, "MIC BIAS1 External"},
421 {"MIC BIAS1 External", NULL, "Digital Mic1"},
422
423 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700424 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530425 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700426 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530427 */
428 {"DMIC2", NULL, "MIC BIAS1 External"},
429 {"MIC BIAS1 External", NULL, "Digital Mic2"},
430 /**
431 * Digital Mic3. Back Bottom Digital Mic on Fluid.
432 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800433 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530434 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800435 {"DMIC3", NULL, "MIC BIAS1 External"},
436 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530437
438 /**
439 * Digital Mic4. Back top Digital Mic on Fluid.
440 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800441 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530442 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800443 {"DMIC4", NULL, "MIC BIAS1 External"},
444 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530445
446
447};
448
Laxminath Kasam852c7812013-03-07 20:03:37 +0530449static const struct snd_soc_dapm_route common_audio_map_sglte[] = {
450
451 {"RX_BIAS", NULL, "MCLK"},
452 {"LDO_H", NULL, "MCLK"},
453
454 {"MIC BIAS1 Internal1", NULL, "MCLK"},
455 {"MIC BIAS2 Internal1", NULL, "MCLK"},
456
457 /* Speaker path */
458 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
459 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
460
461 /* Headset Mic */
462 {"AMIC2", NULL, "MIC BIAS2 External"},
463 {"MIC BIAS2 External", NULL, "Headset Mic"},
464
465 /* Microphone path */
466 {"AMIC1", NULL, "MIC BIAS1 External"},
467 {"MIC BIAS1 External", NULL, "ANCLeft Headset Mic"},
468
469 {"AMIC3", NULL, "MIC BIAS1 External"},
470 {"MIC BIAS1 External", NULL, "ANCRight Headset Mic"},
471
472 {"HEADPHONE", NULL, "LDO_H"},
473};
474
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530475static const char *spk_function[] = {"Off", "On"};
476static const char *slim0_rx_ch_text[] = {"One", "Two"};
477static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
478
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800479static const char * const hdmi_rate[] = {"Default", "Variable"};
480
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530481static const struct soc_enum msm8930_enum[] = {
482 SOC_ENUM_SINGLE_EXT(2, spk_function),
483 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
484 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800485 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530486};
487
488static const char *btsco_rate_text[] = {"8000", "16000"};
489static const struct soc_enum msm8930_btsco_enum[] = {
490 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
491};
492
493static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
494 struct snd_ctl_elem_value *ucontrol)
495{
496 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800497 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530498 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
499 return 0;
500}
501
502static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
503 struct snd_ctl_elem_value *ucontrol)
504{
505 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
506
507 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800508 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530509 return 1;
510}
511
512static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
513 struct snd_ctl_elem_value *ucontrol)
514{
515 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
516 msm8930_slim_0_tx_ch);
517 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
518 return 0;
519}
520
521static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
522 struct snd_ctl_elem_value *ucontrol)
523{
524 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
525
526 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
527 msm8930_slim_0_tx_ch);
528 return 1;
529}
530
531static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
532 struct snd_ctl_elem_value *ucontrol)
533{
534 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
535 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
536 return 0;
537}
538
539static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
540 struct snd_ctl_elem_value *ucontrol)
541{
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700542
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530543 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700544 case 8000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530545 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
546 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700547 case 16000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530548 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
549 break;
550 default:
551 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
552 break;
553 }
554 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
555 return 0;
556}
557
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700558static const char *pmic_spk_gain_text[] = {
559 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
560 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
561 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
562};
563
564static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
565 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
566 pmic_spk_gain_text),
567};
568
569static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
570 struct snd_ctl_elem_value *ucontrol)
571{
572 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
573 msm8930_pmic_spk_gain);
574 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
575 return 0;
576}
577
578static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
579 struct snd_ctl_elem_value *ucontrol)
580{
581 int ret = 0;
582 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700583 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
584 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700585 pr_debug("%s: msm8930_pmic_spk_gain = %d"
586 " ucontrol->value.integer.value[0] = %d\n", __func__,
587 msm8930_pmic_spk_gain,
588 (int) ucontrol->value.integer.value[0]);
589 return ret;
590}
591
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800592static int msm8930_hdmi_rate_put(struct snd_kcontrol *kcontrol,
593 struct snd_ctl_elem_value *ucontrol)
594{
595 hdmi_rate_variable = ucontrol->value.integer.value[0];
596 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
597 return 0;
598}
599
600static int msm8930_hdmi_rate_get(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
602{
603 ucontrol->value.integer.value[0] = hdmi_rate_variable;
604 return 0;
605}
606
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530607static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
608 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
609 msm8930_set_spk),
610 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
611 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
612 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
613 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700614 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
615 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530616 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
617 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800618 SOC_ENUM_EXT("HDMI RX Rate", msm8930_enum[3],
619 msm8930_hdmi_rate_get,
620 msm8930_hdmi_rate_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530621};
622
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800623static void *def_sitar_mbhc_cal(void)
624{
625 void *sitar_cal;
626 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
627 u16 *btn_low, *btn_high;
628 u8 *n_ready, *n_cic, *gain;
629
630 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
631 SITAR_MBHC_DEF_RLOADS),
632 GFP_KERNEL);
633 if (!sitar_cal) {
634 pr_err("%s: out of memory\n", __func__);
635 return NULL;
636 }
637
638#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
639 S(t_ldoh, 100);
640 S(t_bg_fast_settle, 100);
641 S(t_shutdown_plug_rem, 255);
642 S(mbhc_nsa, 4);
643 S(mbhc_navg, 4);
644#undef S
645#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
646 S(mic_current, SITAR_PID_MIC_5_UA);
647 S(hph_current, SITAR_PID_MIC_5_UA);
648 S(t_mic_pid, 100);
649 S(t_ins_complete, 250);
650 S(t_ins_retry, 200);
651#undef S
652#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
653 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700654 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800655#undef S
656#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
657 S(c[0], 62);
658 S(c[1], 124);
659 S(nc, 1);
660 S(n_meas, 3);
661 S(mbhc_nsc, 11);
662 S(n_btn_meas, 1);
663 S(n_btn_con, 2);
664 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
665 S(v_btn_press_delta_sta, 100);
666 S(v_btn_press_delta_cic, 50);
667#undef S
668 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
669 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
670 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
671 btn_low[0] = -50;
672 btn_high[0] = 10;
673 btn_low[1] = 11;
674 btn_high[1] = 38;
675 btn_low[2] = 39;
676 btn_high[2] = 64;
677 btn_low[3] = 65;
678 btn_high[3] = 91;
679 btn_low[4] = 92;
680 btn_high[4] = 115;
681 btn_low[5] = 116;
682 btn_high[5] = 141;
683 btn_low[6] = 142;
684 btn_high[6] = 163;
685 btn_low[7] = 164;
686 btn_high[7] = 250;
687 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
688 n_ready[0] = 48;
689 n_ready[1] = 38;
690 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
691 n_cic[0] = 60;
692 n_cic[1] = 47;
693 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
694 gain[0] = 11;
695 gain[1] = 9;
696
697 return sitar_cal;
698}
699
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530700static int msm8930_hw_params(struct snd_pcm_substream *substream,
701 struct snd_pcm_hw_params *params)
702{
703 struct snd_soc_pcm_runtime *rtd = substream->private_data;
704 struct snd_soc_dai *codec_dai = rtd->codec_dai;
705 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
706 int ret = 0;
707 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
708 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
709
710 pr_debug("%s: ch=%d\n", __func__,
711 msm8930_slim_0_rx_ch);
712 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
713 ret = snd_soc_dai_get_channel_map(codec_dai,
714 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
715 if (ret < 0) {
716 pr_err("%s: failed to get codec chan map\n", __func__);
717 goto end;
718 }
719
720 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
721 msm8930_slim_0_rx_ch, rx_ch);
722 if (ret < 0) {
723 pr_err("%s: failed to set cpu chan map\n", __func__);
724 goto end;
725 }
726 ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
727 msm8930_slim_0_rx_ch, rx_ch);
728 if (ret < 0) {
729 pr_err("%s: failed to set codec channel map\n",
730 __func__);
731 goto end;
732 }
733 } else {
734 ret = snd_soc_dai_get_channel_map(codec_dai,
735 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
736 if (ret < 0) {
737 pr_err("%s: failed to get codec chan map\n", __func__);
738 goto end;
739 }
740 ret = snd_soc_dai_set_channel_map(cpu_dai,
741 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
742 if (ret < 0) {
743 pr_err("%s: failed to set cpu chan map\n", __func__);
744 goto end;
745 }
746 ret = snd_soc_dai_set_channel_map(codec_dai,
747 msm8930_slim_0_tx_ch, tx_ch, 0, 0);
748 if (ret < 0) {
749 pr_err("%s: failed to set codec channel map\n",
750 __func__);
751 goto end;
752 }
753
754 }
755end:
756 return ret;
757}
758
759static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
760{
761 int err;
762 struct snd_soc_codec *codec = rtd->codec;
763 struct snd_soc_dapm_context *dapm = &codec->dapm;
764 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
765
766 pr_debug("%s()\n", __func__);
767
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530768 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
769 ARRAY_SIZE(msm8930_dapm_widgets));
770
Laxminath Kasam852c7812013-03-07 20:03:37 +0530771 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
772 snd_soc_dapm_add_routes(dapm, common_audio_map_sglte,
773 ARRAY_SIZE(common_audio_map_sglte));
774 else
775 snd_soc_dapm_add_routes(dapm, common_audio_map,
776 ARRAY_SIZE(common_audio_map));
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530777
778 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800779 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530780
781 snd_soc_dapm_sync(dapm);
782
783 err = snd_soc_jack_new(codec, "Headset Jack",
784 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
785 &hs_jack);
786 if (err) {
787 pr_err("failed to create new jack\n");
788 return err;
789 }
790
791 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700792 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530793 if (err) {
794 pr_err("failed to create new jack\n");
795 return err;
796 }
797 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800798
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700799 mbhc_cfg.gpio = 37;
Laxminath Kasam852c7812013-03-07 20:03:37 +0530800 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
801 mbhc_cfg.gpio = GPIO_HS_DET;
802
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700803 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
804 sitar_hs_detect(codec, &mbhc_cfg);
805
Bhalchandra Gajareb28275f2012-08-13 12:32:12 -0700806 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
807 /* Initialize default PMIC speaker gain */
808 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
809 }
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700810
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530811 return 0;
812}
813
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530814static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
815 struct snd_pcm_hw_params *params)
816{
817 struct snd_interval *rate = hw_param_interval(params,
818 SNDRV_PCM_HW_PARAM_RATE);
819
820 struct snd_interval *channels = hw_param_interval(params,
821 SNDRV_PCM_HW_PARAM_CHANNELS);
822
823 pr_debug("%s()\n", __func__);
824 rate->min = rate->max = 48000;
825 channels->min = channels->max = msm8930_slim_0_rx_ch;
826
827 return 0;
828}
829
830static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
831 struct snd_pcm_hw_params *params)
832{
833 struct snd_interval *rate = hw_param_interval(params,
834 SNDRV_PCM_HW_PARAM_RATE);
835
836 struct snd_interval *channels = hw_param_interval(params,
837 SNDRV_PCM_HW_PARAM_CHANNELS);
838
839 pr_debug("%s()\n", __func__);
840 rate->min = rate->max = 48000;
841 channels->min = channels->max = msm8930_slim_0_tx_ch;
842
843 return 0;
844}
845
846static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
847 struct snd_pcm_hw_params *params)
848{
849 struct snd_interval *rate = hw_param_interval(params,
850 SNDRV_PCM_HW_PARAM_RATE);
851
852 pr_debug("%s()\n", __func__);
853 rate->min = rate->max = 48000;
854
855 return 0;
856}
857
858static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
859 struct snd_pcm_hw_params *params)
860{
861 struct snd_interval *rate = hw_param_interval(params,
862 SNDRV_PCM_HW_PARAM_RATE);
863
864 struct snd_interval *channels = hw_param_interval(params,
865 SNDRV_PCM_HW_PARAM_CHANNELS);
866
Vicky Sehrawat53f5c2e2012-11-05 17:54:13 -0800867 if (!hdmi_rate_variable)
868 rate->min = rate->max = 48000;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530869 channels->min = channels->max = 2;
870
871 return 0;
872}
873
874static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
875 struct snd_pcm_hw_params *params)
876{
877 struct snd_interval *rate = hw_param_interval(params,
878 SNDRV_PCM_HW_PARAM_RATE);
879
880 struct snd_interval *channels = hw_param_interval(params,
881 SNDRV_PCM_HW_PARAM_CHANNELS);
882
883 rate->min = rate->max = msm8930_btsco_rate;
884 channels->min = channels->max = msm8930_btsco_ch;
885
886 return 0;
887}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530888
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700889static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
890 struct snd_pcm_hw_params *params)
891{
892 struct snd_interval *rate = hw_param_interval(params,
893 SNDRV_PCM_HW_PARAM_RATE);
894
895 struct snd_interval *channels = hw_param_interval(params,
896 SNDRV_PCM_HW_PARAM_CHANNELS);
897
898 /* PCM only supports mono output with 8khz sample rate */
899 rate->min = rate->max = 8000;
900 channels->min = channels->max = 1;
901
902 return 0;
903}
904
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -0700905static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
906 struct snd_pcm_hw_params *params)
907{
908 struct snd_interval *rate = hw_param_interval(params,
909 SNDRV_PCM_HW_PARAM_RATE);
910
911 pr_debug("%s()\n", __func__);
912 rate->min = rate->max = 48000;
913
914 return 0;
915}
916
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700917static int msm8930_aux_pcm_get_gpios(void)
918{
919 int ret = 0;
920
921 pr_debug("%s\n", __func__);
922
923 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
924 if (ret < 0) {
925 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
926 __func__, GPIO_AUX_PCM_DOUT);
927
928 goto fail_dout;
929 }
930
931 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
932 if (ret < 0) {
933 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
934 __func__, GPIO_AUX_PCM_DIN);
935 goto fail_din;
936 }
937
938 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
939 if (ret < 0) {
940 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
941 __func__, GPIO_AUX_PCM_SYNC);
942 goto fail_sync;
943 }
944
945 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
946 if (ret < 0) {
947 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
948 __func__, GPIO_AUX_PCM_CLK);
949 goto fail_clk;
950 }
951
952 return 0;
953
954fail_clk:
955 gpio_free(GPIO_AUX_PCM_SYNC);
956fail_sync:
957 gpio_free(GPIO_AUX_PCM_DIN);
958fail_din:
959 gpio_free(GPIO_AUX_PCM_DOUT);
960fail_dout:
961
962 return ret;
963}
964
965static int msm8930_aux_pcm_free_gpios(void)
966{
967 gpio_free(GPIO_AUX_PCM_DIN);
968 gpio_free(GPIO_AUX_PCM_DOUT);
969 gpio_free(GPIO_AUX_PCM_SYNC);
970 gpio_free(GPIO_AUX_PCM_CLK);
971
972 return 0;
973}
974
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530975static int msm8930_startup(struct snd_pcm_substream *substream)
976{
977 pr_debug("%s(): substream = %s stream = %d\n", __func__,
978 substream->name, substream->stream);
979 return 0;
980}
981
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700982static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
983{
984 int ret = 0;
985
Kuirong Wang892c9ad2012-09-20 11:43:17 -0700986 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
987 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
988 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
989 ret = msm8930_aux_pcm_get_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700990 if (ret < 0) {
991 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
992 return -EINVAL;
993 }
994 return 0;
995
996}
997
998static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
999{
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001000 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1001 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1002 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
1003 msm8930_aux_pcm_free_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001004}
1005
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301006static void msm8930_shutdown(struct snd_pcm_substream *substream)
1007{
1008 pr_debug("%s(): substream = %s stream = %d\n", __func__,
1009 substream->name, substream->stream);
1010}
1011
1012static struct snd_soc_ops msm8930_be_ops = {
1013 .startup = msm8930_startup,
1014 .hw_params = msm8930_hw_params,
1015 .shutdown = msm8930_shutdown,
1016};
1017
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001018static struct snd_soc_ops msm8930_auxpcm_be_ops = {
1019 .startup = msm8930_auxpcm_startup,
1020 .shutdown = msm8930_auxpcm_shutdown,
1021};
1022
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301023/* Digital audio interface glue - connects codec <---> CPU */
1024static struct snd_soc_dai_link msm8930_dai[] = {
1025 /* FrontEnd DAI Links */
1026 {
1027 .name = "MSM8930 Media1",
1028 .stream_name = "MultiMedia1",
1029 .cpu_dai_name = "MultiMedia1",
1030 .platform_name = "msm-pcm-dsp",
1031 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001032 .codec_dai_name = "snd-soc-dummy-dai",
1033 .codec_name = "snd-soc-dummy",
1034 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1035 .ignore_suspend = 1,
1036 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301037 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1038 },
1039 {
1040 .name = "MSM8930 Media2",
1041 .stream_name = "MultiMedia2",
1042 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +05301043 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301044 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001045 .codec_dai_name = "snd-soc-dummy-dai",
1046 .codec_name = "snd-soc-dummy",
1047 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1048 .ignore_suspend = 1,
1049 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301050 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1051 },
1052 {
1053 .name = "Circuit-Switch Voice",
1054 .stream_name = "CS-Voice",
1055 .cpu_dai_name = "CS-VOICE",
1056 .platform_name = "msm-pcm-voice",
1057 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001058 .codec_dai_name = "snd-soc-dummy-dai",
1059 .codec_name = "snd-soc-dummy",
1060 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301061 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
1062 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1063 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001064 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301065 },
1066 {
1067 .name = "MSM VoIP",
1068 .stream_name = "VoIP",
1069 .cpu_dai_name = "VoIP",
1070 .platform_name = "msm-voip-dsp",
1071 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001072 .codec_dai_name = "snd-soc-dummy-dai",
1073 .codec_name = "snd-soc-dummy",
1074 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1075 .ignore_suspend = 1,
1076 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301077 .be_id = MSM_FRONTEND_DAI_VOIP,
1078 },
1079 {
1080 .name = "MSM8930 LPA",
1081 .stream_name = "LPA",
1082 .cpu_dai_name = "MultiMedia3",
1083 .platform_name = "msm-pcm-lpa",
1084 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001085 .codec_dai_name = "snd-soc-dummy-dai",
1086 .codec_name = "snd-soc-dummy",
1087 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1088 .ignore_suspend = 1,
1089 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301090 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1091 },
1092 /* Hostless PMC purpose */
1093 {
1094 .name = "SLIMBUS_0 Hostless",
1095 .stream_name = "SLIMBUS_0 Hostless",
1096 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1097 .platform_name = "msm-pcm-hostless",
1098 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001099 .codec_dai_name = "snd-soc-dummy-dai",
1100 .codec_name = "snd-soc-dummy",
1101 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301102 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1103 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001104 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301105 /* .be_id = do not care */
1106 },
1107 {
1108 .name = "INT_FM Hostless",
1109 .stream_name = "INT_FM Hostless",
1110 .cpu_dai_name = "INT_FM_HOSTLESS",
1111 .platform_name = "msm-pcm-hostless",
1112 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001113 .codec_dai_name = "snd-soc-dummy-dai",
1114 .codec_name = "snd-soc-dummy",
1115 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301116 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1117 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001118 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301119 /* .be_id = do not care */
1120 },
1121 {
1122 .name = "MSM AFE-PCM RX",
1123 .stream_name = "AFE-PROXY RX",
1124 .cpu_dai_name = "msm-dai-q6.241",
1125 .codec_name = "msm-stub-codec.1",
1126 .codec_dai_name = "msm-stub-rx",
1127 .platform_name = "msm-pcm-afe",
1128 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001129 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301130 },
1131 {
1132 .name = "MSM AFE-PCM TX",
1133 .stream_name = "AFE-PROXY TX",
1134 .cpu_dai_name = "msm-dai-q6.240",
1135 .codec_name = "msm-stub-codec.1",
1136 .codec_dai_name = "msm-stub-tx",
1137 .platform_name = "msm-pcm-afe",
1138 .ignore_suspend = 1,
1139 },
1140 {
1141 .name = "MSM8930 Compr",
1142 .stream_name = "COMPR",
1143 .cpu_dai_name = "MultiMedia4",
1144 .platform_name = "msm-compr-dsp",
1145 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001146 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1147 .codec_dai_name = "snd-soc-dummy-dai",
1148 .codec_name = "snd-soc-dummy",
1149 .ignore_suspend = 1,
1150 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301151 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1152 },
1153 {
1154 .name = "AUXPCM Hostless",
1155 .stream_name = "AUXPCM Hostless",
1156 .cpu_dai_name = "AUXPCM_HOSTLESS",
1157 .platform_name = "msm-pcm-hostless",
1158 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001159 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301160 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1161 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001162 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1163 .codec_dai_name = "snd-soc-dummy-dai",
1164 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301165 },
1166 /* HDMI Hostless */
1167 {
1168 .name = "HDMI_RX_HOSTLESS",
1169 .stream_name = "HDMI_RX_HOSTLESS",
1170 .cpu_dai_name = "HDMI_HOSTLESS",
1171 .platform_name = "msm-pcm-hostless",
1172 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001173 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301174 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301175 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001176 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1177 .codec_dai_name = "snd-soc-dummy-dai",
1178 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301179 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001180 {
1181 .name = "VoLTE",
1182 .stream_name = "VoLTE",
1183 .cpu_dai_name = "VoLTE",
1184 .platform_name = "msm-pcm-voice",
1185 .dynamic = 1,
1186 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1187 SND_SOC_DPCM_TRIGGER_POST},
1188 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1189 .ignore_suspend = 1,
1190 /* this dainlink has playback support */
1191 .ignore_pmdown_time = 1,
1192 .codec_dai_name = "snd-soc-dummy-dai",
1193 .codec_name = "snd-soc-dummy",
1194 .be_id = MSM_FRONTEND_DAI_VOLTE,
1195 },
1196 {
1197 .name = "SGLTE",
1198 .stream_name = "SGLTE",
1199 .cpu_dai_name = "SGLTE",
1200 .platform_name = "msm-pcm-voice",
1201 .dynamic = 1,
1202 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1203 SND_SOC_DPCM_TRIGGER_POST},
1204 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1205 .ignore_suspend = 1,
1206 /* this dainlink has playback support */
1207 .ignore_pmdown_time = 1,
1208 .codec_dai_name = "snd-soc-dummy-dai",
1209 .codec_name = "snd-soc-dummy",
1210 .be_id = MSM_FRONTEND_DAI_SGLTE,
1211 },
1212 {
1213 .name = "MSM8960 LowLatency",
1214 .stream_name = "MultiMedia5",
1215 .cpu_dai_name = "MultiMedia5",
1216 .platform_name = "msm-lowlatency-pcm-dsp",
1217 .dynamic = 1,
1218 .codec_dai_name = "snd-soc-dummy-dai",
1219 .codec_name = "snd-soc-dummy",
1220 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1221 SND_SOC_DPCM_TRIGGER_POST},
1222 .ignore_suspend = 1,
1223 /* this dainlink has playback support */
1224 .ignore_pmdown_time = 1,
1225 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1226 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301227 /* Backend DAI Links */
1228 {
1229 .name = LPASS_BE_SLIMBUS_0_RX,
1230 .stream_name = "Slimbus Playback",
1231 .cpu_dai_name = "msm-dai-q6.16384",
1232 .platform_name = "msm-pcm-routing",
1233 .codec_name = "sitar_codec",
1234 .codec_dai_name = "sitar_rx1",
1235 .no_pcm = 1,
1236 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1237 .init = &msm8930_audrx_init,
1238 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1239 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001240 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301241 },
1242 {
1243 .name = LPASS_BE_SLIMBUS_0_TX,
1244 .stream_name = "Slimbus Capture",
1245 .cpu_dai_name = "msm-dai-q6.16385",
1246 .platform_name = "msm-pcm-routing",
1247 .codec_name = "sitar_codec",
1248 .codec_dai_name = "sitar_tx1",
1249 .no_pcm = 1,
1250 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1251 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1252 .ops = &msm8930_be_ops,
1253 },
1254 /* Backend BT/FM DAI Links */
1255 {
1256 .name = LPASS_BE_INT_BT_SCO_RX,
1257 .stream_name = "Internal BT-SCO Playback",
1258 .cpu_dai_name = "msm-dai-q6.12288",
1259 .platform_name = "msm-pcm-routing",
1260 .codec_name = "msm-stub-codec.1",
1261 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301262 .no_pcm = 1,
1263 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1264 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001265 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301266 },
1267 {
1268 .name = LPASS_BE_INT_BT_SCO_TX,
1269 .stream_name = "Internal BT-SCO Capture",
1270 .cpu_dai_name = "msm-dai-q6.12289",
1271 .platform_name = "msm-pcm-routing",
1272 .codec_name = "msm-stub-codec.1",
1273 .codec_dai_name = "msm-stub-tx",
1274 .no_pcm = 1,
1275 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1276 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1277 },
1278 {
1279 .name = LPASS_BE_INT_FM_RX,
1280 .stream_name = "Internal FM Playback",
1281 .cpu_dai_name = "msm-dai-q6.12292",
1282 .platform_name = "msm-pcm-routing",
1283 .codec_name = "msm-stub-codec.1",
1284 .codec_dai_name = "msm-stub-rx",
1285 .no_pcm = 1,
1286 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1287 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001288 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301289 },
1290 {
1291 .name = LPASS_BE_INT_FM_TX,
1292 .stream_name = "Internal FM Capture",
1293 .cpu_dai_name = "msm-dai-q6.12293",
1294 .platform_name = "msm-pcm-routing",
1295 .codec_name = "msm-stub-codec.1",
1296 .codec_dai_name = "msm-stub-tx",
1297 .no_pcm = 1,
1298 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1299 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1300 },
1301 /* HDMI BACK END DAI Link */
1302 {
1303 .name = LPASS_BE_HDMI,
1304 .stream_name = "HDMI Playback",
1305 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1306 .platform_name = "msm-pcm-routing",
1307 .codec_name = "msm-stub-codec.1",
1308 .codec_dai_name = "msm-stub-rx",
1309 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301310 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1311 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001312 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301313 },
1314 /* Backend AFE DAI Links */
1315 {
1316 .name = LPASS_BE_AFE_PCM_RX,
1317 .stream_name = "AFE Playback",
1318 .cpu_dai_name = "msm-dai-q6.224",
1319 .platform_name = "msm-pcm-routing",
1320 .codec_name = "msm-stub-codec.1",
1321 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301322 .no_pcm = 1,
1323 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001324 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001325 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301326 },
1327 {
1328 .name = LPASS_BE_AFE_PCM_TX,
1329 .stream_name = "AFE Capture",
1330 .cpu_dai_name = "msm-dai-q6.225",
1331 .platform_name = "msm-pcm-routing",
1332 .codec_name = "msm-stub-codec.1",
1333 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301334 .no_pcm = 1,
1335 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina6b4de782012-10-23 16:52:01 -07001336 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301337 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001338 /* AUX PCM Backend DAI Links */
1339 {
1340 .name = LPASS_BE_AUXPCM_RX,
1341 .stream_name = "AUX PCM Playback",
1342 .cpu_dai_name = "msm-dai-q6.2",
1343 .platform_name = "msm-pcm-routing",
1344 .codec_name = "msm-stub-codec.1",
1345 .codec_dai_name = "msm-stub-rx",
1346 .no_pcm = 1,
1347 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1348 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1349 .ops = &msm8930_auxpcm_be_ops,
1350 },
1351 {
1352 .name = LPASS_BE_AUXPCM_TX,
1353 .stream_name = "AUX PCM Capture",
1354 .cpu_dai_name = "msm-dai-q6.3",
1355 .platform_name = "msm-pcm-routing",
1356 .codec_name = "msm-stub-codec.1",
1357 .codec_dai_name = "msm-stub-tx",
1358 .no_pcm = 1,
1359 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1360 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001361 .ops = &msm8930_auxpcm_be_ops,
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001362 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301363 /* Incall Music BACK END DAI Link */
1364 {
1365 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1366 .stream_name = "Voice Farend Playback",
1367 .cpu_dai_name = "msm-dai-q6.32773",
1368 .platform_name = "msm-pcm-routing",
1369 .codec_name = "msm-stub-codec.1",
1370 .codec_dai_name = "msm-stub-rx",
1371 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301372 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1373 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1374 },
1375 /* Incall Record Uplink BACK END DAI Link */
1376 {
1377 .name = LPASS_BE_INCALL_RECORD_TX,
1378 .stream_name = "Voice Uplink Capture",
1379 .cpu_dai_name = "msm-dai-q6.32772",
1380 .platform_name = "msm-pcm-routing",
1381 .codec_name = "msm-stub-codec.1",
1382 .codec_dai_name = "msm-stub-tx",
1383 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301384 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1385 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1386 },
1387 /* Incall Record Downlink BACK END DAI Link */
1388 {
1389 .name = LPASS_BE_INCALL_RECORD_RX,
1390 .stream_name = "Voice Downlink Capture",
1391 .cpu_dai_name = "msm-dai-q6.32771",
1392 .platform_name = "msm-pcm-routing",
1393 .codec_name = "msm-stub-codec.1",
1394 .codec_dai_name = "msm-stub-tx",
1395 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301396 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1397 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001398 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301399 },
1400};
1401
1402struct snd_soc_card snd_soc_card_msm8930 = {
1403 .name = "msm8930-sitar-snd-card",
1404 .dai_link = msm8930_dai,
1405 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001406 .controls = sitar_msm8930_controls,
1407 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301408};
1409
1410static struct platform_device *msm8930_snd_device;
1411
1412static int msm8930_configure_headset_mic_gpios(void)
1413{
1414 int ret;
Laxminath Kasam852c7812013-03-07 20:03:37 +05301415 int gpio_val = 0;
1416
1417 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
1418 gpio_val = GPIO_HS_SW_SEL;
1419 else
1420 gpio_val = 80;
1421 ret = gpio_request(gpio_val, "US_EURO_SWITCH");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301422 if (ret) {
Laxminath Kasam852c7812013-03-07 20:03:37 +05301423 pr_err("%s: Failed to request gpio %d\n", __func__, gpio_val);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301424 return ret;
1425 }
Laxminath Kasam852c7812013-03-07 20:03:37 +05301426 ret = gpio_direction_output(gpio_val, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301427 if (ret) {
1428 pr_err("%s: Unable to set direction\n", __func__);
Laxminath Kasam852c7812013-03-07 20:03:37 +05301429 gpio_free(gpio_val);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301430 }
1431 msm8930_headset_gpios_configured = 0;
1432 return 0;
1433}
1434static void msm8930_free_headset_mic_gpios(void)
1435{
Laxminath Kasam852c7812013-03-07 20:03:37 +05301436 int gpio_val = 0;
1437
1438 if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
1439 gpio_val = GPIO_HS_SW_SEL;
1440 else
1441 gpio_val = 80;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301442 if (msm8930_headset_gpios_configured)
Laxminath Kasam852c7812013-03-07 20:03:37 +05301443 gpio_free(gpio_val);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301444}
1445
1446static int __init msm8930_audio_init(void)
1447{
1448 int ret;
1449
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001450 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301451 pr_err("%s: Not the right machine type\n", __func__);
1452 return -ENODEV ;
1453 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001454 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1455 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001456 pr_err("Calibration data allocation failed\n");
1457 return -ENOMEM;
1458 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301459
1460 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1461 if (!msm8930_snd_device) {
1462 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001463 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301464 return -ENOMEM;
1465 }
1466
1467 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1468 ret = platform_device_add(msm8930_snd_device);
1469 if (ret) {
1470 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001471 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301472 return ret;
1473 }
1474
1475 if (msm8930_configure_headset_mic_gpios()) {
1476 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1477 msm8930_headset_gpios_configured = 0;
1478 } else
1479 msm8930_headset_gpios_configured = 1;
1480
Kuirong Wang892c9ad2012-09-20 11:43:17 -07001481 atomic_set(&auxpcm_rsc_ref, 0);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301482 return ret;
1483
1484}
1485module_init(msm8930_audio_init);
1486
1487static void __exit msm8930_audio_exit(void)
1488{
Stepan Moskovchenkoc6a603a2012-09-21 20:32:17 -07001489 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301490 pr_err("%s: Not the right machine type\n", __func__);
1491 return ;
1492 }
1493 msm8930_free_headset_mic_gpios();
1494 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001495 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301496}
1497module_exit(msm8930_audio_exit);
1498
1499MODULE_DESCRIPTION("ALSA SoC MSM8930");
1500MODULE_LICENSE("GPL v2");