blob: 38099160c356d1a77865a435ce67bd4e5e7b1dc1 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2012, 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>
27#include "msm-pcm-routing.h"
28#include "../codecs/wcd9304.h"
29
30/* 8930 machine driver */
31
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053032#define MSM8930_SPK_ON 1
33#define MSM8930_SPK_OFF 0
34
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053035#define BTSCO_RATE_8KHZ 8000
36#define BTSCO_RATE_16KHZ 16000
37
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080038#define SPK_AMP_POS 0x1
39#define SPK_AMP_NEG 0x2
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -070040#define SPKR_BOOST_GPIO 15
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -070041#define LEFT_SPKR_AMPL_GPIO 15
Bhalchandra Gajare97676792012-05-22 17:41:45 -070042#define DEFAULT_PMIC_SPK_GAIN 0x0D
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053043#define SITAR_EXT_CLK_RATE 12288000
44
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -070045#define SITAR_MBHC_DEF_BUTTONS 8
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053046#define SITAR_MBHC_DEF_RLOADS 5
47
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -070048#define GPIO_AUX_PCM_DOUT 63
49#define GPIO_AUX_PCM_DIN 64
50#define GPIO_AUX_PCM_SYNC 65
51#define GPIO_AUX_PCM_CLK 66
52
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053053static int msm8930_spk_control;
54static int msm8930_slim_0_rx_ch = 1;
55static int msm8930_slim_0_tx_ch = 1;
Bhalchandra Gajare97676792012-05-22 17:41:45 -070056static int msm8930_pmic_spk_gain = DEFAULT_PMIC_SPK_GAIN;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053057
Asish Bhattacharyac71827a2012-03-05 10:11:45 -080058static int msm8930_ext_spk_pamp;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053059static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
60static int msm8930_btsco_ch = 1;
Vicky Sehrawat45204132012-11-05 17:54:13 -080061static int hdmi_rate_variable;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053062static struct clk *codec_clk;
63static int clk_users;
64
65static int msm8930_headset_gpios_configured;
Laxminath Kasam87be2992013-03-29 12:34:41 +053066static struct mutex cdc_mclk_mutex;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053067
68static struct snd_soc_jack hs_jack;
69static struct snd_soc_jack button_jack;
Kuirong Wangae395b02012-09-20 11:43:17 -070070static atomic_t auxpcm_rsc_ref;
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -070071
72static int msm8930_enable_codec_ext_clk(
73 struct snd_soc_codec *codec, int enable,
74 bool dapm);
75
76static struct sitar_mbhc_config mbhc_cfg = {
77 .headset_jack = &hs_jack,
78 .button_jack = &button_jack,
79 .read_fw_bin = false,
80 .calibration = NULL,
81 .micbias = SITAR_MICBIAS2,
82 .mclk_cb_fn = msm8930_enable_codec_ext_clk,
83 .mclk_rate = SITAR_EXT_CLK_RATE,
84 .gpio = 0,
85 .gpio_irq = 0,
86 .gpio_level_insert = 1,
87};
88
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053089
90static void msm8930_ext_control(struct snd_soc_codec *codec)
91{
92 struct snd_soc_dapm_context *dapm = &codec->dapm;
93
94 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
95 if (msm8930_spk_control == MSM8930_SPK_ON) {
96 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -080097 snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +053098 } else {
99 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800100 snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530101 }
102
103 snd_soc_dapm_sync(dapm);
104}
105
106static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
107 struct snd_ctl_elem_value *ucontrol)
108{
109 pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
110 ucontrol->value.integer.value[0] = msm8930_spk_control;
111 return 0;
112}
113static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
114 struct snd_ctl_elem_value *ucontrol)
115{
116 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
117
118 pr_debug("%s()\n", __func__);
119 if (msm8930_spk_control == ucontrol->value.integer.value[0])
120 return 0;
121
122 msm8930_spk_control = ucontrol->value.integer.value[0];
123 msm8930_ext_control(codec);
124 return 1;
125}
126
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700127static int msm8930_cfg_spkr_gpio(int gpio,
128 int enable, const char *gpio_label)
129{
130 int ret = 0;
131
132 pr_debug("%s: Configure %s GPIO %u",
133 __func__, gpio_label, gpio);
134 ret = gpio_request(gpio, gpio_label);
135 if (ret)
136 return ret;
137
138 pr_debug("%s: Enable %s gpio %u\n",
139 __func__, gpio_label, gpio);
140 gpio_direction_output(gpio, enable);
141
142 return ret;
143}
144
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800145static void msm8960_ext_spk_power_amp_on(u32 spk)
146{
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700147 int ret = 0;
148
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800149 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
150 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
151 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
152
153 pr_debug("%s() External Bottom Speaker Ampl already "
154 "turned on. spk = 0x%08x\n", __func__, spk);
155 return;
156 }
157
158 msm8930_ext_spk_pamp |= spk;
159
160 if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
161 (msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
162
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700163 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
164 ret = msm8930_cfg_spkr_gpio(
165 LEFT_SPKR_AMPL_GPIO,
166 1, "LEFT_SPKR_AMPL");
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700167 if (ret) {
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700168 pr_err("%s: Failed to config ampl gpio %u\n",
169 __func__, LEFT_SPKR_AMPL_GPIO);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700170 return;
171 }
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700172 } else {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700173
Bhalchandra Gajare0cf772a2012-11-13 12:30:26 -0800174 /*
175 * 8930 CDP does not have a 5V speaker boost,
176 * hence the GPIO enable for speaker boost is
177 * only required for platforms other than CDP
178 */
179 if (!machine_is_msm8930_cdp()) {
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700180 ret = msm8930_cfg_spkr_gpio(
181 SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
182 if (ret) {
183 pr_err("%s: Failure: spkr boost gpio %u\n",
184 __func__, SPKR_BOOST_GPIO);
185 return;
186 }
187 }
188 pm8xxx_spk_enable(MSM8930_SPK_ON);
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700189 }
190
Bhalchandra Gajare37e7e612012-10-09 12:37:20 -0700191 pr_debug("%s: sleeping 10 ms after turning on external "
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800192 " Left Speaker Ampl\n", __func__);
Bhalchandra Gajare37e7e612012-10-09 12:37:20 -0700193 usleep_range(10000, 10000);
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800194 }
195
196 } else {
197
198 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
199 __func__, spk);
200 return;
201 }
202}
203
204static void msm8960_ext_spk_power_amp_off(u32 spk)
205{
206 if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
207 if (!msm8930_ext_spk_pamp)
208 return;
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700209
210 if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
211 gpio_free(LEFT_SPKR_AMPL_GPIO);
212 msm8930_ext_spk_pamp = 0;
213 return;
214 }
215
Bhalchandra Gajare0cf772a2012-11-13 12:30:26 -0800216 if (!machine_is_msm8930_cdp()) {
Bhalchandra Gajare98a28cd2012-05-16 12:00:20 -0700217 pr_debug("%s: Free speaker boost gpio %u\n",
218 __func__, SPKR_BOOST_GPIO);
219 gpio_direction_output(SPKR_BOOST_GPIO, 0);
220 gpio_free(SPKR_BOOST_GPIO);
221 }
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800222
223 pm8xxx_spk_enable(MSM8930_SPK_OFF);
224 msm8930_ext_spk_pamp = 0;
Bhalchandra Gajare37e7e612012-10-09 12:37:20 -0700225 pr_debug("%s: slepping 10 ms after turning on external "
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800226 " Left Speaker Ampl\n", __func__);
Bhalchandra Gajare37e7e612012-10-09 12:37:20 -0700227 usleep_range(10000, 10000);
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800228
229 } else {
230
231 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
232 __func__, spk);
233 return;
234 }
235}
236
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530237static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
238 struct snd_kcontrol *k, int event)
239{
240 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800241 if (SND_SOC_DAPM_EVENT_ON(event)) {
242 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
243 msm8960_ext_spk_power_amp_on(SPK_AMP_POS);
244 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
245 msm8960_ext_spk_power_amp_on(SPK_AMP_NEG);
246 else {
247 pr_err("%s() Invalid Speaker Widget = %s\n",
248 __func__, w->name);
249 return -EINVAL;
250 }
251 } else {
252 if (!strncmp(w->name, "Ext Spk Left Pos", 17))
253 msm8960_ext_spk_power_amp_off(SPK_AMP_POS);
254 else if (!strncmp(w->name, "Ext Spk Left Neg", 17))
255 msm8960_ext_spk_power_amp_off(SPK_AMP_NEG);
256 else {
257 pr_err("%s() Invalid Speaker Widget = %s\n",
258 __func__, w->name);
259 return -EINVAL;
260 }
261 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530262 return 0;
263}
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800264
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700265static int msm8930_enable_codec_ext_clk(
266 struct snd_soc_codec *codec, int enable,
267 bool dapm)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530268{
Laxminath Kasam87be2992013-03-29 12:34:41 +0530269 int r = 0;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530270 pr_debug("%s: enable = %d\n", __func__, enable);
Laxminath Kasam87be2992013-03-29 12:34:41 +0530271
272 mutex_lock(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530273 if (enable) {
274 clk_users++;
275 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
Laxminath Kasam87be2992013-03-29 12:34:41 +0530276 if (clk_users == 1) {
277 if (codec_clk) {
278 clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
279 clk_prepare_enable(codec_clk);
280 sitar_mclk_enable(codec, 1, dapm);
281 } else {
282 pr_err("%s: Error setting Sitar MCLK\n",
283 __func__);
284 clk_users--;
285 r = -EINVAL;
286 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530287 }
288 } else {
Laxminath Kasam87be2992013-03-29 12:34:41 +0530289 if (clk_users > 0) {
290 clk_users--;
291 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
292 if (clk_users == 0) {
293 pr_debug("%s: disabling MCLK. clk_users = %d\n",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530294 __func__, clk_users);
Laxminath Kasam87be2992013-03-29 12:34:41 +0530295 sitar_mclk_enable(codec, 0, dapm);
296 clk_disable_unprepare(codec_clk);
297 }
298 } else {
299 pr_err("%s: Error releasing Sitar MCLK\n", __func__);
300 r = -EINVAL;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530301 }
302 }
Laxminath Kasam87be2992013-03-29 12:34:41 +0530303 mutex_unlock(&cdc_mclk_mutex);
304 return r;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530305}
306
307static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
308 struct snd_kcontrol *kcontrol, int event)
309{
310 pr_debug("%s: event = %d\n", __func__, event);
311
312 switch (event) {
313 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700314 return msm8930_enable_codec_ext_clk(w->codec, 1, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530315 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700316 return msm8930_enable_codec_ext_clk(w->codec, 0, true);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530317 }
318 return 0;
319}
320
321static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
322
323 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
324 msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
325
326 SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
Asish Bhattacharyac71827a2012-03-05 10:11:45 -0800327 SND_SOC_DAPM_SPK("Ext Spk Left Neg", msm8930_spkramp_event),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530328
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530329 SND_SOC_DAPM_MIC("Headset Mic", NULL),
330 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
331 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
332 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
333
334 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
335 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
336 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
337 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
338
339};
340
341static const struct snd_soc_dapm_route common_audio_map[] = {
342
343 {"RX_BIAS", NULL, "MCLK"},
344 {"LDO_H", NULL, "MCLK"},
345
346 {"MIC BIAS1 Internal1", NULL, "MCLK"},
347 {"MIC BIAS2 Internal1", NULL, "MCLK"},
348
349 /* Speaker path */
350 {"Ext Spk Left Pos", NULL, "LINEOUT1"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800351 {"Ext Spk Left Neg", NULL, "LINEOUT2"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530352
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800353 /* Headset Mic */
Bhalchandra Gajare553fb9e2012-06-26 14:48:54 -0700354 {"AMIC2", NULL, "MIC BIAS2 External"},
355 {"MIC BIAS2 External", NULL, "Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530356
357 /* Microphone path */
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700358 {"AMIC1", NULL, "MIC BIAS2 External"},
359 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800360
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700361 {"AMIC3", NULL, "MIC BIAS2 External"},
362 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530363
364 {"HEADPHONE", NULL, "LDO_H"},
365
366 /**
367 * The digital Mic routes are setup considering
368 * fluid as default device.
369 */
370
371 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700372 * Digital Mic1. Front Bottom left Mic on Fluid and MTP.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530373 * Digital Mic GM5 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700374 * Conncted to DMIC1 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530375 */
376 {"DMIC1", NULL, "MIC BIAS1 External"},
377 {"MIC BIAS1 External", NULL, "Digital Mic1"},
378
379 /**
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700380 * Digital Mic2. Back top MIC on Fluid.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530381 * Digital Mic GM6 on CDP mainboard.
Bhalchandra Gajaree6a30f72012-05-23 19:46:21 -0700382 * Conncted to DMIC2 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530383 */
384 {"DMIC2", NULL, "MIC BIAS1 External"},
385 {"MIC BIAS1 External", NULL, "Digital Mic2"},
386 /**
387 * Digital Mic3. Back Bottom Digital Mic on Fluid.
388 * Digital Mic GM1 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800389 * Conncted to DMIC4 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530390 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800391 {"DMIC3", NULL, "MIC BIAS1 External"},
392 {"MIC BIAS1 External", NULL, "Digital Mic3"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530393
394 /**
395 * Digital Mic4. Back top Digital Mic on Fluid.
396 * Digital Mic GM2 on CDP mainboard.
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800397 * Conncted to DMIC3 Input on Sitar codec.
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530398 */
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800399 {"DMIC4", NULL, "MIC BIAS1 External"},
400 {"MIC BIAS1 External", NULL, "Digital Mic4"},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530401
402
403};
404
405static const char *spk_function[] = {"Off", "On"};
406static const char *slim0_rx_ch_text[] = {"One", "Two"};
407static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
408
Vicky Sehrawat45204132012-11-05 17:54:13 -0800409static const char * const hdmi_rate[] = {"Default", "Variable"};
410
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530411static const struct soc_enum msm8930_enum[] = {
412 SOC_ENUM_SINGLE_EXT(2, spk_function),
413 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
414 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat45204132012-11-05 17:54:13 -0800415 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530416};
417
418static const char *btsco_rate_text[] = {"8000", "16000"};
419static const struct soc_enum msm8930_btsco_enum[] = {
420 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
421};
422
423static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *ucontrol)
425{
426 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800427 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530428 ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
429 return 0;
430}
431
432static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
433 struct snd_ctl_elem_value *ucontrol)
434{
435 msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
436
437 pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800438 msm8930_slim_0_rx_ch);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530439 return 1;
440}
441
442static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
443 struct snd_ctl_elem_value *ucontrol)
444{
445 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
446 msm8930_slim_0_tx_ch);
447 ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
448 return 0;
449}
450
451static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
452 struct snd_ctl_elem_value *ucontrol)
453{
454 msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
455
456 pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
457 msm8930_slim_0_tx_ch);
458 return 1;
459}
460
461static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol)
463{
464 pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
465 ucontrol->value.integer.value[0] = msm8930_btsco_rate;
466 return 0;
467}
468
469static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
471{
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700472
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530473 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700474 case 8000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530475 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
476 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700477 case 16000:
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530478 msm8930_btsco_rate = BTSCO_RATE_16KHZ;
479 break;
480 default:
481 msm8930_btsco_rate = BTSCO_RATE_8KHZ;
482 break;
483 }
484 pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
485 return 0;
486}
487
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700488static const char *pmic_spk_gain_text[] = {
489 "NEG_6_DB", "NEG_4_DB", "NEG_2_DB", "ZERO_DB", "POS_2_DB", "POS_4_DB",
490 "POS_6_DB", "POS_8_DB", "POS_10_DB", "POS_12_DB", "POS_14_DB",
491 "POS_16_DB", "POS_18_DB", "POS_20_DB", "POS_22_DB", "POS_24_DB"
492};
493
494static const struct soc_enum msm8960_pmic_spk_gain_enum[] = {
495 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pmic_spk_gain_text),
496 pmic_spk_gain_text),
497};
498
499static int msm8930_pmic_gain_get(struct snd_kcontrol *kcontrol,
500 struct snd_ctl_elem_value *ucontrol)
501{
502 pr_debug("%s: msm8930_pmic_spk_gain = %d\n", __func__,
503 msm8930_pmic_spk_gain);
504 ucontrol->value.integer.value[0] = msm8930_pmic_spk_gain;
505 return 0;
506}
507
508static int msm8930_pmic_gain_put(struct snd_kcontrol *kcontrol,
509 struct snd_ctl_elem_value *ucontrol)
510{
511 int ret = 0;
512 msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700513 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
514 ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700515 pr_debug("%s: msm8930_pmic_spk_gain = %d"
516 " ucontrol->value.integer.value[0] = %d\n", __func__,
517 msm8930_pmic_spk_gain,
518 (int) ucontrol->value.integer.value[0]);
519 return ret;
520}
521
Vicky Sehrawat45204132012-11-05 17:54:13 -0800522static int msm8930_hdmi_rate_put(struct snd_kcontrol *kcontrol,
523 struct snd_ctl_elem_value *ucontrol)
524{
525 hdmi_rate_variable = ucontrol->value.integer.value[0];
526 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
527 return 0;
528}
529
530static int msm8930_hdmi_rate_get(struct snd_kcontrol *kcontrol,
531 struct snd_ctl_elem_value *ucontrol)
532{
533 ucontrol->value.integer.value[0] = hdmi_rate_variable;
534 return 0;
535}
536
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530537static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
538 SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
539 msm8930_set_spk),
540 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
541 msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
542 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
543 msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700544 SOC_ENUM_EXT("PMIC SPK Gain", msm8960_pmic_spk_gain_enum[0],
545 msm8930_pmic_gain_get, msm8930_pmic_gain_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530546 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
547 msm8930_btsco_rate_get, msm8930_btsco_rate_put),
Vicky Sehrawat45204132012-11-05 17:54:13 -0800548 SOC_ENUM_EXT("HDMI RX Rate", msm8930_enum[3],
549 msm8930_hdmi_rate_get,
550 msm8930_hdmi_rate_put),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530551};
552
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800553static void *def_sitar_mbhc_cal(void)
554{
555 void *sitar_cal;
556 struct sitar_mbhc_btn_detect_cfg *btn_cfg;
557 u16 *btn_low, *btn_high;
558 u8 *n_ready, *n_cic, *gain;
559
560 sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
561 SITAR_MBHC_DEF_RLOADS),
562 GFP_KERNEL);
563 if (!sitar_cal) {
564 pr_err("%s: out of memory\n", __func__);
565 return NULL;
566 }
567
568#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
569 S(t_ldoh, 100);
570 S(t_bg_fast_settle, 100);
571 S(t_shutdown_plug_rem, 255);
572 S(mbhc_nsa, 4);
573 S(mbhc_navg, 4);
574#undef S
575#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
576 S(mic_current, SITAR_PID_MIC_5_UA);
577 S(hph_current, SITAR_PID_MIC_5_UA);
578 S(t_mic_pid, 100);
579 S(t_ins_complete, 250);
580 S(t_ins_retry, 200);
581#undef S
582#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
583 S(v_no_mic, 30);
Bhalchandra Gajare18314d52012-06-06 19:03:01 -0700584 S(v_hs_max, 1650);
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800585#undef S
586#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
587 S(c[0], 62);
588 S(c[1], 124);
589 S(nc, 1);
590 S(n_meas, 3);
591 S(mbhc_nsc, 11);
592 S(n_btn_meas, 1);
593 S(n_btn_con, 2);
594 S(num_btn, SITAR_MBHC_DEF_BUTTONS);
595 S(v_btn_press_delta_sta, 100);
596 S(v_btn_press_delta_cic, 50);
597#undef S
598 btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
599 btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
600 btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
601 btn_low[0] = -50;
602 btn_high[0] = 10;
603 btn_low[1] = 11;
604 btn_high[1] = 38;
605 btn_low[2] = 39;
606 btn_high[2] = 64;
607 btn_low[3] = 65;
608 btn_high[3] = 91;
609 btn_low[4] = 92;
610 btn_high[4] = 115;
611 btn_low[5] = 116;
612 btn_high[5] = 141;
613 btn_low[6] = 142;
614 btn_high[6] = 163;
615 btn_low[7] = 164;
616 btn_high[7] = 250;
617 n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
618 n_ready[0] = 48;
619 n_ready[1] = 38;
620 n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
621 n_cic[0] = 60;
622 n_cic[1] = 47;
623 gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
624 gain[0] = 11;
625 gain[1] = 9;
626
627 return sitar_cal;
628}
629
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530630static int msm8930_hw_params(struct snd_pcm_substream *substream,
631 struct snd_pcm_hw_params *params)
632{
633 struct snd_soc_pcm_runtime *rtd = substream->private_data;
634 struct snd_soc_dai *codec_dai = rtd->codec_dai;
635 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
636 int ret = 0;
637 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
638 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
639
640 pr_debug("%s: ch=%d\n", __func__,
641 msm8930_slim_0_rx_ch);
642 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
643 ret = snd_soc_dai_get_channel_map(codec_dai,
644 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
645 if (ret < 0) {
646 pr_err("%s: failed to get codec chan map\n", __func__);
647 goto end;
648 }
649
650 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
651 msm8930_slim_0_rx_ch, rx_ch);
652 if (ret < 0) {
653 pr_err("%s: failed to set cpu chan map\n", __func__);
654 goto end;
655 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530656 } else {
657 ret = snd_soc_dai_get_channel_map(codec_dai,
658 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
659 if (ret < 0) {
660 pr_err("%s: failed to get codec chan map\n", __func__);
661 goto end;
662 }
663 ret = snd_soc_dai_set_channel_map(cpu_dai,
664 msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
665 if (ret < 0) {
666 pr_err("%s: failed to set cpu chan map\n", __func__);
667 goto end;
668 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530669 }
670end:
671 return ret;
672}
673
674static int msm8930_audrx_init(struct snd_soc_pcm_runtime *rtd)
675{
676 int err;
677 struct snd_soc_codec *codec = rtd->codec;
678 struct snd_soc_dapm_context *dapm = &codec->dapm;
679 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuirong Wang906ac472012-07-09 12:54:44 -0700680 struct snd_soc_dai *codec_dai = rtd->codec_dai;
681
682 /* Tabla SLIMBUS configuration
683 * RX1, RX2, RX3, RX4, RX5
684 * TX1, TX2, TX3, TX4, TX5
685 */
686 unsigned int rx_ch[SITAR_RX_MAX] = {138, 139, 140, 141, 142};
687 unsigned int tx_ch[SITAR_TX_MAX] = {128, 129, 130, 131, 132};
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530688
689 pr_debug("%s()\n", __func__);
690
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530691 snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
692 ARRAY_SIZE(msm8930_dapm_widgets));
693
694 snd_soc_dapm_add_routes(dapm, common_audio_map,
695 ARRAY_SIZE(common_audio_map));
696
697 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800698 snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530699
700 snd_soc_dapm_sync(dapm);
701
702 err = snd_soc_jack_new(codec, "Headset Jack",
703 (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
704 &hs_jack);
705 if (err) {
706 pr_err("failed to create new jack\n");
707 return err;
708 }
709
710 err = snd_soc_jack_new(codec, "Button Jack",
Bhalchandra Gajare7708ee32012-05-24 17:37:37 -0700711 SITAR_JACK_BUTTON_MASK, &button_jack);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530712 if (err) {
713 pr_err("failed to create new jack\n");
714 return err;
715 }
716 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -0800717
Kuirong Wang906ac472012-07-09 12:54:44 -0700718 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
719 tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
720
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -0700721 mbhc_cfg.gpio = 37;
722 mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
723 sitar_hs_detect(codec, &mbhc_cfg);
724
Bhalchandra Gajaref6d1f722012-08-13 12:32:12 -0700725 if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
726 /* Initialize default PMIC speaker gain */
727 pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
728 }
Bhalchandra Gajare97676792012-05-22 17:41:45 -0700729
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530730 return 0;
731}
732
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530733static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
734 struct snd_pcm_hw_params *params)
735{
736 struct snd_interval *rate = hw_param_interval(params,
737 SNDRV_PCM_HW_PARAM_RATE);
738
739 struct snd_interval *channels = hw_param_interval(params,
740 SNDRV_PCM_HW_PARAM_CHANNELS);
741
742 pr_debug("%s()\n", __func__);
743 rate->min = rate->max = 48000;
744 channels->min = channels->max = msm8930_slim_0_rx_ch;
745
746 return 0;
747}
748
749static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
750 struct snd_pcm_hw_params *params)
751{
752 struct snd_interval *rate = hw_param_interval(params,
753 SNDRV_PCM_HW_PARAM_RATE);
754
755 struct snd_interval *channels = hw_param_interval(params,
756 SNDRV_PCM_HW_PARAM_CHANNELS);
757
758 pr_debug("%s()\n", __func__);
759 rate->min = rate->max = 48000;
760 channels->min = channels->max = msm8930_slim_0_tx_ch;
761
762 return 0;
763}
764
765static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
766 struct snd_pcm_hw_params *params)
767{
768 struct snd_interval *rate = hw_param_interval(params,
769 SNDRV_PCM_HW_PARAM_RATE);
770
771 pr_debug("%s()\n", __func__);
772 rate->min = rate->max = 48000;
773
774 return 0;
775}
776
777static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
778 struct snd_pcm_hw_params *params)
779{
780 struct snd_interval *rate = hw_param_interval(params,
781 SNDRV_PCM_HW_PARAM_RATE);
782
783 struct snd_interval *channels = hw_param_interval(params,
784 SNDRV_PCM_HW_PARAM_CHANNELS);
785
Vicky Sehrawat45204132012-11-05 17:54:13 -0800786 if (!hdmi_rate_variable)
787 rate->min = rate->max = 48000;
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530788 channels->min = channels->max = 2;
789
790 return 0;
791}
792
793static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
794 struct snd_pcm_hw_params *params)
795{
796 struct snd_interval *rate = hw_param_interval(params,
797 SNDRV_PCM_HW_PARAM_RATE);
798
799 struct snd_interval *channels = hw_param_interval(params,
800 SNDRV_PCM_HW_PARAM_CHANNELS);
801
802 rate->min = rate->max = msm8930_btsco_rate;
803 channels->min = channels->max = msm8930_btsco_ch;
804
805 return 0;
806}
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530807
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700808static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
809 struct snd_pcm_hw_params *params)
810{
811 struct snd_interval *rate = hw_param_interval(params,
812 SNDRV_PCM_HW_PARAM_RATE);
813
814 struct snd_interval *channels = hw_param_interval(params,
815 SNDRV_PCM_HW_PARAM_CHANNELS);
816
817 /* PCM only supports mono output with 8khz sample rate */
818 rate->min = rate->max = 8000;
819 channels->min = channels->max = 1;
820
821 return 0;
822}
823
Jayasena Sangaraboina69ab7352012-10-23 16:52:01 -0700824static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
825 struct snd_pcm_hw_params *params)
826{
827 struct snd_interval *rate = hw_param_interval(params,
828 SNDRV_PCM_HW_PARAM_RATE);
829
830 pr_debug("%s()\n", __func__);
831 rate->min = rate->max = 48000;
832
833 return 0;
834}
835
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700836static int msm8930_aux_pcm_get_gpios(void)
837{
838 int ret = 0;
839
840 pr_debug("%s\n", __func__);
841
842 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
843 if (ret < 0) {
844 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
845 __func__, GPIO_AUX_PCM_DOUT);
846
847 goto fail_dout;
848 }
849
850 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
851 if (ret < 0) {
852 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
853 __func__, GPIO_AUX_PCM_DIN);
854 goto fail_din;
855 }
856
857 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
858 if (ret < 0) {
859 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
860 __func__, GPIO_AUX_PCM_SYNC);
861 goto fail_sync;
862 }
863
864 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
865 if (ret < 0) {
866 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
867 __func__, GPIO_AUX_PCM_CLK);
868 goto fail_clk;
869 }
870
871 return 0;
872
873fail_clk:
874 gpio_free(GPIO_AUX_PCM_SYNC);
875fail_sync:
876 gpio_free(GPIO_AUX_PCM_DIN);
877fail_din:
878 gpio_free(GPIO_AUX_PCM_DOUT);
879fail_dout:
880
881 return ret;
882}
883
884static int msm8930_aux_pcm_free_gpios(void)
885{
886 gpio_free(GPIO_AUX_PCM_DIN);
887 gpio_free(GPIO_AUX_PCM_DOUT);
888 gpio_free(GPIO_AUX_PCM_SYNC);
889 gpio_free(GPIO_AUX_PCM_CLK);
890
891 return 0;
892}
893
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530894static int msm8930_startup(struct snd_pcm_substream *substream)
895{
896 pr_debug("%s(): substream = %s stream = %d\n", __func__,
897 substream->name, substream->stream);
898 return 0;
899}
900
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700901static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
902{
903 int ret = 0;
904
Kuirong Wangae395b02012-09-20 11:43:17 -0700905 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
906 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
907 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
908 ret = msm8930_aux_pcm_get_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700909 if (ret < 0) {
910 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
911 return -EINVAL;
912 }
913 return 0;
914
915}
916
917static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
918{
Kuirong Wangae395b02012-09-20 11:43:17 -0700919 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
920 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
921 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
922 msm8930_aux_pcm_free_gpios();
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700923}
924
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530925static void msm8930_shutdown(struct snd_pcm_substream *substream)
926{
927 pr_debug("%s(): substream = %s stream = %d\n", __func__,
928 substream->name, substream->stream);
929}
930
931static struct snd_soc_ops msm8930_be_ops = {
932 .startup = msm8930_startup,
933 .hw_params = msm8930_hw_params,
934 .shutdown = msm8930_shutdown,
935};
936
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -0700937static struct snd_soc_ops msm8930_auxpcm_be_ops = {
938 .startup = msm8930_auxpcm_startup,
939 .shutdown = msm8930_auxpcm_shutdown,
940};
941
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530942/* Digital audio interface glue - connects codec <---> CPU */
943static struct snd_soc_dai_link msm8930_dai[] = {
944 /* FrontEnd DAI Links */
945 {
946 .name = "MSM8930 Media1",
947 .stream_name = "MultiMedia1",
948 .cpu_dai_name = "MultiMedia1",
949 .platform_name = "msm-pcm-dsp",
950 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700951 .codec_dai_name = "snd-soc-dummy-dai",
952 .codec_name = "snd-soc-dummy",
953 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
954 .ignore_suspend = 1,
955 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530956 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
957 },
958 {
959 .name = "MSM8930 Media2",
960 .stream_name = "MultiMedia2",
961 .cpu_dai_name = "MultiMedia2",
Asish Bhattacharyae2601ae2012-07-18 21:13:21 +0530962 .platform_name = "msm-multi-ch-pcm-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530963 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700964 .codec_dai_name = "snd-soc-dummy-dai",
965 .codec_name = "snd-soc-dummy",
966 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
967 .ignore_suspend = 1,
968 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530969 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
970 },
971 {
972 .name = "Circuit-Switch Voice",
973 .stream_name = "CS-Voice",
974 .cpu_dai_name = "CS-VOICE",
975 .platform_name = "msm-pcm-voice",
976 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700977 .codec_dai_name = "snd-soc-dummy-dai",
978 .codec_name = "snd-soc-dummy",
979 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530980 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
981 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
982 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700983 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530984 },
985 {
986 .name = "MSM VoIP",
987 .stream_name = "VoIP",
988 .cpu_dai_name = "VoIP",
989 .platform_name = "msm-voip-dsp",
990 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700991 .codec_dai_name = "snd-soc-dummy-dai",
992 .codec_name = "snd-soc-dummy",
993 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
994 .ignore_suspend = 1,
995 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530996 .be_id = MSM_FRONTEND_DAI_VOIP,
997 },
998 {
999 .name = "MSM8930 LPA",
1000 .stream_name = "LPA",
1001 .cpu_dai_name = "MultiMedia3",
1002 .platform_name = "msm-pcm-lpa",
1003 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001004 .codec_dai_name = "snd-soc-dummy-dai",
1005 .codec_name = "snd-soc-dummy",
1006 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1007 .ignore_suspend = 1,
1008 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301009 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1010 },
1011 /* Hostless PMC purpose */
1012 {
1013 .name = "SLIMBUS_0 Hostless",
1014 .stream_name = "SLIMBUS_0 Hostless",
1015 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1016 .platform_name = "msm-pcm-hostless",
1017 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001018 .codec_dai_name = "snd-soc-dummy-dai",
1019 .codec_name = "snd-soc-dummy",
1020 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301021 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1022 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001023 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301024 /* .be_id = do not care */
1025 },
1026 {
1027 .name = "INT_FM Hostless",
1028 .stream_name = "INT_FM Hostless",
1029 .cpu_dai_name = "INT_FM_HOSTLESS",
1030 .platform_name = "msm-pcm-hostless",
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},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301035 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1036 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001037 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301038 /* .be_id = do not care */
1039 },
1040 {
1041 .name = "MSM AFE-PCM RX",
1042 .stream_name = "AFE-PROXY RX",
1043 .cpu_dai_name = "msm-dai-q6.241",
1044 .codec_name = "msm-stub-codec.1",
1045 .codec_dai_name = "msm-stub-rx",
1046 .platform_name = "msm-pcm-afe",
1047 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001048 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301049 },
1050 {
1051 .name = "MSM AFE-PCM TX",
1052 .stream_name = "AFE-PROXY TX",
1053 .cpu_dai_name = "msm-dai-q6.240",
1054 .codec_name = "msm-stub-codec.1",
1055 .codec_dai_name = "msm-stub-tx",
1056 .platform_name = "msm-pcm-afe",
1057 .ignore_suspend = 1,
1058 },
1059 {
1060 .name = "MSM8930 Compr",
1061 .stream_name = "COMPR",
1062 .cpu_dai_name = "MultiMedia4",
Xiaojun Sang43f3d3b2017-04-27 14:44:25 +08001063 .platform_name = "msm-compress-dsp",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301064 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001065 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1066 .codec_dai_name = "snd-soc-dummy-dai",
1067 .codec_name = "snd-soc-dummy",
1068 .ignore_suspend = 1,
1069 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301070 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1071 },
1072 {
1073 .name = "AUXPCM Hostless",
1074 .stream_name = "AUXPCM Hostless",
1075 .cpu_dai_name = "AUXPCM_HOSTLESS",
1076 .platform_name = "msm-pcm-hostless",
1077 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001078 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301079 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1080 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001081 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1082 .codec_dai_name = "snd-soc-dummy-dai",
1083 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301084 },
1085 /* HDMI Hostless */
1086 {
1087 .name = "HDMI_RX_HOSTLESS",
1088 .stream_name = "HDMI_RX_HOSTLESS",
1089 .cpu_dai_name = "HDMI_HOSTLESS",
1090 .platform_name = "msm-pcm-hostless",
1091 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001092 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301093 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301094 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001095 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1096 .codec_dai_name = "snd-soc-dummy-dai",
1097 .codec_name = "snd-soc-dummy",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301098 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001099 {
1100 .name = "VoLTE",
1101 .stream_name = "VoLTE",
1102 .cpu_dai_name = "VoLTE",
1103 .platform_name = "msm-pcm-voice",
1104 .dynamic = 1,
1105 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1106 SND_SOC_DPCM_TRIGGER_POST},
1107 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1108 .ignore_suspend = 1,
1109 /* this dainlink has playback support */
1110 .ignore_pmdown_time = 1,
1111 .codec_dai_name = "snd-soc-dummy-dai",
1112 .codec_name = "snd-soc-dummy",
1113 .be_id = MSM_FRONTEND_DAI_VOLTE,
1114 },
1115 {
Helen Zengc5bd1bb2013-03-06 10:37:52 -08001116 .name = "Voice2",
1117 .stream_name = "Voice2",
1118 .cpu_dai_name = "Voice2",
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001119 .platform_name = "msm-pcm-voice",
1120 .dynamic = 1,
1121 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1122 SND_SOC_DPCM_TRIGGER_POST},
1123 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1124 .ignore_suspend = 1,
1125 /* this dainlink has playback support */
1126 .ignore_pmdown_time = 1,
1127 .codec_dai_name = "snd-soc-dummy-dai",
1128 .codec_name = "snd-soc-dummy",
Helen Zengc5bd1bb2013-03-06 10:37:52 -08001129 .be_id = MSM_FRONTEND_DAI_VOICE2,
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001130 },
1131 {
1132 .name = "MSM8960 LowLatency",
1133 .stream_name = "MultiMedia5",
1134 .cpu_dai_name = "MultiMedia5",
1135 .platform_name = "msm-lowlatency-pcm-dsp",
1136 .dynamic = 1,
1137 .codec_dai_name = "snd-soc-dummy-dai",
1138 .codec_name = "snd-soc-dummy",
1139 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1140 SND_SOC_DPCM_TRIGGER_POST},
1141 .ignore_suspend = 1,
1142 /* this dainlink has playback support */
1143 .ignore_pmdown_time = 1,
1144 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1145 },
Damir Didjustoc828dd12013-04-23 13:48:24 -07001146 {
1147 .name = "MSM8960 FM",
1148 .stream_name = "MultiMedia6",
1149 .cpu_dai_name = "MultiMedia6",
1150 .platform_name = "msm-pcm-loopback",
1151 .dynamic = 1,
1152 .codec_dai_name = "snd-soc-dummy-dai",
1153 .codec_name = "snd-soc-dummy",
1154 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1155 SND_SOC_DPCM_TRIGGER_POST},
1156 .ignore_suspend = 1,
1157 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1158 /* this dainlink has playback support */
1159 .ignore_pmdown_time = 1,
1160 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
1161 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301162 /* Backend DAI Links */
1163 {
1164 .name = LPASS_BE_SLIMBUS_0_RX,
1165 .stream_name = "Slimbus Playback",
1166 .cpu_dai_name = "msm-dai-q6.16384",
1167 .platform_name = "msm-pcm-routing",
1168 .codec_name = "sitar_codec",
1169 .codec_dai_name = "sitar_rx1",
1170 .no_pcm = 1,
1171 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1172 .init = &msm8930_audrx_init,
1173 .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
1174 .ops = &msm8930_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001175 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301176 },
1177 {
1178 .name = LPASS_BE_SLIMBUS_0_TX,
1179 .stream_name = "Slimbus Capture",
1180 .cpu_dai_name = "msm-dai-q6.16385",
1181 .platform_name = "msm-pcm-routing",
1182 .codec_name = "sitar_codec",
1183 .codec_dai_name = "sitar_tx1",
1184 .no_pcm = 1,
1185 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1186 .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
1187 .ops = &msm8930_be_ops,
1188 },
1189 /* Backend BT/FM DAI Links */
1190 {
1191 .name = LPASS_BE_INT_BT_SCO_RX,
1192 .stream_name = "Internal BT-SCO Playback",
1193 .cpu_dai_name = "msm-dai-q6.12288",
1194 .platform_name = "msm-pcm-routing",
1195 .codec_name = "msm-stub-codec.1",
1196 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301197 .no_pcm = 1,
1198 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
1199 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001200 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301201 },
1202 {
1203 .name = LPASS_BE_INT_BT_SCO_TX,
1204 .stream_name = "Internal BT-SCO Capture",
1205 .cpu_dai_name = "msm-dai-q6.12289",
1206 .platform_name = "msm-pcm-routing",
1207 .codec_name = "msm-stub-codec.1",
1208 .codec_dai_name = "msm-stub-tx",
1209 .no_pcm = 1,
1210 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
1211 .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
1212 },
1213 {
1214 .name = LPASS_BE_INT_FM_RX,
1215 .stream_name = "Internal FM Playback",
1216 .cpu_dai_name = "msm-dai-q6.12292",
1217 .platform_name = "msm-pcm-routing",
1218 .codec_name = "msm-stub-codec.1",
1219 .codec_dai_name = "msm-stub-rx",
1220 .no_pcm = 1,
1221 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1222 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001223 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301224 },
1225 {
1226 .name = LPASS_BE_INT_FM_TX,
1227 .stream_name = "Internal FM Capture",
1228 .cpu_dai_name = "msm-dai-q6.12293",
1229 .platform_name = "msm-pcm-routing",
1230 .codec_name = "msm-stub-codec.1",
1231 .codec_dai_name = "msm-stub-tx",
1232 .no_pcm = 1,
1233 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1234 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1235 },
1236 /* HDMI BACK END DAI Link */
1237 {
1238 .name = LPASS_BE_HDMI,
1239 .stream_name = "HDMI Playback",
1240 .cpu_dai_name = "msm-dai-q6-hdmi.8",
1241 .platform_name = "msm-pcm-routing",
1242 .codec_name = "msm-stub-codec.1",
1243 .codec_dai_name = "msm-stub-rx",
1244 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301245 .be_id = MSM_BACKEND_DAI_HDMI_RX,
1246 .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001247 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301248 },
1249 /* Backend AFE DAI Links */
1250 {
1251 .name = LPASS_BE_AFE_PCM_RX,
1252 .stream_name = "AFE Playback",
1253 .cpu_dai_name = "msm-dai-q6.224",
1254 .platform_name = "msm-pcm-routing",
1255 .codec_name = "msm-stub-codec.1",
1256 .codec_dai_name = "msm-stub-rx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301257 .no_pcm = 1,
1258 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina69ab7352012-10-23 16:52:01 -07001259 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001260 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301261 },
1262 {
1263 .name = LPASS_BE_AFE_PCM_TX,
1264 .stream_name = "AFE Capture",
1265 .cpu_dai_name = "msm-dai-q6.225",
1266 .platform_name = "msm-pcm-routing",
1267 .codec_name = "msm-stub-codec.1",
1268 .codec_dai_name = "msm-stub-tx",
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301269 .no_pcm = 1,
1270 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina69ab7352012-10-23 16:52:01 -07001271 .be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301272 },
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001273 /* AUX PCM Backend DAI Links */
1274 {
1275 .name = LPASS_BE_AUXPCM_RX,
1276 .stream_name = "AUX PCM Playback",
1277 .cpu_dai_name = "msm-dai-q6.2",
1278 .platform_name = "msm-pcm-routing",
1279 .codec_name = "msm-stub-codec.1",
1280 .codec_dai_name = "msm-stub-rx",
1281 .no_pcm = 1,
1282 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1283 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
1284 .ops = &msm8930_auxpcm_be_ops,
1285 },
1286 {
1287 .name = LPASS_BE_AUXPCM_TX,
1288 .stream_name = "AUX PCM Capture",
1289 .cpu_dai_name = "msm-dai-q6.3",
1290 .platform_name = "msm-pcm-routing",
1291 .codec_name = "msm-stub-codec.1",
1292 .codec_dai_name = "msm-stub-tx",
1293 .no_pcm = 1,
1294 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1295 .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
Kuirong Wangae395b02012-09-20 11:43:17 -07001296 .ops = &msm8930_auxpcm_be_ops,
Bhalchandra Gajare2e0893e2012-05-24 00:39:47 -07001297 },
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301298 /* Incall Music BACK END DAI Link */
1299 {
1300 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1301 .stream_name = "Voice Farend Playback",
1302 .cpu_dai_name = "msm-dai-q6.32773",
1303 .platform_name = "msm-pcm-routing",
1304 .codec_name = "msm-stub-codec.1",
1305 .codec_dai_name = "msm-stub-rx",
1306 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301307 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1308 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1309 },
1310 /* Incall Record Uplink BACK END DAI Link */
1311 {
1312 .name = LPASS_BE_INCALL_RECORD_TX,
1313 .stream_name = "Voice Uplink Capture",
1314 .cpu_dai_name = "msm-dai-q6.32772",
1315 .platform_name = "msm-pcm-routing",
1316 .codec_name = "msm-stub-codec.1",
1317 .codec_dai_name = "msm-stub-tx",
1318 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301319 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1320 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
1321 },
1322 /* Incall Record Downlink BACK END DAI Link */
1323 {
1324 .name = LPASS_BE_INCALL_RECORD_RX,
1325 .stream_name = "Voice Downlink Capture",
1326 .cpu_dai_name = "msm-dai-q6.32771",
1327 .platform_name = "msm-pcm-routing",
1328 .codec_name = "msm-stub-codec.1",
1329 .codec_dai_name = "msm-stub-tx",
1330 .no_pcm = 1,
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301331 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1332 .be_hw_params_fixup = msm8930_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001333 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301334 },
1335};
1336
1337struct snd_soc_card snd_soc_card_msm8930 = {
1338 .name = "msm8930-sitar-snd-card",
1339 .dai_link = msm8930_dai,
1340 .num_links = ARRAY_SIZE(msm8930_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001341 .controls = sitar_msm8930_controls,
1342 .num_controls = ARRAY_SIZE(sitar_msm8930_controls),
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301343};
1344
1345static struct platform_device *msm8930_snd_device;
1346
1347static int msm8930_configure_headset_mic_gpios(void)
1348{
1349 int ret;
1350 ret = gpio_request(80, "US_EURO_SWITCH");
1351 if (ret) {
1352 pr_err("%s: Failed to request gpio 80\n", __func__);
1353 return ret;
1354 }
1355 ret = gpio_direction_output(80, 0);
1356 if (ret) {
1357 pr_err("%s: Unable to set direction\n", __func__);
1358 gpio_free(80);
1359 }
1360 msm8930_headset_gpios_configured = 0;
1361 return 0;
1362}
1363static void msm8930_free_headset_mic_gpios(void)
1364{
1365 if (msm8930_headset_gpios_configured)
1366 gpio_free(80);
1367}
1368
1369static int __init msm8930_audio_init(void)
1370{
1371 int ret;
1372
Stepan Moskovchenko5b9e7762012-09-21 20:32:17 -07001373 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301374 pr_err("%s: Not the right machine type\n", __func__);
1375 return -ENODEV ;
1376 }
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001377 mbhc_cfg.calibration = def_sitar_mbhc_cal();
1378 if (!mbhc_cfg.calibration) {
Asish Bhattacharyaf868a1f2012-03-05 10:07:44 -08001379 pr_err("Calibration data allocation failed\n");
1380 return -ENOMEM;
1381 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301382
1383 msm8930_snd_device = platform_device_alloc("soc-audio", 0);
1384 if (!msm8930_snd_device) {
1385 pr_err("Platform device allocation failed\n");
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001386 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301387 return -ENOMEM;
1388 }
1389
1390 platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
1391 ret = platform_device_add(msm8930_snd_device);
1392 if (ret) {
1393 platform_device_put(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001394 kfree(mbhc_cfg.calibration);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301395 return ret;
1396 }
1397
1398 if (msm8930_configure_headset_mic_gpios()) {
1399 pr_err("%s Fail to configure headset mic gpios\n", __func__);
1400 msm8930_headset_gpios_configured = 0;
1401 } else
1402 msm8930_headset_gpios_configured = 1;
1403
Kuirong Wangae395b02012-09-20 11:43:17 -07001404 atomic_set(&auxpcm_rsc_ref, 0);
Laxminath Kasam87be2992013-03-29 12:34:41 +05301405 mutex_init(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301406 return ret;
1407
1408}
1409module_init(msm8930_audio_init);
1410
1411static void __exit msm8930_audio_exit(void)
1412{
Stepan Moskovchenko5b9e7762012-09-21 20:32:17 -07001413 if (!soc_class_is_msm8930()) {
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301414 pr_err("%s: Not the right machine type\n", __func__);
1415 return ;
1416 }
1417 msm8930_free_headset_mic_gpios();
1418 platform_device_unregister(msm8930_snd_device);
Bhalchandra Gajare466aafe2012-05-02 17:55:26 -07001419 kfree(mbhc_cfg.calibration);
Laxminath Kasam87be2992013-03-29 12:34:41 +05301420 mutex_destroy(&cdc_mclk_mutex);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301421}
1422module_exit(msm8930_audio_exit);
1423
1424MODULE_DESCRIPTION("ALSA SoC MSM8930");
1425MODULE_LICENSE("GPL v2");