blob: 7aea4ae825ec4795db1176b2bed67aea1da99b5e [file] [log] [blame]
Simmi Pateriya71d63872012-11-08 01:06:30 +05301/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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>
Kiran Kandidb0a4b02011-08-23 09:32:09 -070014#include <linux/delay.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/gpio.h>
16#include <linux/mfd/pm8xxx/pm8921.h>
17#include <linux/platform_device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#include <linux/mfd/pm8xxx/pm8921.h>
Joonwoo Park0976d012011-12-22 11:48:18 -080019#include <linux/slab.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020#include <sound/core.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include <sound/pcm.h>
24#include <sound/jack.h>
Bradley Rubin229c6a52011-07-12 16:18:48 -070025#include <asm/mach-types.h>
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -080026#include <mach/socinfo.h>
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070027#include <linux/mfd/wcd9xxx/core.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028#include "msm-pcm-routing.h"
Bhalchandra Gajare0b9d4d52011-10-21 16:17:47 -070029#include "../codecs/wcd9310.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030
31/* 8960 machine driver */
32
33#define PM8921_GPIO_BASE NR_GPIO_IRQS
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070034#define PM8921_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070035#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
36
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070037#define MSM8960_SPK_ON 1
38#define MSM8960_SPK_OFF 0
39
40#define msm8960_SLIM_0_RX_MAX_CHANNELS 2
41#define msm8960_SLIM_0_TX_MAX_CHANNELS 4
42
Kuirong Wang054e1832012-05-11 15:43:30 -070043#define SAMPLE_RATE_8KHZ 8000
44#define SAMPLE_RATE_16KHZ 16000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
Kiran Kandi462acea2011-08-31 23:53:14 -070046#define BOTTOM_SPK_AMP_POS 0x1
47#define BOTTOM_SPK_AMP_NEG 0x2
48#define TOP_SPK_AMP_POS 0x4
49#define TOP_SPK_AMP_NEG 0x8
Kiran Kandi97fe19d2012-05-20 22:34:04 -070050#define TOP_SPK_AMP 0x10
Kiran Kandi462acea2011-08-31 23:53:14 -070051
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070052#define GPIO_AUX_PCM_DOUT 63
53#define GPIO_AUX_PCM_DIN 64
54#define GPIO_AUX_PCM_SYNC 65
55#define GPIO_AUX_PCM_CLK 66
56
Joonwoo Park0976d012011-12-22 11:48:18 -080057#define TABLA_EXT_CLK_RATE 12288000
58
Joonwoo Park6b9b03f2012-01-23 18:48:54 -080059#define TABLA_MBHC_DEF_BUTTONS 8
Joonwoo Park0976d012011-12-22 11:48:18 -080060#define TABLA_MBHC_DEF_RLOADS 5
61
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070062#define JACK_DETECT_GPIO 38
63#define JACK_DETECT_INT PM8921_GPIO_IRQ(PM8921_IRQ_BASE, JACK_DETECT_GPIO)
Joonwoo Park2cc13f02012-05-09 12:44:25 -070064#define JACK_US_EURO_SEL_GPIO 35
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -070065
Harmandeep Singh0dd82412011-11-11 09:46:17 -080066static u32 top_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(18);
67static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070068static int msm8960_spk_control;
Kiran Kandi462acea2011-08-31 23:53:14 -070069static int msm8960_ext_bottom_spk_pamp;
70static int msm8960_ext_top_spk_pamp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071static int msm8960_slim_0_rx_ch = 1;
72static int msm8960_slim_0_tx_ch = 1;
73
Kuirong Wang054e1832012-05-11 15:43:30 -070074static int msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -070075static int msm8960_btsco_ch = 1;
Vicky Sehrawat45204132012-11-05 17:54:13 -080076static int hdmi_rate_variable;
Kuirong Wang054e1832012-05-11 15:43:30 -070077static int msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
78
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070079static struct clk *codec_clk;
80static int clk_users;
81
82static int msm8960_headset_gpios_configured;
83
84static struct snd_soc_jack hs_jack;
Bradley Rubincb1e2732011-06-23 16:49:20 -070085static struct snd_soc_jack button_jack;
Kuirong Wangae395b02012-09-20 11:43:17 -070086static atomic_t auxpcm_rsc_ref;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070087
Simmi Pateriya71d63872012-11-08 01:06:30 +053088static bool hs_micbias_always_on;
89module_param(hs_micbias_always_on, bool, 0444);
90MODULE_PARM_DESC(hs_micbias_always_on, "Keep micbias always on if headset is inserted");
91
Joonwoo Park9115ade2012-04-18 13:14:10 -070092static bool hs_detect_use_gpio;
93module_param(hs_detect_use_gpio, bool, 0444);
94MODULE_PARM_DESC(hs_detect_use_gpio, "Use GPIO for headset detection");
95
Ravi Kumar Alamanda07b6bd62012-08-15 18:39:47 -070096static bool hs_detect_extn_cable;
97module_param(hs_detect_extn_cable, bool, 0444);
98MODULE_PARM_DESC(hs_detect_extn_cable, "Enable extension cable feature");
99
Joonwoo Park9115ade2012-04-18 13:14:10 -0700100static bool hs_detect_use_firmware;
101module_param(hs_detect_use_firmware, bool, 0444);
102MODULE_PARM_DESC(hs_detect_use_firmware, "Use firmware for headset detection");
103
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700104static int msm8960_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
105 bool dapm);
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700106static bool msm8960_swap_gnd_mic(struct snd_soc_codec *codec);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700107
108static struct tabla_mbhc_config mbhc_cfg = {
109 .headset_jack = &hs_jack,
110 .button_jack = &button_jack,
111 .read_fw_bin = false,
112 .calibration = NULL,
113 .micbias = TABLA_MICBIAS2,
114 .mclk_cb_fn = msm8960_enable_codec_ext_clk,
115 .mclk_rate = TABLA_EXT_CLK_RATE,
116 .gpio = 0,
117 .gpio_irq = 0,
118 .gpio_level_insert = 1,
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700119 .swap_gnd_mic = NULL,
Ravi Kumar Alamanda07b6bd62012-08-15 18:39:47 -0700120 .detect_extn_cable = false,
Simmi Pateriya71d63872012-11-08 01:06:30 +0530121 .micbias_always_on = false
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700122};
Joonwoo Park0976d012011-12-22 11:48:18 -0800123
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700124static u32 us_euro_sel_gpio = PM8921_GPIO_PM_TO_SYS(JACK_US_EURO_SEL_GPIO);
125
Joonwoo Park28f49c82012-03-16 12:29:21 -0700126static struct mutex cdc_mclk_mutex;
127
Kiran Kandi462acea2011-08-31 23:53:14 -0700128static void msm8960_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700129{
130 int ret = 0;
131
132 struct pm_gpio param = {
133 .direction = PM_GPIO_DIR_OUT,
134 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
135 .output_value = 1,
136 .pull = PM_GPIO_PULL_NO,
137 .vin_sel = PM_GPIO_VIN_S4,
138 .out_strength = PM_GPIO_STRENGTH_MED,
Kiran Kandi462acea2011-08-31 23:53:14 -0700139 .
140 function = PM_GPIO_FUNC_NORMAL,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 };
142
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800143 if (spk_amp_gpio == bottom_spk_pamp_gpio) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800145 ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
Kiran Kandi462acea2011-08-31 23:53:14 -0700146 if (ret) {
147 pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800148 __func__, bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700149 return;
150 }
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800151 ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
Kiran Kandi462acea2011-08-31 23:53:14 -0700152 if (ret)
153 pr_err("%s: Failed to configure Bottom Spk Ampl"
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800154 " gpio %u\n", __func__, bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700155 else {
156 pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800157 gpio_direction_output(bottom_spk_pamp_gpio, 1);
Kiran Kandi462acea2011-08-31 23:53:14 -0700158 }
159
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800160 } else if (spk_amp_gpio == top_spk_pamp_gpio) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700161
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800162 ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700163 if (ret) {
164 pr_err("%s: Error requesting GPIO %d\n", __func__,
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800165 top_spk_pamp_gpio);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700166 return;
167 }
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800168 ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700169 if (ret)
Kiran Kandi462acea2011-08-31 23:53:14 -0700170 pr_err("%s: Failed to configure Top Spk Ampl"
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800171 " gpio %u\n", __func__, top_spk_pamp_gpio);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700172 else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700173 pr_debug("%s: enable Top spkr amp gpio\n", __func__);
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800174 gpio_direction_output(top_spk_pamp_gpio, 1);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700175 }
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700176 } else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700177 pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
178 " gpio = %u\n", __func__, spk_amp_gpio);
179 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181}
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700182
Kiran Kandi462acea2011-08-31 23:53:14 -0700183static void msm8960_ext_spk_power_amp_on(u32 spk)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700184{
Kiran Kandi462acea2011-08-31 23:53:14 -0700185 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
186
187 if ((msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
188 (msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
189
190 pr_debug("%s() External Bottom Speaker Ampl already "
191 "turned on. spk = 0x%08x\n", __func__, spk);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700192 return;
Kiran Kandi462acea2011-08-31 23:53:14 -0700193 }
194
195 msm8960_ext_bottom_spk_pamp |= spk;
196
197 if ((msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
198 (msm8960_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
199
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800200 msm8960_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700201 pr_debug("%s: slepping 4 ms after turning on external "
202 " Bottom Speaker Ampl\n", __func__);
203 usleep_range(4000, 4000);
204 }
205
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700206 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700207
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700208 pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
209 __func__, msm8960_ext_top_spk_pamp, spk);
210
211 if (((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
212 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
213 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP)) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700214
215 pr_debug("%s() External Top Speaker Ampl already"
216 "turned on. spk = 0x%08x\n", __func__, spk);
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700217 return;
Kiran Kandi462acea2011-08-31 23:53:14 -0700218 }
219
220 msm8960_ext_top_spk_pamp |= spk;
221
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700222 if (((msm8960_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
223 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) ||
224 (msm8960_ext_top_spk_pamp & TOP_SPK_AMP)) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700225
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800226 msm8960_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700227 pr_debug("%s: sleeping 4 ms after turning on "
228 " external Top Speaker Ampl\n", __func__);
229 usleep_range(4000, 4000);
230 }
231 } else {
232
233 pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
234 __func__, spk);
235 return;
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700236 }
Kiran Kandi462acea2011-08-31 23:53:14 -0700237}
238
239static void msm8960_ext_spk_power_amp_off(u32 spk)
240{
241 if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
242
243 if (!msm8960_ext_bottom_spk_pamp)
244 return;
245
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800246 gpio_direction_output(bottom_spk_pamp_gpio, 0);
247 gpio_free(bottom_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700248 msm8960_ext_bottom_spk_pamp = 0;
249
250 pr_debug("%s: sleeping 4 ms after turning off external Bottom"
251 " Speaker Ampl\n", __func__);
252
253 usleep_range(4000, 4000);
254
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700255 } else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG | TOP_SPK_AMP)) {
256
257 pr_debug("%s: top_spk_amp_state = 0x%x spk_event = 0x%x\n",
258 __func__, msm8960_ext_top_spk_pamp, spk);
Kiran Kandi462acea2011-08-31 23:53:14 -0700259
260 if (!msm8960_ext_top_spk_pamp)
261 return;
262
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700263 if ((spk & TOP_SPK_AMP_POS) || (spk & TOP_SPK_AMP_NEG)) {
264
265 msm8960_ext_top_spk_pamp &= (~(TOP_SPK_AMP_POS |
266 TOP_SPK_AMP_NEG));
267 } else if (spk & TOP_SPK_AMP) {
268 msm8960_ext_top_spk_pamp &= ~TOP_SPK_AMP;
269 }
270
271 if (msm8960_ext_top_spk_pamp)
272 return;
273
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800274 gpio_direction_output(top_spk_pamp_gpio, 0);
275 gpio_free(top_spk_pamp_gpio);
Kiran Kandi462acea2011-08-31 23:53:14 -0700276 msm8960_ext_top_spk_pamp = 0;
277
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700278 pr_debug("%s: sleeping 4 ms after ext Top Spek Ampl is off\n",
279 __func__);
Kiran Kandi462acea2011-08-31 23:53:14 -0700280
281 usleep_range(4000, 4000);
282 } else {
283
284 pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
285 __func__, spk);
286 return;
287 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288}
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700289
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290static void msm8960_ext_control(struct snd_soc_codec *codec)
291{
292 struct snd_soc_dapm_context *dapm = &codec->dapm;
293
Jayasena Sangaraboina247d36e2012-04-17 10:16:18 -0700294 mutex_lock(&dapm->codec->mutex);
295
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 pr_debug("%s: msm8960_spk_control = %d", __func__, msm8960_spk_control);
Peter Lohmannb8203ef2011-10-07 15:05:28 -0700297 if (msm8960_spk_control == MSM8960_SPK_ON) {
298 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
299 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
300 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
301 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
302 } else {
303 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
304 snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
305 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
306 snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
307 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308
309 snd_soc_dapm_sync(dapm);
Jayasena Sangaraboina247d36e2012-04-17 10:16:18 -0700310 mutex_unlock(&dapm->codec->mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311}
312
313static int msm8960_get_spk(struct snd_kcontrol *kcontrol,
314 struct snd_ctl_elem_value *ucontrol)
315{
316 pr_debug("%s: msm8960_spk_control = %d", __func__, msm8960_spk_control);
317 ucontrol->value.integer.value[0] = msm8960_spk_control;
318 return 0;
319}
320static int msm8960_set_spk(struct snd_kcontrol *kcontrol,
321 struct snd_ctl_elem_value *ucontrol)
322{
323 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
324
325 pr_debug("%s()\n", __func__);
326 if (msm8960_spk_control == ucontrol->value.integer.value[0])
327 return 0;
328
329 msm8960_spk_control = ucontrol->value.integer.value[0];
330 msm8960_ext_control(codec);
331 return 1;
332}
333static int msm8960_spkramp_event(struct snd_soc_dapm_widget *w,
334 struct snd_kcontrol *k, int event)
335{
336 pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700337
338 if (SND_SOC_DAPM_EVENT_ON(event)) {
Kiran Kandi462acea2011-08-31 23:53:14 -0700339 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
340 msm8960_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
341 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
342 msm8960_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
343 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
344 msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
345 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
346 msm8960_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700347 else if (!strncmp(w->name, "Ext Spk Top", 12))
348 msm8960_ext_spk_power_amp_on(TOP_SPK_AMP);
Kiran Kandi462acea2011-08-31 23:53:14 -0700349 else {
350 pr_err("%s() Invalid Speaker Widget = %s\n",
351 __func__, w->name);
352 return -EINVAL;
353 }
354
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700355 } else {
Kiran Kandi462acea2011-08-31 23:53:14 -0700356 if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
357 msm8960_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
358 else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
359 msm8960_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
360 else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
361 msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
362 else if (!strncmp(w->name, "Ext Spk Top Neg", 15))
363 msm8960_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700364 else if (!strncmp(w->name, "Ext Spk Top", 12))
365 msm8960_ext_spk_power_amp_off(TOP_SPK_AMP);
Kiran Kandi462acea2011-08-31 23:53:14 -0700366 else {
367 pr_err("%s() Invalid Speaker Widget = %s\n",
368 __func__, w->name);
369 return -EINVAL;
370 }
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700371 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372 return 0;
373}
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700374
375static int msm8960_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
376 bool dapm)
Joonwoo Park0976d012011-12-22 11:48:18 -0800377{
Joonwoo Park28f49c82012-03-16 12:29:21 -0700378 int r = 0;
Joonwoo Park0976d012011-12-22 11:48:18 -0800379 pr_debug("%s: enable = %d\n", __func__, enable);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700380
381 mutex_lock(&cdc_mclk_mutex);
Joonwoo Park0976d012011-12-22 11:48:18 -0800382 if (enable) {
383 clk_users++;
384 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700385 if (clk_users == 1) {
386 if (codec_clk) {
387 clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530388 clk_prepare_enable(codec_clk);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700389 tabla_mclk_enable(codec, 1, dapm);
390 } else {
391 pr_err("%s: Error setting Tabla MCLK\n",
392 __func__);
393 clk_users--;
394 r = -EINVAL;
395 }
Joonwoo Park0976d012011-12-22 11:48:18 -0800396 }
397 } else {
Joonwoo Park28f49c82012-03-16 12:29:21 -0700398 if (clk_users > 0) {
399 clk_users--;
400 pr_debug("%s: clk_users = %d\n", __func__, clk_users);
401 if (clk_users == 0) {
402 pr_debug("%s: disabling MCLK. clk_users = %d\n",
Joonwoo Park0976d012011-12-22 11:48:18 -0800403 __func__, clk_users);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700404 tabla_mclk_enable(codec, 0, dapm);
Asish Bhattacharya4776d962012-04-25 12:08:09 +0530405 clk_disable_unprepare(codec_clk);
Joonwoo Park28f49c82012-03-16 12:29:21 -0700406 }
407 } else {
408 pr_err("%s: Error releasing Tabla MCLK\n", __func__);
409 r = -EINVAL;
Joonwoo Park0976d012011-12-22 11:48:18 -0800410 }
411 }
Joonwoo Park28f49c82012-03-16 12:29:21 -0700412 mutex_unlock(&cdc_mclk_mutex);
413 return r;
Joonwoo Park0976d012011-12-22 11:48:18 -0800414}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700416static bool msm8960_swap_gnd_mic(struct snd_soc_codec *codec)
417{
418 int value = gpio_get_value_cansleep(us_euro_sel_gpio);
419 pr_debug("%s: US EURO select switch %d to %d\n", __func__, value,
420 !value);
421 gpio_set_value_cansleep(us_euro_sel_gpio, !value);
422 return true;
423}
424
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700425static int msm8960_mclk_event(struct snd_soc_dapm_widget *w,
426 struct snd_kcontrol *kcontrol, int event)
427{
428 pr_debug("%s: event = %d\n", __func__, event);
429
430 switch (event) {
431 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700432 return msm8960_enable_codec_ext_clk(w->codec, 1, true);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700433 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700434 return msm8960_enable_codec_ext_clk(w->codec, 0, true);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700435 }
436 return 0;
437}
438
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439static const struct snd_soc_dapm_widget msm8960_dapm_widgets[] = {
Kiran Kandi3a30bda2011-08-15 10:36:42 -0700440
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700441 SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
442 msm8960_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
443
Kiran Kandi462acea2011-08-31 23:53:14 -0700444 SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm8960_spkramp_event),
445 SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm8960_spkramp_event),
446
447 SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm8960_spkramp_event),
448 SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm8960_spkramp_event),
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700449 SND_SOC_DAPM_SPK("Ext Spk Top", msm8960_spkramp_event),
Kiran Kandi3a30bda2011-08-15 10:36:42 -0700450
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 SND_SOC_DAPM_MIC("Handset Mic", NULL),
452 SND_SOC_DAPM_MIC("Headset Mic", NULL),
453 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700454 SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
455 SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700456
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700457 SND_SOC_DAPM_MIC("Digital Mic1", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700458 SND_SOC_DAPM_MIC("Digital Mic2", NULL),
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700459 SND_SOC_DAPM_MIC("Digital Mic3", NULL),
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700460 SND_SOC_DAPM_MIC("Digital Mic4", NULL),
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700461 SND_SOC_DAPM_MIC("Digital Mic5", NULL),
462 SND_SOC_DAPM_MIC("Digital Mic6", NULL),
463
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700464};
465
Bradley Rubin229c6a52011-07-12 16:18:48 -0700466static const struct snd_soc_dapm_route common_audio_map[] = {
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700467
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700468 {"RX_BIAS", NULL, "MCLK"},
469 {"LDO_H", NULL, "MCLK"},
470
471 /* Speaker path */
Kiran Kandi462acea2011-08-31 23:53:14 -0700472 {"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
473 {"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
Kiran Kandidb0a4b02011-08-23 09:32:09 -0700474
Kiran Kandi462acea2011-08-31 23:53:14 -0700475 {"Ext Spk Top Pos", NULL, "LINEOUT2"},
476 {"Ext Spk Top Neg", NULL, "LINEOUT4"},
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700477 {"Ext Spk Top", NULL, "LINEOUT5"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700478
479 /* Microphone path */
Bradley Rubin229c6a52011-07-12 16:18:48 -0700480 {"AMIC1", NULL, "MIC BIAS1 Internal1"},
481 {"MIC BIAS1 Internal1", NULL, "Handset Mic"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700482
483 {"AMIC2", NULL, "MIC BIAS2 External"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484 {"MIC BIAS2 External", NULL, "Headset Mic"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700485
Patrick Laie519dd62011-09-28 12:37:11 -0700486 /**
487 * AMIC3 and AMIC4 inputs are connected to ANC microphones
488 * These mics are biased differently on CDP and FLUID
489 * routing entries below are based on bias arrangement
490 * on FLUID.
491 */
492 {"AMIC3", NULL, "MIC BIAS3 Internal1"},
Joonwoo Park557f5c42012-04-24 11:41:48 -0700493 {"MIC BIAS3 Internal1", NULL, "MIC BIAS2 External"},
494 {"MIC BIAS2 External", NULL, "ANCRight Headset Mic"},
Patrick Laie519dd62011-09-28 12:37:11 -0700495 {"AMIC4", NULL, "MIC BIAS1 Internal2"},
Joonwoo Park557f5c42012-04-24 11:41:48 -0700496 {"MIC BIAS1 Internal2", NULL, "MIC BIAS2 External"},
497 {"MIC BIAS2 External", NULL, "ANCLeft Headset Mic"},
Patrick Laie519dd62011-09-28 12:37:11 -0700498
Kiran Kandie9bf86a2011-07-21 16:50:41 -0700499 {"HEADPHONE", NULL, "LDO_H"},
500
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700501 /**
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700502 * The digital Mic routes are setup considering
503 * fluid as default device.
504 */
505
506 /**
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700507 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700508 * Digital Mic GM5 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700509 * Conncted to DMIC2 Input on Tabla codec.
510 */
511 {"DMIC2", NULL, "MIC BIAS1 External"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700512 {"MIC BIAS1 External", NULL, "Digital Mic1"},
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700513
514 /**
515 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700516 * Digital Mic GM6 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700517 * Conncted to DMIC1 Input on Tabla codec.
518 */
519 {"DMIC1", NULL, "MIC BIAS1 External"},
520 {"MIC BIAS1 External", NULL, "Digital Mic2"},
521
522 /**
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700523 * Digital Mic3. Back Bottom Digital Mic on Fluid.
524 * Digital Mic GM1 on CDP mainboard.
525 * Conncted to DMIC4 Input on Tabla codec.
526 */
527 {"DMIC4", NULL, "MIC BIAS3 External"},
528 {"MIC BIAS3 External", NULL, "Digital Mic3"},
529
530 /**
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700531 * Digital Mic4. Back top Digital Mic on Fluid.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700532 * Digital Mic GM2 on CDP mainboard.
Kiran Kandia21d6bc2011-07-17 21:19:59 -0700533 * Conncted to DMIC3 Input on Tabla codec.
534 */
535 {"DMIC3", NULL, "MIC BIAS3 External"},
536 {"MIC BIAS3 External", NULL, "Digital Mic4"},
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700537
538 /**
539 * Digital Mic5. Front top Digital Mic on Fluid.
540 * Digital Mic GM3 on CDP mainboard.
541 * Conncted to DMIC5 Input on Tabla codec.
542 */
543 {"DMIC5", NULL, "MIC BIAS4 External"},
544 {"MIC BIAS4 External", NULL, "Digital Mic5"},
545
Patrick Laicb7802b2011-10-04 12:39:18 -0700546 /* Tabla digital Mic6 - back bottom digital Mic on Liquid and
547 * bottom mic on CDP. FLUID/MTP do not have dmic6 installed.
Bhalchandra Gajarea0101ba2011-08-11 20:05:56 -0700548 */
549 {"DMIC6", NULL, "MIC BIAS4 External"},
550 {"MIC BIAS4 External", NULL, "Digital Mic6"},
Bradley Rubin229c6a52011-07-12 16:18:48 -0700551};
552
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553static const char *spk_function[] = {"Off", "On"};
Patrick Lai9f4b4292011-07-16 22:11:09 -0700554static const char *slim0_rx_ch_text[] = {"One", "Two"};
555static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
Vicky Sehrawat45204132012-11-05 17:54:13 -0800556static const char * const hdmi_rate[] = {"Default", "Variable"};
Patrick Lai9f4b4292011-07-16 22:11:09 -0700557
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558static const struct soc_enum msm8960_enum[] = {
559 SOC_ENUM_SINGLE_EXT(2, spk_function),
Patrick Lai9f4b4292011-07-16 22:11:09 -0700560 SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
561 SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
Vicky Sehrawat45204132012-11-05 17:54:13 -0800562 SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563};
564
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700565static const char *btsco_rate_text[] = {"8000", "16000"};
566static const struct soc_enum msm8960_btsco_enum[] = {
567 SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
568};
569
Kuirong Wang054e1832012-05-11 15:43:30 -0700570static const char *auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
571static const struct soc_enum msm8960_auxpcm_enum[] = {
572 SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text),
573};
574
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575static int msm8960_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
576 struct snd_ctl_elem_value *ucontrol)
577{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700578 pr_debug("%s: msm8960_slim_0_rx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800579 msm8960_slim_0_rx_ch);
Patrick Lai9f4b4292011-07-16 22:11:09 -0700580 ucontrol->value.integer.value[0] = msm8960_slim_0_rx_ch - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 return 0;
582}
583
584static int msm8960_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
585 struct snd_ctl_elem_value *ucontrol)
586{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700587 msm8960_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588
Patrick Lai9f4b4292011-07-16 22:11:09 -0700589 pr_debug("%s: msm8960_slim_0_rx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800590 msm8960_slim_0_rx_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700591 return 1;
592}
593
594static int msm8960_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
595 struct snd_ctl_elem_value *ucontrol)
596{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700597 pr_debug("%s: msm8960_slim_0_tx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800598 msm8960_slim_0_tx_ch);
Patrick Lai9f4b4292011-07-16 22:11:09 -0700599 ucontrol->value.integer.value[0] = msm8960_slim_0_tx_ch - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600 return 0;
601}
602
603static int msm8960_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
604 struct snd_ctl_elem_value *ucontrol)
605{
Patrick Lai9f4b4292011-07-16 22:11:09 -0700606 msm8960_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607
608 pr_debug("%s: msm8960_slim_0_tx_ch = %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -0800609 msm8960_slim_0_tx_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610 return 1;
611}
612
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700613static int msm8960_btsco_rate_get(struct snd_kcontrol *kcontrol,
614 struct snd_ctl_elem_value *ucontrol)
615{
Joonwoo Park0976d012011-12-22 11:48:18 -0800616 pr_debug("%s: msm8960_btsco_rate = %d", __func__, msm8960_btsco_rate);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700617 ucontrol->value.integer.value[0] = msm8960_btsco_rate;
618 return 0;
619}
620
621static int msm8960_btsco_rate_put(struct snd_kcontrol *kcontrol,
622 struct snd_ctl_elem_value *ucontrol)
623{
624 switch (ucontrol->value.integer.value[0]) {
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700625 case 8000:
Kuirong Wang054e1832012-05-11 15:43:30 -0700626 msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700627 break;
Kuirong Wangfd8e0b32012-05-30 19:45:04 -0700628 case 16000:
Kuirong Wang054e1832012-05-11 15:43:30 -0700629 msm8960_btsco_rate = SAMPLE_RATE_16KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700630 break;
631 default:
Kuirong Wang054e1832012-05-11 15:43:30 -0700632 msm8960_btsco_rate = SAMPLE_RATE_8KHZ;
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700633 break;
634 }
Joonwoo Park0976d012011-12-22 11:48:18 -0800635 pr_debug("%s: msm8960_btsco_rate = %d\n", __func__, msm8960_btsco_rate);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700636 return 0;
637}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638
Kuirong Wang054e1832012-05-11 15:43:30 -0700639static int msm8960_auxpcm_rate_get(struct snd_kcontrol *kcontrol,
640 struct snd_ctl_elem_value *ucontrol)
641{
642 pr_debug("%s: msm8960_auxpcm_rate = %d", __func__,
643 msm8960_auxpcm_rate);
644 ucontrol->value.integer.value[0] = msm8960_auxpcm_rate;
645 return 0;
646}
647
648static int msm8960_auxpcm_rate_put(struct snd_kcontrol *kcontrol,
649 struct snd_ctl_elem_value *ucontrol)
650{
651 switch (ucontrol->value.integer.value[0]) {
652 case 0:
653 msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
654 break;
655 case 1:
656 msm8960_auxpcm_rate = SAMPLE_RATE_16KHZ;
657 break;
658 default:
659 msm8960_auxpcm_rate = SAMPLE_RATE_8KHZ;
660 break;
661 }
662 pr_debug("%s: msm8960_auxpcm_rate = %d"
663 "ucontrol->value.integer.value[0] = %d\n", __func__,
664 msm8960_auxpcm_rate,
665 (int)ucontrol->value.integer.value[0]);
666 return 0;
667}
668
Vicky Sehrawat45204132012-11-05 17:54:13 -0800669static int msm8960_hdmi_rate_put(struct snd_kcontrol *kcontrol,
670 struct snd_ctl_elem_value *ucontrol)
671{
672 hdmi_rate_variable = ucontrol->value.integer.value[0];
673 pr_debug("%s: hdmi_rate_variable = %d\n", __func__, hdmi_rate_variable);
674 return 0;
675}
676
677static int msm8960_hdmi_rate_get(struct snd_kcontrol *kcontrol,
678 struct snd_ctl_elem_value *ucontrol)
679{
680 ucontrol->value.integer.value[0] = hdmi_rate_variable;
681 return 0;
682}
683
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684static const struct snd_kcontrol_new tabla_msm8960_controls[] = {
685 SOC_ENUM_EXT("Speaker Function", msm8960_enum[0], msm8960_get_spk,
686 msm8960_set_spk),
Patrick Lai9f4b4292011-07-16 22:11:09 -0700687 SOC_ENUM_EXT("SLIM_0_RX Channels", msm8960_enum[1],
688 msm8960_slim_0_rx_ch_get, msm8960_slim_0_rx_ch_put),
689 SOC_ENUM_EXT("SLIM_0_TX Channels", msm8960_enum[2],
690 msm8960_slim_0_tx_ch_get, msm8960_slim_0_tx_ch_put),
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -0700691 SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8960_btsco_enum[0],
692 msm8960_btsco_rate_get, msm8960_btsco_rate_put),
Kuirong Wang054e1832012-05-11 15:43:30 -0700693 SOC_ENUM_EXT("AUX PCM SampleRate", msm8960_auxpcm_enum[0],
694 msm8960_auxpcm_rate_get, msm8960_auxpcm_rate_put),
Vicky Sehrawat45204132012-11-05 17:54:13 -0800695 SOC_ENUM_EXT("HDMI RX Rate", msm8960_enum[3],
696 msm8960_hdmi_rate_get,
697 msm8960_hdmi_rate_put),
Kuirong Wang054e1832012-05-11 15:43:30 -0700698};
699
Joonwoo Park0976d012011-12-22 11:48:18 -0800700static void *def_tabla_mbhc_cal(void)
701{
702 void *tabla_cal;
703 struct tabla_mbhc_btn_detect_cfg *btn_cfg;
704 u16 *btn_low, *btn_high;
Joonwoo Parkc0672392012-01-11 11:03:14 -0800705 u8 *n_ready, *n_cic, *gain;
Joonwoo Park0976d012011-12-22 11:48:18 -0800706
707 tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
708 TABLA_MBHC_DEF_RLOADS),
709 GFP_KERNEL);
710 if (!tabla_cal) {
711 pr_err("%s: out of memory\n", __func__);
712 return NULL;
713 }
714
715#define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
716 S(t_ldoh, 100);
717 S(t_bg_fast_settle, 100);
718 S(t_shutdown_plug_rem, 255);
719 S(mbhc_nsa, 4);
720 S(mbhc_navg, 4);
721#undef S
722#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
723 S(mic_current, TABLA_PID_MIC_5_UA);
724 S(hph_current, TABLA_PID_MIC_5_UA);
725 S(t_mic_pid, 100);
Joonwoo Parkf4267c22012-01-10 13:25:24 -0800726 S(t_ins_complete, 250);
Joonwoo Park0976d012011-12-22 11:48:18 -0800727 S(t_ins_retry, 200);
728#undef S
729#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
730 S(v_no_mic, 30);
Joonwoo Parkcf473b42012-03-29 19:48:16 -0700731 S(v_hs_max, 2400);
Joonwoo Park0976d012011-12-22 11:48:18 -0800732#undef S
733#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800734 S(c[0], 62);
735 S(c[1], 124);
736 S(nc, 1);
737 S(n_meas, 3);
Joonwoo Park0976d012011-12-22 11:48:18 -0800738 S(mbhc_nsc, 11);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800739 S(n_btn_meas, 1);
740 S(n_btn_con, 2);
Joonwoo Park0976d012011-12-22 11:48:18 -0800741 S(num_btn, TABLA_MBHC_DEF_BUTTONS);
742 S(v_btn_press_delta_sta, 100);
743 S(v_btn_press_delta_cic, 50);
744#undef S
745 btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
746 btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
747 btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800748 btn_low[0] = -50;
Simmi Pateriya51a09fc2013-03-26 23:29:03 +0530749 btn_high[0] = 21;
750 btn_low[1] = 22;
751 btn_high[1] = 67;
752 btn_low[2] = 68;
753 btn_high[2] = 111;
754 btn_low[3] = 112;
755 btn_high[3] = 153;
756 btn_low[4] = 154;
757 btn_high[4] = 191;
758 btn_low[5] = 192;
759 btn_high[5] = 233;
760 btn_low[6] = 234;
761 btn_high[6] = 272;
762 btn_low[7] = 273;
763 btn_high[7] = 400;
Joonwoo Parkc0672392012-01-11 11:03:14 -0800764 n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
Joonwoo Parkcf473b42012-03-29 19:48:16 -0700765 n_ready[0] = 80;
766 n_ready[1] = 68;
Joonwoo Park0976d012011-12-22 11:48:18 -0800767 n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800768 n_cic[0] = 60;
769 n_cic[1] = 47;
Joonwoo Park0976d012011-12-22 11:48:18 -0800770 gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
771 gain[0] = 11;
772 gain[1] = 9;
773
774 return tabla_cal;
775}
776
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800777static int msm8960_hw_params(struct snd_pcm_substream *substream,
778 struct snd_pcm_hw_params *params)
779{
780 struct snd_soc_pcm_runtime *rtd = substream->private_data;
781 struct snd_soc_dai *codec_dai = rtd->codec_dai;
782 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
783 int ret = 0;
784 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
785 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700786
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800787 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700788
789 pr_debug("%s: rx_0_ch=%d\n", __func__, msm8960_slim_0_rx_ch);
790
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800791 ret = snd_soc_dai_get_channel_map(codec_dai,
792 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
793 if (ret < 0) {
794 pr_err("%s: failed to get codec chan map\n", __func__);
795 goto end;
796 }
797
798 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
799 msm8960_slim_0_rx_ch, rx_ch);
800 if (ret < 0) {
801 pr_err("%s: failed to set cpu chan map\n", __func__);
802 goto end;
803 }
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800804 } else {
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700805
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700806 pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
807 codec_dai->name, codec_dai->id, msm8960_slim_0_tx_ch);
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700808
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800809 ret = snd_soc_dai_get_channel_map(codec_dai,
810 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
811 if (ret < 0) {
812 pr_err("%s: failed to get codec chan map\n", __func__);
813 goto end;
814 }
815 ret = snd_soc_dai_set_channel_map(cpu_dai,
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700816 msm8960_slim_0_tx_ch, tx_ch, 0 , 0);
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800817 if (ret < 0) {
818 pr_err("%s: failed to set cpu chan map\n", __func__);
819 goto end;
820 }
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700821 }
822end:
823 return ret;
824}
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800825
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700826static int msm8960_slimbus_2_hw_params(struct snd_pcm_substream *substream,
827 struct snd_pcm_hw_params *params)
828{
829 struct snd_soc_pcm_runtime *rtd = substream->private_data;
830 struct snd_soc_dai *codec_dai = rtd->codec_dai;
831 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
832 int ret = 0;
833 unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
834 unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
835 unsigned int num_tx_ch = 0;
836 unsigned int num_rx_ch = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800837
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700838 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
839
840 num_rx_ch = params_channels(params);
841
842 pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
843 codec_dai->name, codec_dai->id, num_rx_ch);
844
845 ret = snd_soc_dai_get_channel_map(codec_dai,
846 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
847 if (ret < 0) {
848 pr_err("%s: failed to get codec chan map\n", __func__);
849 goto end;
850 }
851
852 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
853 num_rx_ch, rx_ch);
854 if (ret < 0) {
855 pr_err("%s: failed to set cpu chan map\n", __func__);
856 goto end;
857 }
Kiran Kandi97fe19d2012-05-20 22:34:04 -0700858 } else {
859 num_tx_ch = params_channels(params);
860
861 pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
862 codec_dai->name, codec_dai->id, num_tx_ch);
863
864 ret = snd_soc_dai_get_channel_map(codec_dai,
865 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
866 if (ret < 0) {
867 pr_err("%s: failed to get codec chan map\n", __func__);
868 goto end;
869 }
870
871 ret = snd_soc_dai_set_channel_map(cpu_dai,
872 num_tx_ch, tx_ch, 0 , 0);
873 if (ret < 0) {
874 pr_err("%s: failed to set cpu chan map\n", __func__);
875 goto end;
876 }
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800877 }
878end:
879 return ret;
880}
881
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700882static int msm8960_audrx_init(struct snd_soc_pcm_runtime *rtd)
883{
884 int err;
885 struct snd_soc_codec *codec = rtd->codec;
886 struct snd_soc_dapm_context *dapm = &codec->dapm;
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800887 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700888 struct pm_gpio jack_gpio_cfg = {
889 .direction = PM_GPIO_DIR_IN,
890 .pull = PM_GPIO_PULL_UP_1P5,
891 .function = PM_GPIO_FUNC_NORMAL,
892 .vin_sel = 2,
893 .inv_int_pol = 0,
894 };
Kuirong Wang906ac472012-07-09 12:54:44 -0700895 struct snd_soc_dai *codec_dai = rtd->codec_dai;
896
897 /* Tabla SLIMBUS configuration
898 * RX1, RX2, RX3, RX4, RX5, RX6, RX7
899 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8
900 */
901 unsigned int rx_ch[TABLA_RX_MAX] = {138, 139, 140, 141, 142, 143, 144};
902 unsigned int tx_ch[TABLA_TX_MAX] = {128, 129, 130, 131, 132, 133, 134,
903 135, 136, 137};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800905 pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700906
Harmandeep Singh0dd82412011-11-11 09:46:17 -0800907 if (machine_is_msm8960_liquid()) {
908 top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
909 bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
910 }
911
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912 snd_soc_dapm_new_controls(dapm, msm8960_dapm_widgets,
913 ARRAY_SIZE(msm8960_dapm_widgets));
914
Bradley Rubin229c6a52011-07-12 16:18:48 -0700915 snd_soc_dapm_add_routes(dapm, common_audio_map,
916 ARRAY_SIZE(common_audio_map));
917
Peter Lohmannb8203ef2011-10-07 15:05:28 -0700918 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
919 snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
920 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
921 snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922
923 snd_soc_dapm_sync(dapm);
924
925 err = snd_soc_jack_new(codec, "Headset Jack",
Ravi Kumar Alamanda07b6bd62012-08-15 18:39:47 -0700926 (SND_JACK_HEADSET | SND_JACK_LINEOUT |
927 SND_JACK_OC_HPHL | SND_JACK_OC_HPHR |
928 SND_JACK_UNSUPPORTED),
929 &hs_jack);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930 if (err) {
931 pr_err("failed to create new jack\n");
932 return err;
933 }
Bradley Rubincb1e2732011-06-23 16:49:20 -0700934
935 err = snd_soc_jack_new(codec, "Button Jack",
Joonwoo Park6b9b03f2012-01-23 18:48:54 -0800936 TABLA_JACK_BUTTON_MASK, &button_jack);
Bradley Rubincb1e2732011-06-23 16:49:20 -0700937 if (err) {
938 pr_err("failed to create new jack\n");
939 return err;
940 }
941
Kuirong Wanga9c3acc2012-02-09 17:00:45 -0800942 codec_clk = clk_get(cpu_dai->dev, "osr_clk");
943
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700944 if (machine_is_msm8960_cdp())
945 mbhc_cfg.swap_gnd_mic = msm8960_swap_gnd_mic;
946
Simmi Pateriya71d63872012-11-08 01:06:30 +0530947 if (hs_micbias_always_on)
948 mbhc_cfg.micbias_always_on = true;
949
Joonwoo Park9115ade2012-04-18 13:14:10 -0700950 if (hs_detect_use_gpio) {
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700951 mbhc_cfg.gpio = PM8921_GPIO_PM_TO_SYS(JACK_DETECT_GPIO);
952 mbhc_cfg.gpio_irq = JACK_DETECT_INT;
Ravi Kumar Alamanda07b6bd62012-08-15 18:39:47 -0700953 if (hs_detect_extn_cable)
954 mbhc_cfg.detect_extn_cable = true;
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700955 }
956
957 if (mbhc_cfg.gpio) {
958 err = pm8xxx_gpio_config(mbhc_cfg.gpio, &jack_gpio_cfg);
959 if (err) {
Joonwoo Park2cc13f02012-05-09 12:44:25 -0700960 pr_err("%s: pm8xxx_gpio_config JACK_DETECT failed %d\n",
961 __func__, err);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700962 return err;
963 }
964 }
Joonwoo Park9115ade2012-04-18 13:14:10 -0700965
966 mbhc_cfg.read_fw_bin = hs_detect_use_firmware;
967
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -0700968 err = tabla_hs_detect(codec, &mbhc_cfg);
Kuirong Wang906ac472012-07-09 12:54:44 -0700969 snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
970 tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700971
Joonwoo Park03324832012-03-19 19:36:16 -0700972 return err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700973}
974
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700975static int msm8960_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
976 struct snd_pcm_hw_params *params)
977{
978 struct snd_interval *rate = hw_param_interval(params,
979 SNDRV_PCM_HW_PARAM_RATE);
980
981 struct snd_interval *channels = hw_param_interval(params,
982 SNDRV_PCM_HW_PARAM_CHANNELS);
983
984 pr_debug("%s()\n", __func__);
985 rate->min = rate->max = 48000;
986 channels->min = channels->max = msm8960_slim_0_rx_ch;
987
988 return 0;
989}
990
991static int msm8960_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
992 struct snd_pcm_hw_params *params)
993{
994 struct snd_interval *rate = hw_param_interval(params,
995 SNDRV_PCM_HW_PARAM_RATE);
996
997 struct snd_interval *channels = hw_param_interval(params,
998 SNDRV_PCM_HW_PARAM_CHANNELS);
999
1000 pr_debug("%s()\n", __func__);
1001 rate->min = rate->max = 48000;
1002 channels->min = channels->max = msm8960_slim_0_tx_ch;
1003
1004 return 0;
1005}
1006
1007static int msm8960_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1008 struct snd_pcm_hw_params *params)
1009{
1010 struct snd_interval *rate = hw_param_interval(params,
1011 SNDRV_PCM_HW_PARAM_RATE);
1012
1013 pr_debug("%s()\n", __func__);
1014 rate->min = rate->max = 48000;
1015
1016 return 0;
1017}
1018
Helen Zeng73f7fc62011-11-18 16:29:59 -08001019static int msm8960_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1020 struct snd_pcm_hw_params *params)
1021{
1022 struct snd_interval *rate = hw_param_interval(params,
1023 SNDRV_PCM_HW_PARAM_RATE);
1024
1025 struct snd_interval *channels = hw_param_interval(params,
1026 SNDRV_PCM_HW_PARAM_CHANNELS);
1027
Kiran Kandi5e809b02012-01-31 00:24:33 -08001028 pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
1029 channels->min, channels->max);
1030
Helen Zeng12123a12012-09-26 15:57:43 -07001031 if (channels->max < 2)
1032 channels->min = channels->max = 2;
Vicky Sehrawat45204132012-11-05 17:54:13 -08001033 if (!hdmi_rate_variable)
1034 rate->min = rate->max = 48000;
Helen Zeng73f7fc62011-11-18 16:29:59 -08001035
1036 return 0;
1037}
1038
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001039static int msm8960_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1040 struct snd_pcm_hw_params *params)
1041{
1042 struct snd_interval *rate = hw_param_interval(params,
1043 SNDRV_PCM_HW_PARAM_RATE);
1044
1045 struct snd_interval *channels = hw_param_interval(params,
1046 SNDRV_PCM_HW_PARAM_CHANNELS);
1047
1048 rate->min = rate->max = msm8960_btsco_rate;
1049 channels->min = channels->max = msm8960_btsco_ch;
1050
1051 return 0;
1052}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001053static int msm8960_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
1054 struct snd_pcm_hw_params *params)
1055{
1056 struct snd_interval *rate = hw_param_interval(params,
1057 SNDRV_PCM_HW_PARAM_RATE);
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001058
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001059 struct snd_interval *channels = hw_param_interval(params,
1060 SNDRV_PCM_HW_PARAM_CHANNELS);
1061
Kuirong Wang054e1832012-05-11 15:43:30 -07001062 rate->min = rate->max = msm8960_auxpcm_rate;
1063 /* PCM only supports mono output */
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001064 channels->min = channels->max = 1;
1065
1066 return 0;
1067}
Jayasena Sangaraboina66bd39d2012-06-29 18:10:23 -07001068static int msm8960_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
1069 struct snd_pcm_hw_params *params)
1070{
1071 struct snd_interval *rate = hw_param_interval(params,
1072 SNDRV_PCM_HW_PARAM_RATE);
1073
1074 pr_debug("%s()\n", __func__);
1075 rate->min = rate->max = 48000;
1076
1077 return 0;
1078}
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001079static int msm8960_aux_pcm_get_gpios(void)
1080{
1081 int ret = 0;
1082
1083 pr_debug("%s\n", __func__);
1084
1085 ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
1086 if (ret < 0) {
1087 pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
1088 __func__, GPIO_AUX_PCM_DOUT);
1089 goto fail_dout;
1090 }
1091
1092 ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
1093 if (ret < 0) {
1094 pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
1095 __func__, GPIO_AUX_PCM_DIN);
1096 goto fail_din;
1097 }
1098
1099 ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
1100 if (ret < 0) {
1101 pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
1102 __func__, GPIO_AUX_PCM_SYNC);
1103 goto fail_sync;
1104 }
1105 ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
1106 if (ret < 0) {
1107 pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
1108 __func__, GPIO_AUX_PCM_CLK);
1109 goto fail_clk;
1110 }
1111
1112 return 0;
1113
1114fail_clk:
1115 gpio_free(GPIO_AUX_PCM_SYNC);
1116fail_sync:
1117 gpio_free(GPIO_AUX_PCM_DIN);
1118fail_din:
1119 gpio_free(GPIO_AUX_PCM_DOUT);
1120fail_dout:
1121
1122 return ret;
1123}
1124
1125static int msm8960_aux_pcm_free_gpios(void)
1126{
1127 gpio_free(GPIO_AUX_PCM_DIN);
1128 gpio_free(GPIO_AUX_PCM_DOUT);
1129 gpio_free(GPIO_AUX_PCM_SYNC);
1130 gpio_free(GPIO_AUX_PCM_CLK);
1131
1132 return 0;
1133}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001134static int msm8960_startup(struct snd_pcm_substream *substream)
1135{
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001136 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1137
1138 pr_debug("%s(): dai_link_str_name = %s cpu_dai = %s codec_dai = %s\n",
1139 __func__, rtd->dai_link->stream_name,
1140 rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001141 return 0;
1142}
1143
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001144static int msm8960_auxpcm_startup(struct snd_pcm_substream *substream)
1145{
1146 int ret = 0;
1147
Kuirong Wangae395b02012-09-20 11:43:17 -07001148 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1149 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1150 if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
1151 ret = msm8960_aux_pcm_get_gpios();
1152
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001153 if (ret < 0) {
1154 pr_err("%s: Aux PCM GPIO request failed\n", __func__);
1155 return -EINVAL;
1156 }
1157 return 0;
1158}
1159
1160static void msm8960_auxpcm_shutdown(struct snd_pcm_substream *substream)
1161{
Kuirong Wangae395b02012-09-20 11:43:17 -07001162 pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
1163 __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
1164 if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
1165 msm8960_aux_pcm_free_gpios();
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001166}
1167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168static void msm8960_shutdown(struct snd_pcm_substream *substream)
1169{
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001170 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1171
1172 pr_debug("%s(): dai_link str_name = %s cpu_dai = %s codec_dai = %s\n",
1173 __func__, rtd->dai_link->stream_name,
1174 rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001175}
1176
1177static struct snd_soc_ops msm8960_be_ops = {
1178 .startup = msm8960_startup,
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001179 .hw_params = msm8960_hw_params,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180 .shutdown = msm8960_shutdown,
1181};
1182
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001183static struct snd_soc_ops msm8960_auxpcm_be_ops = {
1184 .startup = msm8960_auxpcm_startup,
1185 .shutdown = msm8960_auxpcm_shutdown,
1186};
1187
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001188static struct snd_soc_ops msm8960_slimbus_2_be_ops = {
1189 .startup = msm8960_startup,
1190 .hw_params = msm8960_slimbus_2_hw_params,
1191 .shutdown = msm8960_shutdown,
1192};
1193
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001194/* Digital audio interface glue - connects codec <---> CPU */
Kuirong Wangb25838e2012-01-16 23:37:23 -08001195static struct snd_soc_dai_link msm8960_dai_common[] = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196 /* FrontEnd DAI Links */
1197 {
1198 .name = "MSM8960 Media1",
1199 .stream_name = "MultiMedia1",
1200 .cpu_dai_name = "MultiMedia1",
1201 .platform_name = "msm-pcm-dsp",
1202 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001203 .codec_dai_name = "snd-soc-dummy-dai",
1204 .codec_name = "snd-soc-dummy",
1205 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1206 .ignore_suspend = 1,
1207 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001208 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
1209 },
1210 {
1211 .name = "MSM8960 Media2",
1212 .stream_name = "MultiMedia2",
1213 .cpu_dai_name = "MultiMedia2",
Kiran Kandi5e809b02012-01-31 00:24:33 -08001214 .platform_name = "msm-multi-ch-pcm-dsp",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001215 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001216 .codec_dai_name = "snd-soc-dummy-dai",
1217 .codec_name = "snd-soc-dummy",
1218 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1219 .ignore_suspend = 1,
1220 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001221 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
1222 },
1223 {
1224 .name = "Circuit-Switch Voice",
1225 .stream_name = "CS-Voice",
1226 .cpu_dai_name = "CS-VOICE",
1227 .platform_name = "msm-pcm-voice",
1228 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001229 .codec_dai_name = "snd-soc-dummy-dai",
1230 .codec_name = "snd-soc-dummy",
1231 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001232 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001233 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001234 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1235 .be_id = MSM_FRONTEND_DAI_CS_VOICE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001236 },
1237 {
1238 .name = "MSM VoIP",
1239 .stream_name = "VoIP",
1240 .cpu_dai_name = "VoIP",
1241 .platform_name = "msm-voip-dsp",
1242 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001243 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1244 .codec_dai_name = "snd-soc-dummy-dai",
1245 .codec_name = "snd-soc-dummy",
1246 .ignore_suspend = 1,
1247 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001248 .be_id = MSM_FRONTEND_DAI_VOIP,
1249 },
1250 {
1251 .name = "MSM8960 LPA",
1252 .stream_name = "LPA",
1253 .cpu_dai_name = "MultiMedia3",
1254 .platform_name = "msm-pcm-lpa",
1255 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001256 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1257 .codec_dai_name = "snd-soc-dummy-dai",
1258 .codec_name = "snd-soc-dummy",
1259 .ignore_suspend = 1,
1260 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001261 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
1262 },
1263 /* Hostless PMC purpose */
1264 {
1265 .name = "SLIMBUS_0 Hostless",
1266 .stream_name = "SLIMBUS_0 Hostless",
1267 .cpu_dai_name = "SLIMBUS0_HOSTLESS",
1268 .platform_name = "msm-pcm-hostless",
1269 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001270 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001271 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001272 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001273 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1274 .codec_dai_name = "snd-soc-dummy-dai",
1275 .codec_name = "snd-soc-dummy",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001276 },
1277 {
1278 .name = "INT_FM Hostless",
1279 .stream_name = "INT_FM Hostless",
1280 .cpu_dai_name = "INT_FM_HOSTLESS",
1281 .platform_name = "msm-pcm-hostless",
1282 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001283 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001284 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb9367922011-09-21 23:09:43 -07001285 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001286 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1287 .codec_dai_name = "snd-soc-dummy-dai",
1288 .codec_name = "snd-soc-dummy",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001289 },
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301290 {
1291 .name = "MSM AFE-PCM RX",
1292 .stream_name = "AFE-PROXY RX",
1293 .cpu_dai_name = "msm-dai-q6.241",
1294 .codec_name = "msm-stub-codec.1",
1295 .codec_dai_name = "msm-stub-rx",
1296 .platform_name = "msm-pcm-afe",
Alex Wongb9367922011-09-21 23:09:43 -07001297 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001298 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301299 },
1300 {
1301 .name = "MSM AFE-PCM TX",
1302 .stream_name = "AFE-PROXY TX",
1303 .cpu_dai_name = "msm-dai-q6.240",
1304 .codec_name = "msm-stub-codec.1",
1305 .codec_dai_name = "msm-stub-tx",
1306 .platform_name = "msm-pcm-afe",
Alex Wongb9367922011-09-21 23:09:43 -07001307 .ignore_suspend = 1,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301308 },
Asish Bhattacharya09f9e0a2011-11-11 13:22:47 +05301309 {
1310 .name = "MSM8960 Compr",
1311 .stream_name = "COMPR",
1312 .cpu_dai_name = "MultiMedia4",
Xiaojun Sang43f3d3b2017-04-27 14:44:25 +08001313 .platform_name = "msm-compress-dsp",
Asish Bhattacharya09f9e0a2011-11-11 13:22:47 +05301314 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001315 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
1316 .codec_dai_name = "snd-soc-dummy-dai",
1317 .codec_name = "snd-soc-dummy",
1318 .ignore_suspend = 1,
1319 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Asish Bhattacharya09f9e0a2011-11-11 13:22:47 +05301320 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
1321 },
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001322 {
1323 .name = "AUXPCM Hostless",
1324 .stream_name = "AUXPCM Hostless",
1325 .cpu_dai_name = "AUXPCM_HOSTLESS",
1326 .platform_name = "msm-pcm-hostless",
1327 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001328 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001329 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1330 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001331 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1332 .codec_dai_name = "snd-soc-dummy-dai",
1333 .codec_name = "snd-soc-dummy",
Patrick Lai9b56e1d2012-01-22 22:14:15 -08001334 },
Alex Wongb3d06a02012-01-12 10:00:41 -08001335 /* HDMI Hostless */
1336 {
1337 .name = "HDMI_RX_HOSTLESS",
1338 .stream_name = "HDMI_RX_HOSTLESS",
1339 .cpu_dai_name = "HDMI_HOSTLESS",
1340 .platform_name = "msm-pcm-hostless",
1341 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001342 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Alex Wongb3d06a02012-01-12 10:00:41 -08001343 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Alex Wongb3d06a02012-01-12 10:00:41 -08001344 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001345 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1346 .codec_dai_name = "snd-soc-dummy-dai",
1347 .codec_name = "snd-soc-dummy",
Alex Wongb3d06a02012-01-12 10:00:41 -08001348 },
Venkat Sudhir1c79c3b2012-04-09 23:42:28 -07001349 {
1350 .name = "VoLTE",
1351 .stream_name = "VoLTE",
1352 .cpu_dai_name = "VoLTE",
1353 .platform_name = "msm-pcm-voice",
1354 .dynamic = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001355 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
Venkat Sudhir1c79c3b2012-04-09 23:42:28 -07001356 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1357 .ignore_suspend = 1,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001358 .ignore_pmdown_time = 1, /* this dainlink has playback support */
1359 .codec_dai_name = "snd-soc-dummy-dai",
1360 .codec_name = "snd-soc-dummy",
1361 .be_id = MSM_FRONTEND_DAI_VOLTE,
Venkat Sudhir1c79c3b2012-04-09 23:42:28 -07001362 },
Satish Babu Patakokila75645ce2012-06-20 15:01:02 +05301363 {
Helen Zengc5bd1bb2013-03-06 10:37:52 -08001364 .name = "Voice2",
1365 .stream_name = "Voice2",
1366 .cpu_dai_name = "Voice2",
Satish Babu Patakokila75645ce2012-06-20 15:01:02 +05301367 .platform_name = "msm-pcm-voice",
1368 .dynamic = 1,
1369 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1370 SND_SOC_DPCM_TRIGGER_POST},
1371 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1372 .ignore_suspend = 1,
1373 .ignore_pmdown_time = 1,/* this dainlink has playback support */
1374 .codec_dai_name = "snd-soc-dummy-dai",
1375 .codec_name = "snd-soc-dummy",
Helen Zengc5bd1bb2013-03-06 10:37:52 -08001376 .be_id = MSM_FRONTEND_DAI_VOICE2,
Satish Babu Patakokila75645ce2012-06-20 15:01:02 +05301377 },
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -07001378 {
1379 .name = "MSM8960 LowLatency",
1380 .stream_name = "MultiMedia5",
1381 .cpu_dai_name = "MultiMedia5",
1382 .platform_name = "msm-lowlatency-pcm-dsp",
1383 .dynamic = 1,
1384 .codec_dai_name = "snd-soc-dummy-dai",
1385 .codec_name = "snd-soc-dummy",
1386 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1387 SND_SOC_DPCM_TRIGGER_POST},
1388 .ignore_suspend = 1,
1389 /* this dainlink has playback support */
1390 .ignore_pmdown_time = 1,
1391 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
1392 },
Krishnankutty Kolathappilly64658722012-08-08 14:44:48 -07001393 {
1394 .name = "MSM8960 Media6",
1395 .stream_name = "MultiMedia6",
1396 .cpu_dai_name = "MultiMedia6",
1397 .platform_name = "msm-multi-ch-pcm-dsp",
1398 .dynamic = 1,
1399 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1400 SND_SOC_DPCM_TRIGGER_POST},
1401 .codec_dai_name = "snd-soc-dummy-dai",
1402 .codec_name = "snd-soc-dummy",
1403 .ignore_suspend = 1,
1404 .ignore_pmdown_time = 1, /* this dailink has playback support */
1405 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
1406 },
1407 {
1408 .name = "MSM8960 Compr2",
1409 .stream_name = "COMPR2",
1410 .cpu_dai_name = "MultiMedia7",
Xiaojun Sang43f3d3b2017-04-27 14:44:25 +08001411 .platform_name = "msm-compress-dsp",
Krishnankutty Kolathappilly64658722012-08-08 14:44:48 -07001412 .dynamic = 1,
1413 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1414 SND_SOC_DPCM_TRIGGER_POST},
1415 .codec_dai_name = "snd-soc-dummy-dai",
1416 .codec_name = "snd-soc-dummy",
1417 .ignore_suspend = 1,
1418 .ignore_pmdown_time = 1, /* this dailink has playback support */
1419 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
1420 },
1421 {
1422 .name = "MSM8960 Compr3",
1423 .stream_name = "COMPR3",
1424 .cpu_dai_name = "MultiMedia8",
Xiaojun Sang43f3d3b2017-04-27 14:44:25 +08001425 .platform_name = "msm-compress-dsp",
Krishnankutty Kolathappilly64658722012-08-08 14:44:48 -07001426 .dynamic = 1,
1427 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
1428 SND_SOC_DPCM_TRIGGER_POST},
1429 .codec_dai_name = "snd-soc-dummy-dai",
1430 .codec_name = "snd-soc-dummy",
1431 .ignore_suspend = 1,
1432 .ignore_pmdown_time = 1, /* this dailink has playback support */
1433 .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
1434 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001435 /* Backend BT/FM DAI Links */
1436 {
1437 .name = LPASS_BE_INT_BT_SCO_RX,
1438 .stream_name = "Internal BT-SCO Playback",
1439 .cpu_dai_name = "msm-dai-q6.12288",
1440 .platform_name = "msm-pcm-routing",
1441 .codec_name = "msm-stub-codec.1",
1442 .codec_dai_name = "msm-stub-rx",
1443 .no_pcm = 1,
1444 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001445 .be_hw_params_fixup = msm8960_btsco_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001446 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001447 },
1448 {
1449 .name = LPASS_BE_INT_BT_SCO_TX,
1450 .stream_name = "Internal BT-SCO Capture",
1451 .cpu_dai_name = "msm-dai-q6.12289",
1452 .platform_name = "msm-pcm-routing",
1453 .codec_name = "msm-stub-codec.1",
1454 .codec_dai_name = "msm-stub-tx",
1455 .no_pcm = 1,
1456 .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
Jayasena Sangaraboina47c08242011-08-10 11:30:57 -07001457 .be_hw_params_fixup = msm8960_btsco_be_hw_params_fixup,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458 },
1459 {
1460 .name = LPASS_BE_INT_FM_RX,
1461 .stream_name = "Internal FM Playback",
1462 .cpu_dai_name = "msm-dai-q6.12292",
1463 .platform_name = "msm-pcm-routing",
1464 .codec_name = "msm-stub-codec.1",
1465 .codec_dai_name = "msm-stub-rx",
1466 .no_pcm = 1,
1467 .be_id = MSM_BACKEND_DAI_INT_FM_RX,
1468 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001469 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001470 },
1471 {
1472 .name = LPASS_BE_INT_FM_TX,
1473 .stream_name = "Internal FM Capture",
1474 .cpu_dai_name = "msm-dai-q6.12293",
1475 .platform_name = "msm-pcm-routing",
1476 .codec_name = "msm-stub-codec.1",
1477 .codec_dai_name = "msm-stub-tx",
1478 .no_pcm = 1,
1479 .be_id = MSM_BACKEND_DAI_INT_FM_TX,
1480 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1481 },
1482 /* HDMI BACK END DAI Link */
1483 {
1484 .name = LPASS_BE_HDMI,
1485 .stream_name = "HDMI Playback",
Kiran Kandi5e809b02012-01-31 00:24:33 -08001486 .cpu_dai_name = "msm-dai-q6-hdmi.8",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001487 .platform_name = "msm-pcm-routing",
1488 .codec_name = "msm-stub-codec.1",
1489 .codec_dai_name = "msm-stub-rx",
1490 .no_pcm = 1,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001491 .be_id = MSM_BACKEND_DAI_HDMI_RX,
Helen Zeng73f7fc62011-11-18 16:29:59 -08001492 .be_hw_params_fixup = msm8960_hdmi_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001493 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001494 },
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301495 /* Backend AFE DAI Links */
1496 {
1497 .name = LPASS_BE_AFE_PCM_RX,
1498 .stream_name = "AFE Playback",
1499 .cpu_dai_name = "msm-dai-q6.224",
1500 .platform_name = "msm-pcm-routing",
1501 .codec_name = "msm-stub-codec.1",
1502 .codec_dai_name = "msm-stub-rx",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301503 .no_pcm = 1,
1504 .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
Jayasena Sangaraboina66bd39d2012-06-29 18:10:23 -07001505 .be_hw_params_fixup = msm8960_proxy_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001506 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301507 },
1508 {
1509 .name = LPASS_BE_AFE_PCM_TX,
1510 .stream_name = "AFE Capture",
1511 .cpu_dai_name = "msm-dai-q6.225",
1512 .platform_name = "msm-pcm-routing",
1513 .codec_name = "msm-stub-codec.1",
1514 .codec_dai_name = "msm-stub-tx",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301515 .no_pcm = 1,
1516 .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
Jayasena Sangaraboina66bd39d2012-06-29 18:10:23 -07001517 .be_hw_params_fixup = msm8960_proxy_be_hw_params_fixup,
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301518 },
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001519 /* AUX PCM Backend DAI Links */
1520 {
1521 .name = LPASS_BE_AUXPCM_RX,
1522 .stream_name = "AUX PCM Playback",
1523 .cpu_dai_name = "msm-dai-q6.2",
1524 .platform_name = "msm-pcm-routing",
1525 .codec_name = "msm-stub-codec.1",
1526 .codec_dai_name = "msm-stub-rx",
1527 .no_pcm = 1,
1528 .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
1529 .be_hw_params_fixup = msm8960_auxpcm_be_params_fixup,
1530 .ops = &msm8960_auxpcm_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001531 .ignore_pmdown_time = 1,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001532 },
1533 {
1534 .name = LPASS_BE_AUXPCM_TX,
1535 .stream_name = "AUX PCM Capture",
1536 .cpu_dai_name = "msm-dai-q6.3",
1537 .platform_name = "msm-pcm-routing",
1538 .codec_name = "msm-stub-codec.1",
1539 .codec_dai_name = "msm-stub-tx",
1540 .no_pcm = 1,
1541 .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
1542 .be_hw_params_fixup = msm8960_auxpcm_be_params_fixup,
Kuirong Wangae395b02012-09-20 11:43:17 -07001543 .ops = &msm8960_auxpcm_be_ops,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001544 },
Helen Zeng0705a5f2011-10-14 15:29:52 -07001545 /* Incall Music BACK END DAI Link */
1546 {
1547 .name = LPASS_BE_VOICE_PLAYBACK_TX,
1548 .stream_name = "Voice Farend Playback",
1549 .cpu_dai_name = "msm-dai-q6.32773",
1550 .platform_name = "msm-pcm-routing",
1551 .codec_name = "msm-stub-codec.1",
1552 .codec_dai_name = "msm-stub-rx",
1553 .no_pcm = 1,
Helen Zeng0705a5f2011-10-14 15:29:52 -07001554 .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
1555 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1556 },
Helen Zenge3d716a2011-10-14 16:32:16 -07001557 /* Incall Record Uplink BACK END DAI Link */
1558 {
1559 .name = LPASS_BE_INCALL_RECORD_TX,
1560 .stream_name = "Voice Uplink Capture",
1561 .cpu_dai_name = "msm-dai-q6.32772",
1562 .platform_name = "msm-pcm-routing",
1563 .codec_name = "msm-stub-codec.1",
1564 .codec_dai_name = "msm-stub-tx",
1565 .no_pcm = 1,
Helen Zenge3d716a2011-10-14 16:32:16 -07001566 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
1567 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
1568 },
1569 /* Incall Record Downlink BACK END DAI Link */
1570 {
1571 .name = LPASS_BE_INCALL_RECORD_RX,
1572 .stream_name = "Voice Downlink Capture",
1573 .cpu_dai_name = "msm-dai-q6.32771",
1574 .platform_name = "msm-pcm-routing",
1575 .codec_name = "msm-stub-codec.1",
1576 .codec_dai_name = "msm-stub-tx",
1577 .no_pcm = 1,
Helen Zenge3d716a2011-10-14 16:32:16 -07001578 .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
1579 .be_hw_params_fixup = msm8960_be_hw_params_fixup,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001580 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Helen Zenge3d716a2011-10-14 16:32:16 -07001581 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001582};
1583
Kuirong Wangb25838e2012-01-16 23:37:23 -08001584static struct snd_soc_dai_link msm8960_dai_delta_tabla1x[] = {
1585 /* Backend DAI Links */
1586 {
1587 .name = LPASS_BE_SLIMBUS_0_RX,
1588 .stream_name = "Slimbus Playback",
1589 .cpu_dai_name = "msm-dai-q6.16384",
1590 .platform_name = "msm-pcm-routing",
1591 .codec_name = "tabla1x_codec",
1592 .codec_dai_name = "tabla_rx1",
1593 .no_pcm = 1,
1594 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1595 .init = &msm8960_audrx_init,
1596 .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
1597 .ops = &msm8960_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001598 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Kuirong Wangb25838e2012-01-16 23:37:23 -08001599 },
1600 {
1601 .name = LPASS_BE_SLIMBUS_0_TX,
1602 .stream_name = "Slimbus Capture",
1603 .cpu_dai_name = "msm-dai-q6.16385",
1604 .platform_name = "msm-pcm-routing",
1605 .codec_name = "tabla1x_codec",
1606 .codec_dai_name = "tabla_tx1",
1607 .no_pcm = 1,
1608 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1609 .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
1610 .ops = &msm8960_be_ops,
1611 },
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001612 /* Ultrasound TX Back End DAI Link */
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001613 {
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001614 .name = "SLIMBUS_2 Hostless Capture",
1615 .stream_name = "SLIMBUS_2 Hostless Capture",
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001616 .cpu_dai_name = "msm-dai-q6.16389",
1617 .platform_name = "msm-pcm-hostless",
1618 .codec_name = "tabla1x_codec",
1619 .codec_dai_name = "tabla_tx2",
Swaminathan Sathappan630c5a42012-05-10 17:33:01 -07001620 .ignore_suspend = 1,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001621 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001622 .ops = &msm8960_slimbus_2_be_ops,
1623 },
1624 /* Ultrasound RX Back End DAI Link */
1625 {
1626 .name = "SLIMBUS_2 Hostless Playback",
1627 .stream_name = "SLIMBUS_2 Hostless Playback",
1628 .cpu_dai_name = "msm-dai-q6.16388",
1629 .platform_name = "msm-pcm-hostless",
1630 .codec_name = "tabla1x_codec",
1631 .codec_dai_name = "tabla_rx3",
1632 .ignore_suspend = 1,
1633 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1634 .ops = &msm8960_slimbus_2_be_ops,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001635 },
Kuirong Wangb25838e2012-01-16 23:37:23 -08001636};
1637
1638
1639static struct snd_soc_dai_link msm8960_dai_delta_tabla2x[] = {
1640 /* Backend DAI Links */
1641 {
1642 .name = LPASS_BE_SLIMBUS_0_RX,
1643 .stream_name = "Slimbus Playback",
1644 .cpu_dai_name = "msm-dai-q6.16384",
1645 .platform_name = "msm-pcm-routing",
1646 .codec_name = "tabla_codec",
1647 .codec_dai_name = "tabla_rx1",
1648 .no_pcm = 1,
1649 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
1650 .init = &msm8960_audrx_init,
1651 .be_hw_params_fixup = msm8960_slim_0_rx_be_hw_params_fixup,
1652 .ops = &msm8960_be_ops,
Steve Mucklef132c6c2012-06-06 18:30:57 -07001653 .ignore_pmdown_time = 1, /* this dainlink has playback support */
Kuirong Wangb25838e2012-01-16 23:37:23 -08001654 },
1655 {
1656 .name = LPASS_BE_SLIMBUS_0_TX,
1657 .stream_name = "Slimbus Capture",
1658 .cpu_dai_name = "msm-dai-q6.16385",
1659 .platform_name = "msm-pcm-routing",
1660 .codec_name = "tabla_codec",
1661 .codec_dai_name = "tabla_tx1",
1662 .no_pcm = 1,
1663 .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
1664 .be_hw_params_fixup = msm8960_slim_0_tx_be_hw_params_fixup,
1665 .ops = &msm8960_be_ops,
1666 },
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001667 /* Ultrasound TX Back End DAI Link */
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001668 {
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001669 .name = "SLIMBUS_2 Hostless Capture",
1670 .stream_name = "SLIMBUS_2 Hostless Capture",
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001671 .cpu_dai_name = "msm-dai-q6.16389",
1672 .platform_name = "msm-pcm-hostless",
1673 .codec_name = "tabla_codec",
1674 .codec_dai_name = "tabla_tx2",
Swaminathan Sathappan630c5a42012-05-10 17:33:01 -07001675 .ignore_suspend = 1,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001676 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
Kiran Kandi97fe19d2012-05-20 22:34:04 -07001677 .ops = &msm8960_slimbus_2_be_ops,
1678 },
1679 /* Ultrasound RX Back End DAI Link */
1680 {
1681 .name = "SLIMBUS_2 Hostless Playback",
1682 .stream_name = "SLIMBUS_2 Hostless Playback",
1683 .cpu_dai_name = "msm-dai-q6.16388",
1684 .platform_name = "msm-pcm-hostless",
1685 .codec_name = "tabla_codec",
1686 .codec_dai_name = "tabla_rx3",
1687 .ignore_suspend = 1,
1688 .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
1689 .ops = &msm8960_slimbus_2_be_ops,
Kiran Kandi1e6371d2012-03-29 11:48:57 -07001690 },
Kuirong Wangb25838e2012-01-16 23:37:23 -08001691};
1692
1693static struct snd_soc_dai_link msm8960_tabla1x_dai[
1694 ARRAY_SIZE(msm8960_dai_common) +
1695 ARRAY_SIZE(msm8960_dai_delta_tabla1x)];
1696
1697
1698static struct snd_soc_dai_link msm8960_dai[
1699 ARRAY_SIZE(msm8960_dai_common) +
1700 ARRAY_SIZE(msm8960_dai_delta_tabla2x)];
1701
1702static struct snd_soc_card snd_soc_tabla1x_card_msm8960 = {
1703 .name = "msm8960-tabla1x-snd-card",
1704 .dai_link = msm8960_tabla1x_dai,
1705 .num_links = ARRAY_SIZE(msm8960_tabla1x_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001706 .controls = tabla_msm8960_controls,
1707 .num_controls = ARRAY_SIZE(tabla_msm8960_controls),
Kuirong Wangb25838e2012-01-16 23:37:23 -08001708};
1709
1710static struct snd_soc_card snd_soc_card_msm8960 = {
1711 .name = "msm8960-snd-card",
1712 .dai_link = msm8960_dai,
1713 .num_links = ARRAY_SIZE(msm8960_dai),
Steve Mucklef132c6c2012-06-06 18:30:57 -07001714 .controls = tabla_msm8960_controls,
1715 .num_controls = ARRAY_SIZE(tabla_msm8960_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001716};
1717
1718static struct platform_device *msm8960_snd_device;
Kuirong Wangb25838e2012-01-16 23:37:23 -08001719static struct platform_device *msm8960_snd_tabla1x_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001720
1721static int msm8960_configure_headset_mic_gpios(void)
1722{
1723 int ret;
1724 struct pm_gpio param = {
1725 .direction = PM_GPIO_DIR_OUT,
1726 .output_buffer = PM_GPIO_OUT_BUF_CMOS,
1727 .output_value = 1,
1728 .pull = PM_GPIO_PULL_NO,
1729 .vin_sel = PM_GPIO_VIN_S4,
1730 .out_strength = PM_GPIO_STRENGTH_MED,
1731 .function = PM_GPIO_FUNC_NORMAL,
1732 };
1733
1734 ret = gpio_request(PM8921_GPIO_PM_TO_SYS(23), "AV_SWITCH");
1735 if (ret) {
1736 pr_err("%s: Failed to request gpio %d\n", __func__,
1737 PM8921_GPIO_PM_TO_SYS(23));
1738 return ret;
1739 }
1740
1741 ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(23), &param);
1742 if (ret)
1743 pr_err("%s: Failed to configure gpio %d\n", __func__,
1744 PM8921_GPIO_PM_TO_SYS(23));
1745 else
1746 gpio_direction_output(PM8921_GPIO_PM_TO_SYS(23), 0);
1747
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001748 ret = gpio_request(us_euro_sel_gpio, "US_EURO_SWITCH");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749 if (ret) {
1750 pr_err("%s: Failed to request gpio %d\n", __func__,
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001751 us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001752 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
1753 return ret;
1754 }
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001755 ret = pm8xxx_gpio_config(us_euro_sel_gpio, &param);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001756 if (ret)
1757 pr_err("%s: Failed to configure gpio %d\n", __func__,
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001758 us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001759 else
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001760 gpio_direction_output(us_euro_sel_gpio, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001761
1762 return 0;
1763}
1764static void msm8960_free_headset_mic_gpios(void)
1765{
1766 if (msm8960_headset_gpios_configured) {
1767 gpio_free(PM8921_GPIO_PM_TO_SYS(23));
Joonwoo Park2cc13f02012-05-09 12:44:25 -07001768 gpio_free(us_euro_sel_gpio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001769 }
1770}
1771
1772static int __init msm8960_audio_init(void)
1773{
1774 int ret;
1775
Stepan Moskovchenko5b9e7762012-09-21 20:32:17 -07001776 if (!soc_class_is_msm8960()) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07001777 pr_debug("%s: Not the right machine type\n", __func__);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001778 return -ENODEV ;
1779 }
Joonwoo Park0976d012011-12-22 11:48:18 -08001780
Simmi Pateriya95746512013-01-16 00:17:02 +05301781 mutex_init(&cdc_mclk_mutex);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001782 mbhc_cfg.calibration = def_tabla_mbhc_cal();
1783 if (!mbhc_cfg.calibration) {
Joonwoo Park0976d012011-12-22 11:48:18 -08001784 pr_err("Calibration data allocation failed\n");
1785 return -ENOMEM;
1786 }
1787
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001788 msm8960_snd_device = platform_device_alloc("soc-audio", 0);
1789 if (!msm8960_snd_device) {
1790 pr_err("Platform device allocation failed\n");
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001791 kfree(mbhc_cfg.calibration);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001792 return -ENOMEM;
1793 }
1794
Kuirong Wangb25838e2012-01-16 23:37:23 -08001795 memcpy(msm8960_dai, msm8960_dai_common, sizeof(msm8960_dai_common));
1796 memcpy(msm8960_dai + ARRAY_SIZE(msm8960_dai_common),
1797 msm8960_dai_delta_tabla2x, sizeof(msm8960_dai_delta_tabla2x));
1798
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001799 platform_set_drvdata(msm8960_snd_device, &snd_soc_card_msm8960);
1800 ret = platform_device_add(msm8960_snd_device);
1801 if (ret) {
1802 platform_device_put(msm8960_snd_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001803 kfree(mbhc_cfg.calibration);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001804 return ret;
1805 }
1806
Kuirong Wangb25838e2012-01-16 23:37:23 -08001807 msm8960_snd_tabla1x_device = platform_device_alloc("soc-audio", 1);
1808 if (!msm8960_snd_tabla1x_device) {
1809 pr_err("Platform device allocation failed\n");
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001810 kfree(mbhc_cfg.calibration);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001811 return -ENOMEM;
1812 }
1813
1814 memcpy(msm8960_tabla1x_dai, msm8960_dai_common,
1815 sizeof(msm8960_dai_common));
1816 memcpy(msm8960_tabla1x_dai + ARRAY_SIZE(msm8960_dai_common),
1817 msm8960_dai_delta_tabla1x, sizeof(msm8960_dai_delta_tabla1x));
1818
1819 platform_set_drvdata(msm8960_snd_tabla1x_device,
1820 &snd_soc_tabla1x_card_msm8960);
1821 ret = platform_device_add(msm8960_snd_tabla1x_device);
1822 if (ret) {
1823 platform_device_put(msm8960_snd_tabla1x_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001824 kfree(mbhc_cfg.calibration);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001825 return ret;
1826 }
1827
Jayasena Sangaraboina21c9f482012-08-19 09:37:29 -07001828 if (cpu_is_msm8960()) {
1829 if (msm8960_configure_headset_mic_gpios()) {
1830 pr_err("%s Fail to configure headset mic gpios\n",
1831 __func__);
1832 msm8960_headset_gpios_configured = 0;
1833 } else
1834 msm8960_headset_gpios_configured = 1;
1835 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001836 msm8960_headset_gpios_configured = 0;
Jayasena Sangaraboina21c9f482012-08-19 09:37:29 -07001837 pr_debug("%s headset GPIO 23 and 35 not configured msm960ab",
1838 __func__);
1839 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001840
Kuirong Wangae395b02012-09-20 11:43:17 -07001841 atomic_set(&auxpcm_rsc_ref, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001842 return ret;
1843
1844}
1845module_init(msm8960_audio_init);
1846
1847static void __exit msm8960_audio_exit(void)
1848{
Stepan Moskovchenko5b9e7762012-09-21 20:32:17 -07001849 if (!soc_class_is_msm8960()) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07001850 pr_debug("%s: Not the right machine type\n", __func__);
Bharath Ramachandramurthyb8e797f2011-11-30 12:08:42 -08001851 return ;
1852 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001853 msm8960_free_headset_mic_gpios();
1854 platform_device_unregister(msm8960_snd_device);
Kuirong Wangb25838e2012-01-16 23:37:23 -08001855 platform_device_unregister(msm8960_snd_tabla1x_device);
Joonwoo Parkd7cf2e92012-03-19 19:38:23 -07001856 kfree(mbhc_cfg.calibration);
Joonwoo Park28f49c82012-03-16 12:29:21 -07001857 mutex_destroy(&cdc_mclk_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001858}
1859module_exit(msm8960_audio_exit);
1860
1861MODULE_DESCRIPTION("ALSA SoC MSM8960");
1862MODULE_LICENSE("GPL v2");