blob: 30da5c6b24a937b07cb80ca8a698fb3810ae74a0 [file] [log] [blame]
Kiran Kandi3426e512011-09-13 22:50:10 -07001/* Copyright (c) 2011-2012, Code Aurora Forum. 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#include <linux/module.h>
13#include <linux/init.h>
Bradley Rubin229c6a52011-07-12 16:18:48 -070014#include <linux/firmware.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/slab.h>
16#include <linux/platform_device.h>
Santosh Mardie15e2302011-11-15 10:39:23 +053017#include <linux/device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070018#include <linux/printk.h>
19#include <linux/ratelimit.h>
Bradley Rubincb3950a2011-08-18 13:07:26 -070020#include <linux/debugfs.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <linux/mfd/wcd9310/core.h>
22#include <linux/mfd/wcd9310/registers.h>
Patrick Lai3043fba2011-08-01 14:15:57 -070023#include <linux/mfd/wcd9310/pdata.h>
Santosh Mardie15e2302011-11-15 10:39:23 +053024#include <sound/pcm.h>
25#include <sound/pcm_params.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#include <sound/jack.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/tlv.h>
30#include <linux/bitops.h>
31#include <linux/delay.h>
32#include "wcd9310.h"
33
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -070034#define WCD9310_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
35 SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_48000)
36
37#define NUM_DECIMATORS 10
38#define NUM_INTERPOLATORS 7
39#define BITS_PER_REG 8
40#define TABLA_RX_DAI_ID 1
41#define TABLA_TX_DAI_ID 2
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -080042#define TABLA_CFILT_FAST_MODE 0x00
43#define TABLA_CFILT_SLOW_MODE 0x40
Patrick Lai64b43262011-12-06 17:29:15 -080044#define MBHC_FW_READ_ATTEMPTS 15
45#define MBHC_FW_READ_TIMEOUT 2000000
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -070046
Patrick Lai49efeac2011-11-03 11:01:12 -070047#define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
48
Santosh Mardie15e2302011-11-15 10:39:23 +053049#define TABLA_I2S_MASTER_MODE_MASK 0x08
50
Patrick Laic7cae882011-11-18 11:52:49 -080051#define TABLA_OCP_ATTEMPT 1
52
Joonwoo Park0976d012011-12-22 11:48:18 -080053#define TABLA_MCLK_RATE_12288KHZ 12288000
54#define TABLA_MCLK_RATE_9600KHZ 9600000
55
Joonwoo Parkf4267c22012-01-10 13:25:24 -080056#define TABLA_FAKE_INS_THRESHOLD_MS 2500
57
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070058static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
59static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
60static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
61
62enum tabla_bandgap_type {
63 TABLA_BANDGAP_OFF = 0,
64 TABLA_BANDGAP_AUDIO_MODE,
65 TABLA_BANDGAP_MBHC_MODE,
66};
67
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -070068struct mbhc_micbias_regs {
69 u16 cfilt_val;
70 u16 cfilt_ctl;
71 u16 mbhc_reg;
72 u16 int_rbias;
73 u16 ctl_reg;
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -080074 u8 cfilt_sel;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -070075};
76
Ben Romberger1f045a72011-11-04 10:14:57 -070077/* Codec supports 2 IIR filters */
78enum {
79 IIR1 = 0,
80 IIR2,
81 IIR_MAX,
82};
83/* Codec supports 5 bands */
84enum {
85 BAND1 = 0,
86 BAND2,
87 BAND3,
88 BAND4,
89 BAND5,
90 BAND_MAX,
91};
92
Joonwoo Parka9444452011-12-08 18:48:27 -080093/* Flags to track of PA and DAC state.
94 * PA and DAC should be tracked separately as AUXPGA loopback requires
95 * only PA to be turned on without DAC being on. */
96enum tabla_priv_ack_flags {
97 TABLA_HPHL_PA_OFF_ACK = 0,
98 TABLA_HPHR_PA_OFF_ACK,
99 TABLA_HPHL_DAC_OFF_ACK,
100 TABLA_HPHR_DAC_OFF_ACK
101};
102
Joonwoo Park0976d012011-12-22 11:48:18 -0800103/* Data used by MBHC */
104struct mbhc_internal_cal_data {
105 u16 dce_z;
106 u16 dce_mb;
107 u16 sta_z;
108 u16 sta_mb;
109 u32 t_dce;
110 u32 t_sta;
111 u32 micb_mv;
112 u16 v_ins_hu;
113 u16 v_ins_h;
114 u16 v_b1_hu;
115 u16 v_b1_h;
116 u16 v_b1_huc;
117 u16 v_brh;
118 u16 v_brl;
119 u16 v_no_mic;
120 u8 nready;
121 u8 npoll;
122 u8 nbounce_wait;
123};
124
Bradley Rubin229c6a52011-07-12 16:18:48 -0700125struct tabla_priv {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 struct snd_soc_codec *codec;
Joonwoo Park0976d012011-12-22 11:48:18 -0800127 u32 mclk_freq;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 u32 adc_count;
Patrick Lai3043fba2011-08-01 14:15:57 -0700129 u32 cfilt1_cnt;
130 u32 cfilt2_cnt;
131 u32 cfilt3_cnt;
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700132 u32 rx_bias_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133 enum tabla_bandgap_type bandgap_type;
Kiran Kandi6fae8bf2011-08-15 10:36:42 -0700134 bool mclk_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135 bool clock_active;
136 bool config_mode_active;
137 bool mbhc_polling_active;
Joonwoo Parkf4267c22012-01-10 13:25:24 -0800138 unsigned long mbhc_fake_ins_start;
Bradley Rubincb1e2732011-06-23 16:49:20 -0700139 int buttons_pressed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700140
Joonwoo Park0976d012011-12-22 11:48:18 -0800141 enum tabla_micbias_num micbias;
142 /* void* calibration contains:
143 * struct tabla_mbhc_general_cfg generic;
144 * struct tabla_mbhc_plug_detect_cfg plug_det;
145 * struct tabla_mbhc_plug_type_cfg plug_type;
146 * struct tabla_mbhc_btn_detect_cfg btn_det;
147 * struct tabla_mbhc_imped_detect_cfg imped_det;
148 * Note: various size depends on btn_det->num_btn
149 */
150 void *calibration;
151 struct mbhc_internal_cal_data mbhc_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152
Bradley Rubincb1e2732011-06-23 16:49:20 -0700153 struct snd_soc_jack *headset_jack;
154 struct snd_soc_jack *button_jack;
Bradley Rubin229c6a52011-07-12 16:18:48 -0700155
Patrick Lai3043fba2011-08-01 14:15:57 -0700156 struct tabla_pdata *pdata;
Bradley Rubina7096d02011-08-03 18:29:02 -0700157 u32 anc_slot;
Bradley Rubincb3950a2011-08-18 13:07:26 -0700158
159 bool no_mic_headset_override;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -0700160 /* Delayed work to report long button press */
161 struct delayed_work btn0_dwork;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -0700162
163 struct mbhc_micbias_regs mbhc_bias_regs;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -0700164 u8 cfilt_k_value;
165 bool mbhc_micbias_switched;
Patrick Lai49efeac2011-11-03 11:01:12 -0700166
Joonwoo Parka9444452011-12-08 18:48:27 -0800167 /* track PA/DAC state */
168 unsigned long hph_pa_dac_state;
169
Santosh Mardie15e2302011-11-15 10:39:23 +0530170 /*track tabla interface type*/
171 u8 intf_type;
172
Patrick Lai49efeac2011-11-03 11:01:12 -0700173 u32 hph_status; /* track headhpone status */
174 /* define separate work for left and right headphone OCP to avoid
175 * additional checking on which OCP event to report so no locking
176 * to ensure synchronization is required
177 */
178 struct work_struct hphlocp_work; /* reporting left hph ocp off */
179 struct work_struct hphrocp_work; /* reporting right hph ocp off */
Joonwoo Park8b1f0982011-12-08 17:12:45 -0800180
181 /* pm_cnt holds number of sleep lock holders + 1
182 * so if pm_cnt is 1 system is sleep-able. */
183 atomic_t pm_cnt;
184 wait_queue_head_t pm_wq;
Patrick Laic7cae882011-11-18 11:52:49 -0800185
186 u8 hphlocp_cnt; /* headphone left ocp retry */
187 u8 hphrocp_cnt; /* headphone right ocp retry */
Joonwoo Park0976d012011-12-22 11:48:18 -0800188
189 /* Callback function to enable MCLK */
190 int (*mclk_cb) (struct snd_soc_codec*, int);
Patrick Lai64b43262011-12-06 17:29:15 -0800191
192 /* Work to perform MBHC Firmware Read */
193 struct delayed_work mbhc_firmware_dwork;
194 const struct firmware *mbhc_fw;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195};
196
Bradley Rubincb3950a2011-08-18 13:07:26 -0700197#ifdef CONFIG_DEBUG_FS
198struct tabla_priv *debug_tabla_priv;
199#endif
200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201static int tabla_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
202 struct snd_kcontrol *kcontrol, int event)
203{
204 struct snd_soc_codec *codec = w->codec;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205
206 pr_debug("%s %d\n", __func__, event);
207 switch (event) {
208 case SND_SOC_DAPM_POST_PMU:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
210 0x01);
211 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x08);
212 usleep_range(200, 200);
213 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x00);
214 break;
215 case SND_SOC_DAPM_PRE_PMD:
216 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
217 0x10);
218 usleep_range(20, 20);
219 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x08);
220 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x10);
221 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x00);
222 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
223 0x00);
224 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x00);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 break;
226 }
227 return 0;
228}
229
Bradley Rubina7096d02011-08-03 18:29:02 -0700230static int tabla_get_anc_slot(struct snd_kcontrol *kcontrol,
231 struct snd_ctl_elem_value *ucontrol)
232{
233 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
234 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
235 ucontrol->value.integer.value[0] = tabla->anc_slot;
236 return 0;
237}
238
239static int tabla_put_anc_slot(struct snd_kcontrol *kcontrol,
240 struct snd_ctl_elem_value *ucontrol)
241{
242 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
243 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
244 tabla->anc_slot = ucontrol->value.integer.value[0];
245 return 0;
246}
247
Kiran Kandid2d86b52011-09-09 17:44:28 -0700248static int tabla_pa_gain_get(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
250{
251 u8 ear_pa_gain;
252 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
253
254 ear_pa_gain = snd_soc_read(codec, TABLA_A_RX_EAR_GAIN);
255
256 ear_pa_gain = ear_pa_gain >> 5;
257
258 if (ear_pa_gain == 0x00) {
259 ucontrol->value.integer.value[0] = 0;
260 } else if (ear_pa_gain == 0x04) {
261 ucontrol->value.integer.value[0] = 1;
262 } else {
263 pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
264 __func__, ear_pa_gain);
265 return -EINVAL;
266 }
267
268 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
269
270 return 0;
271}
272
273static int tabla_pa_gain_put(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
276 u8 ear_pa_gain;
277 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
278
279 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
280 ucontrol->value.integer.value[0]);
281
282 switch (ucontrol->value.integer.value[0]) {
283 case 0:
284 ear_pa_gain = 0x00;
285 break;
286 case 1:
287 ear_pa_gain = 0x80;
288 break;
289 default:
290 return -EINVAL;
291 }
292
293 snd_soc_update_bits(codec, TABLA_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
294 return 0;
295}
296
Ben Romberger1f045a72011-11-04 10:14:57 -0700297static int tabla_get_iir_enable_audio_mixer(
298 struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
300{
301 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
302 int iir_idx = ((struct soc_multi_mixer_control *)
303 kcontrol->private_value)->reg;
304 int band_idx = ((struct soc_multi_mixer_control *)
305 kcontrol->private_value)->shift;
306
307 ucontrol->value.integer.value[0] =
308 snd_soc_read(codec, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx)) &
309 (1 << band_idx);
310
311 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
312 iir_idx, band_idx,
313 (uint32_t)ucontrol->value.integer.value[0]);
314 return 0;
315}
316
317static int tabla_put_iir_enable_audio_mixer(
318 struct snd_kcontrol *kcontrol,
319 struct snd_ctl_elem_value *ucontrol)
320{
321 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
322 int iir_idx = ((struct soc_multi_mixer_control *)
323 kcontrol->private_value)->reg;
324 int band_idx = ((struct soc_multi_mixer_control *)
325 kcontrol->private_value)->shift;
326 int value = ucontrol->value.integer.value[0];
327
328 /* Mask first 5 bits, 6-8 are reserved */
329 snd_soc_update_bits(codec, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx),
330 (1 << band_idx), (value << band_idx));
331
332 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
333 iir_idx, band_idx, value);
334 return 0;
335}
336static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
337 int iir_idx, int band_idx,
338 int coeff_idx)
339{
340 /* Address does not automatically update if reading */
341 snd_soc_update_bits(codec,
342 (TABLA_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
343 0x1F, band_idx * BAND_MAX + coeff_idx);
344
345 /* Mask bits top 2 bits since they are reserved */
346 return ((snd_soc_read(codec,
347 (TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24) |
348 (snd_soc_read(codec,
349 (TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx)) << 16) |
350 (snd_soc_read(codec,
351 (TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx)) << 8) |
352 (snd_soc_read(codec,
353 (TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx)))) &
354 0x3FFFFFFF;
355}
356
357static int tabla_get_iir_band_audio_mixer(
358 struct snd_kcontrol *kcontrol,
359 struct snd_ctl_elem_value *ucontrol)
360{
361 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
362 int iir_idx = ((struct soc_multi_mixer_control *)
363 kcontrol->private_value)->reg;
364 int band_idx = ((struct soc_multi_mixer_control *)
365 kcontrol->private_value)->shift;
366
367 ucontrol->value.integer.value[0] =
368 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
369 ucontrol->value.integer.value[1] =
370 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
371 ucontrol->value.integer.value[2] =
372 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
373 ucontrol->value.integer.value[3] =
374 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
375 ucontrol->value.integer.value[4] =
376 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
377
378 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
379 "%s: IIR #%d band #%d b1 = 0x%x\n"
380 "%s: IIR #%d band #%d b2 = 0x%x\n"
381 "%s: IIR #%d band #%d a1 = 0x%x\n"
382 "%s: IIR #%d band #%d a2 = 0x%x\n",
383 __func__, iir_idx, band_idx,
384 (uint32_t)ucontrol->value.integer.value[0],
385 __func__, iir_idx, band_idx,
386 (uint32_t)ucontrol->value.integer.value[1],
387 __func__, iir_idx, band_idx,
388 (uint32_t)ucontrol->value.integer.value[2],
389 __func__, iir_idx, band_idx,
390 (uint32_t)ucontrol->value.integer.value[3],
391 __func__, iir_idx, band_idx,
392 (uint32_t)ucontrol->value.integer.value[4]);
393 return 0;
394}
395
396static void set_iir_band_coeff(struct snd_soc_codec *codec,
397 int iir_idx, int band_idx,
398 int coeff_idx, uint32_t value)
399{
400 /* Mask top 3 bits, 6-8 are reserved */
401 /* Update address manually each time */
402 snd_soc_update_bits(codec,
403 (TABLA_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
404 0x1F, band_idx * BAND_MAX + coeff_idx);
405
406 /* Mask top 2 bits, 7-8 are reserved */
407 snd_soc_update_bits(codec,
408 (TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
409 0x3F, (value >> 24) & 0x3F);
410
411 /* Isolate 8bits at a time */
412 snd_soc_update_bits(codec,
413 (TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx),
414 0xFF, (value >> 16) & 0xFF);
415
416 snd_soc_update_bits(codec,
417 (TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx),
418 0xFF, (value >> 8) & 0xFF);
419
420 snd_soc_update_bits(codec,
421 (TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx),
422 0xFF, value & 0xFF);
423}
424
425static int tabla_put_iir_band_audio_mixer(
426 struct snd_kcontrol *kcontrol,
427 struct snd_ctl_elem_value *ucontrol)
428{
429 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
430 int iir_idx = ((struct soc_multi_mixer_control *)
431 kcontrol->private_value)->reg;
432 int band_idx = ((struct soc_multi_mixer_control *)
433 kcontrol->private_value)->shift;
434
435 set_iir_band_coeff(codec, iir_idx, band_idx, 0,
436 ucontrol->value.integer.value[0]);
437 set_iir_band_coeff(codec, iir_idx, band_idx, 1,
438 ucontrol->value.integer.value[1]);
439 set_iir_band_coeff(codec, iir_idx, band_idx, 2,
440 ucontrol->value.integer.value[2]);
441 set_iir_band_coeff(codec, iir_idx, band_idx, 3,
442 ucontrol->value.integer.value[3]);
443 set_iir_band_coeff(codec, iir_idx, band_idx, 4,
444 ucontrol->value.integer.value[4]);
445
446 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
447 "%s: IIR #%d band #%d b1 = 0x%x\n"
448 "%s: IIR #%d band #%d b2 = 0x%x\n"
449 "%s: IIR #%d band #%d a1 = 0x%x\n"
450 "%s: IIR #%d band #%d a2 = 0x%x\n",
451 __func__, iir_idx, band_idx,
452 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
453 __func__, iir_idx, band_idx,
454 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
455 __func__, iir_idx, band_idx,
456 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
457 __func__, iir_idx, band_idx,
458 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
459 __func__, iir_idx, band_idx,
460 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
461 return 0;
462}
463
Kiran Kandid2d86b52011-09-09 17:44:28 -0700464static const char *tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
465static const struct soc_enum tabla_ear_pa_gain_enum[] = {
466 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
467};
468
Santosh Mardi024010f2011-10-18 06:27:21 +0530469/*cut of frequency for high pass filter*/
470static const char *cf_text[] = {
471 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
472};
473
474static const struct soc_enum cf_dec1_enum =
475 SOC_ENUM_SINGLE(TABLA_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
476
477static const struct soc_enum cf_dec2_enum =
478 SOC_ENUM_SINGLE(TABLA_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
479
480static const struct soc_enum cf_dec3_enum =
481 SOC_ENUM_SINGLE(TABLA_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
482
483static const struct soc_enum cf_dec4_enum =
484 SOC_ENUM_SINGLE(TABLA_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
485
486static const struct soc_enum cf_dec5_enum =
487 SOC_ENUM_SINGLE(TABLA_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
488
489static const struct soc_enum cf_dec6_enum =
490 SOC_ENUM_SINGLE(TABLA_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
491
492static const struct soc_enum cf_dec7_enum =
493 SOC_ENUM_SINGLE(TABLA_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
494
495static const struct soc_enum cf_dec8_enum =
496 SOC_ENUM_SINGLE(TABLA_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
497
498static const struct soc_enum cf_dec9_enum =
499 SOC_ENUM_SINGLE(TABLA_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
500
501static const struct soc_enum cf_dec10_enum =
502 SOC_ENUM_SINGLE(TABLA_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
503
504static const struct soc_enum cf_rxmix1_enum =
505 SOC_ENUM_SINGLE(TABLA_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
506
507static const struct soc_enum cf_rxmix2_enum =
508 SOC_ENUM_SINGLE(TABLA_A_CDC_RX2_B4_CTL, 1, 3, cf_text);
509
510static const struct soc_enum cf_rxmix3_enum =
511 SOC_ENUM_SINGLE(TABLA_A_CDC_RX3_B4_CTL, 1, 3, cf_text);
512
513static const struct soc_enum cf_rxmix4_enum =
514 SOC_ENUM_SINGLE(TABLA_A_CDC_RX4_B4_CTL, 1, 3, cf_text);
515
516static const struct soc_enum cf_rxmix5_enum =
517 SOC_ENUM_SINGLE(TABLA_A_CDC_RX5_B4_CTL, 1, 3, cf_text)
518;
519static const struct soc_enum cf_rxmix6_enum =
520 SOC_ENUM_SINGLE(TABLA_A_CDC_RX6_B4_CTL, 1, 3, cf_text);
521
522static const struct soc_enum cf_rxmix7_enum =
523 SOC_ENUM_SINGLE(TABLA_A_CDC_RX7_B4_CTL, 1, 3, cf_text);
524
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525static const struct snd_kcontrol_new tabla_snd_controls[] = {
Kiran Kandid2d86b52011-09-09 17:44:28 -0700526
527 SOC_ENUM_EXT("EAR PA Gain", tabla_ear_pa_gain_enum[0],
528 tabla_pa_gain_get, tabla_pa_gain_put),
529
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700530 SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
531 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700532 SOC_SINGLE_TLV("LINEOUT2 Volume", TABLA_A_RX_LINE_2_GAIN, 0, 12, 1,
533 line_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700534 SOC_SINGLE_TLV("LINEOUT3 Volume", TABLA_A_RX_LINE_3_GAIN, 0, 12, 1,
535 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700536 SOC_SINGLE_TLV("LINEOUT4 Volume", TABLA_A_RX_LINE_4_GAIN, 0, 12, 1,
537 line_gain),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700538 SOC_SINGLE_TLV("LINEOUT5 Volume", TABLA_A_RX_LINE_5_GAIN, 0, 12, 1,
539 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700540
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700541 SOC_SINGLE_TLV("HPHL Volume", TABLA_A_RX_HPH_L_GAIN, 0, 12, 1,
542 line_gain),
543 SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
544 line_gain),
545
Bradley Rubin410383f2011-07-22 13:44:23 -0700546 SOC_SINGLE_S8_TLV("RX1 Digital Volume", TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
547 -84, 40, digital_gain),
548 SOC_SINGLE_S8_TLV("RX2 Digital Volume", TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
549 -84, 40, digital_gain),
550 SOC_SINGLE_S8_TLV("RX3 Digital Volume", TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
551 -84, 40, digital_gain),
552 SOC_SINGLE_S8_TLV("RX4 Digital Volume", TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
553 -84, 40, digital_gain),
554 SOC_SINGLE_S8_TLV("RX5 Digital Volume", TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
555 -84, 40, digital_gain),
556 SOC_SINGLE_S8_TLV("RX6 Digital Volume", TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
557 -84, 40, digital_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558
Bradley Rubin410383f2011-07-22 13:44:23 -0700559 SOC_SINGLE_S8_TLV("DEC1 Volume", TABLA_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560 digital_gain),
Bradley Rubin410383f2011-07-22 13:44:23 -0700561 SOC_SINGLE_S8_TLV("DEC2 Volume", TABLA_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 digital_gain),
Bradley Rubin410383f2011-07-22 13:44:23 -0700563 SOC_SINGLE_S8_TLV("DEC3 Volume", TABLA_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
564 digital_gain),
565 SOC_SINGLE_S8_TLV("DEC4 Volume", TABLA_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
566 digital_gain),
567 SOC_SINGLE_S8_TLV("DEC5 Volume", TABLA_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
568 digital_gain),
569 SOC_SINGLE_S8_TLV("DEC6 Volume", TABLA_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
570 digital_gain),
571 SOC_SINGLE_S8_TLV("DEC7 Volume", TABLA_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
572 digital_gain),
573 SOC_SINGLE_S8_TLV("DEC8 Volume", TABLA_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
574 digital_gain),
575 SOC_SINGLE_S8_TLV("DEC9 Volume", TABLA_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
576 digital_gain),
577 SOC_SINGLE_S8_TLV("DEC10 Volume", TABLA_A_CDC_TX10_VOL_CTL_GAIN, -84,
578 40, digital_gain),
Patrick Lai29006372011-09-28 17:57:42 -0700579 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TABLA_A_CDC_IIR1_GAIN_B1_CTL, -84,
580 40, digital_gain),
581 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TABLA_A_CDC_IIR1_GAIN_B2_CTL, -84,
582 40, digital_gain),
583 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TABLA_A_CDC_IIR1_GAIN_B3_CTL, -84,
584 40, digital_gain),
585 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TABLA_A_CDC_IIR1_GAIN_B4_CTL, -84,
586 40, digital_gain),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700587 SOC_SINGLE_TLV("ADC1 Volume", TABLA_A_TX_1_2_EN, 5, 3, 0, analog_gain),
588 SOC_SINGLE_TLV("ADC2 Volume", TABLA_A_TX_1_2_EN, 1, 3, 0, analog_gain),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700589 SOC_SINGLE_TLV("ADC3 Volume", TABLA_A_TX_3_4_EN, 5, 3, 0, analog_gain),
590 SOC_SINGLE_TLV("ADC4 Volume", TABLA_A_TX_3_4_EN, 1, 3, 0, analog_gain),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700591 SOC_SINGLE_TLV("ADC5 Volume", TABLA_A_TX_5_6_EN, 5, 3, 0, analog_gain),
592 SOC_SINGLE_TLV("ADC6 Volume", TABLA_A_TX_5_6_EN, 1, 3, 0, analog_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700593
594 SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
Santosh Mardi680b41e2011-11-22 16:51:16 -0800595 SOC_SINGLE("MICBIAS2 CAPLESS Switch", TABLA_A_MICB_2_CTL, 4, 1, 1),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700596 SOC_SINGLE("MICBIAS3 CAPLESS Switch", TABLA_A_MICB_3_CTL, 4, 1, 1),
597 SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_A_MICB_4_CTL, 4, 1, 1),
Bradley Rubina7096d02011-08-03 18:29:02 -0700598
599 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tabla_get_anc_slot,
600 tabla_put_anc_slot),
Santosh Mardi024010f2011-10-18 06:27:21 +0530601 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
602 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
603 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
604 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
605 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
606 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
607 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
608 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
609 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
610 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
611
612 SOC_SINGLE("TX1 HPF Switch", TABLA_A_CDC_TX1_MUX_CTL, 3, 1, 0),
613 SOC_SINGLE("TX2 HPF Switch", TABLA_A_CDC_TX2_MUX_CTL, 3, 1, 0),
614 SOC_SINGLE("TX3 HPF Switch", TABLA_A_CDC_TX3_MUX_CTL, 3, 1, 0),
615 SOC_SINGLE("TX4 HPF Switch", TABLA_A_CDC_TX4_MUX_CTL, 3, 1, 0),
616 SOC_SINGLE("TX5 HPF Switch", TABLA_A_CDC_TX5_MUX_CTL, 3, 1, 0),
617 SOC_SINGLE("TX6 HPF Switch", TABLA_A_CDC_TX6_MUX_CTL, 3, 1, 0),
618 SOC_SINGLE("TX7 HPF Switch", TABLA_A_CDC_TX7_MUX_CTL, 3, 1, 0),
619 SOC_SINGLE("TX8 HPF Switch", TABLA_A_CDC_TX8_MUX_CTL, 3, 1, 0),
620 SOC_SINGLE("TX9 HPF Switch", TABLA_A_CDC_TX9_MUX_CTL, 3, 1, 0),
621 SOC_SINGLE("TX10 HPF Switch", TABLA_A_CDC_TX10_MUX_CTL, 3, 1, 0),
622
623 SOC_SINGLE("RX1 HPF Switch", TABLA_A_CDC_RX1_B5_CTL, 2, 1, 0),
624 SOC_SINGLE("RX2 HPF Switch", TABLA_A_CDC_RX2_B5_CTL, 2, 1, 0),
625 SOC_SINGLE("RX3 HPF Switch", TABLA_A_CDC_RX3_B5_CTL, 2, 1, 0),
626 SOC_SINGLE("RX4 HPF Switch", TABLA_A_CDC_RX4_B5_CTL, 2, 1, 0),
627 SOC_SINGLE("RX5 HPF Switch", TABLA_A_CDC_RX5_B5_CTL, 2, 1, 0),
628 SOC_SINGLE("RX6 HPF Switch", TABLA_A_CDC_RX6_B5_CTL, 2, 1, 0),
629 SOC_SINGLE("RX7 HPF Switch", TABLA_A_CDC_RX7_B5_CTL, 2, 1, 0),
630
631 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
632 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
633 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
634 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
635 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
636 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
637 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
Ben Romberger1f045a72011-11-04 10:14:57 -0700638
639 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
640 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
641 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
642 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
643 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
644 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
645 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
646 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
647 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
648 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
649 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
650 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
651 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
652 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
653 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
654 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
655 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
656 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
657 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
658 tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
659
660 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
661 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
662 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
663 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
664 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
665 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
666 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
667 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
668 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
669 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
670 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
671 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
672 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
673 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
674 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
675 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
676 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
677 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
678 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
679 tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680};
681
682static const char *rx_mix1_text[] = {
683 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
684 "RX5", "RX6", "RX7"
685};
686
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700687static const char *rx_dsm_text[] = {
688 "CIC_OUT", "DSM_INV"
689};
690
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700691static const char *sb_tx1_mux_text[] = {
692 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
693 "DEC1"
694};
695
696static const char *sb_tx5_mux_text[] = {
697 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
698 "DEC5"
699};
700
701static const char *sb_tx6_mux_text[] = {
702 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
703 "DEC6"
704};
705
706static const char const *sb_tx7_to_tx10_mux_text[] = {
707 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
708 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
709 "DEC9", "DEC10"
710};
711
712static const char *dec1_mux_text[] = {
713 "ZERO", "DMIC1", "ADC6",
714};
715
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700716static const char *dec2_mux_text[] = {
717 "ZERO", "DMIC2", "ADC5",
718};
719
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700720static const char *dec3_mux_text[] = {
721 "ZERO", "DMIC3", "ADC4",
722};
723
724static const char *dec4_mux_text[] = {
725 "ZERO", "DMIC4", "ADC3",
726};
727
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700728static const char *dec5_mux_text[] = {
729 "ZERO", "DMIC5", "ADC2",
730};
731
732static const char *dec6_mux_text[] = {
733 "ZERO", "DMIC6", "ADC1",
734};
735
736static const char const *dec7_mux_text[] = {
737 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
738};
739
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700740static const char *dec8_mux_text[] = {
741 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
742};
743
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700744static const char *dec9_mux_text[] = {
745 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
746};
747
748static const char *dec10_mux_text[] = {
749 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
750};
751
Bradley Rubin229c6a52011-07-12 16:18:48 -0700752static const char const *anc_mux_text[] = {
753 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
754 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
755};
756
757static const char const *anc1_fb_mux_text[] = {
758 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
759};
760
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761static const char *iir1_inp1_text[] = {
762 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
763 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
764};
765
766static const struct soc_enum rx_mix1_inp1_chain_enum =
767 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
768
Bradley Rubin229c6a52011-07-12 16:18:48 -0700769static const struct soc_enum rx_mix1_inp2_chain_enum =
770 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
771
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772static const struct soc_enum rx2_mix1_inp1_chain_enum =
773 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
774
Bradley Rubin229c6a52011-07-12 16:18:48 -0700775static const struct soc_enum rx2_mix1_inp2_chain_enum =
776 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
777
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778static const struct soc_enum rx3_mix1_inp1_chain_enum =
779 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
780
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700781static const struct soc_enum rx3_mix1_inp2_chain_enum =
782 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
783
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784static const struct soc_enum rx4_mix1_inp1_chain_enum =
785 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
786
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700787static const struct soc_enum rx4_mix1_inp2_chain_enum =
788 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
789
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790static const struct soc_enum rx5_mix1_inp1_chain_enum =
791 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
792
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700793static const struct soc_enum rx5_mix1_inp2_chain_enum =
794 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
795
796static const struct soc_enum rx6_mix1_inp1_chain_enum =
797 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
798
799static const struct soc_enum rx6_mix1_inp2_chain_enum =
800 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
801
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700802static const struct soc_enum rx7_mix1_inp1_chain_enum =
803 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
804
805static const struct soc_enum rx7_mix1_inp2_chain_enum =
806 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
807
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700808static const struct soc_enum rx4_dsm_enum =
809 SOC_ENUM_SINGLE(TABLA_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
810
811static const struct soc_enum rx6_dsm_enum =
812 SOC_ENUM_SINGLE(TABLA_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
813
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814static const struct soc_enum sb_tx5_mux_enum =
815 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
816
817static const struct soc_enum sb_tx6_mux_enum =
818 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
819
820static const struct soc_enum sb_tx7_mux_enum =
821 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
822 sb_tx7_to_tx10_mux_text);
823
824static const struct soc_enum sb_tx8_mux_enum =
825 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
826 sb_tx7_to_tx10_mux_text);
827
Kiran Kandi3426e512011-09-13 22:50:10 -0700828static const struct soc_enum sb_tx9_mux_enum =
829 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
830 sb_tx7_to_tx10_mux_text);
831
832static const struct soc_enum sb_tx10_mux_enum =
833 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
834 sb_tx7_to_tx10_mux_text);
835
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700836static const struct soc_enum sb_tx1_mux_enum =
837 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
838
839static const struct soc_enum dec1_mux_enum =
840 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
841
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700842static const struct soc_enum dec2_mux_enum =
843 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
844
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700845static const struct soc_enum dec3_mux_enum =
846 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
847
848static const struct soc_enum dec4_mux_enum =
849 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
850
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700851static const struct soc_enum dec5_mux_enum =
852 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
853
854static const struct soc_enum dec6_mux_enum =
855 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
856
857static const struct soc_enum dec7_mux_enum =
858 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
859
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700860static const struct soc_enum dec8_mux_enum =
861 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
862
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700863static const struct soc_enum dec9_mux_enum =
864 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
865
866static const struct soc_enum dec10_mux_enum =
867 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
868
Bradley Rubin229c6a52011-07-12 16:18:48 -0700869static const struct soc_enum anc1_mux_enum =
870 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
871
872static const struct soc_enum anc2_mux_enum =
873 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
874
875static const struct soc_enum anc1_fb_mux_enum =
876 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
877
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878static const struct soc_enum iir1_inp1_mux_enum =
879 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
880
881static const struct snd_kcontrol_new rx_mix1_inp1_mux =
882 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
883
Bradley Rubin229c6a52011-07-12 16:18:48 -0700884static const struct snd_kcontrol_new rx_mix1_inp2_mux =
885 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
886
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
888 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
889
Bradley Rubin229c6a52011-07-12 16:18:48 -0700890static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
891 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
892
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
894 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
895
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700896static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
897 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
898
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
900 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
901
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700902static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
903 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
904
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
906 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
907
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700908static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
909 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
910
911static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
912 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
913
914static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
915 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
916
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -0700917static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
918 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
919
920static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
921 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
922
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700923static const struct snd_kcontrol_new rx4_dsm_mux =
924 SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
925
926static const struct snd_kcontrol_new rx6_dsm_mux =
927 SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
928
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929static const struct snd_kcontrol_new sb_tx5_mux =
930 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
931
932static const struct snd_kcontrol_new sb_tx6_mux =
933 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
934
935static const struct snd_kcontrol_new sb_tx7_mux =
936 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
937
938static const struct snd_kcontrol_new sb_tx8_mux =
939 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
940
Kiran Kandi3426e512011-09-13 22:50:10 -0700941static const struct snd_kcontrol_new sb_tx9_mux =
942 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
943
944static const struct snd_kcontrol_new sb_tx10_mux =
945 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
946
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700947static const struct snd_kcontrol_new sb_tx1_mux =
948 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
949
950static const struct snd_kcontrol_new dec1_mux =
951 SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
952
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700953static const struct snd_kcontrol_new dec2_mux =
954 SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
955
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700956static const struct snd_kcontrol_new dec3_mux =
957 SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
958
959static const struct snd_kcontrol_new dec4_mux =
960 SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
961
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700962static const struct snd_kcontrol_new dec5_mux =
963 SOC_DAPM_ENUM("DEC5 MUX Mux", dec5_mux_enum);
964
965static const struct snd_kcontrol_new dec6_mux =
966 SOC_DAPM_ENUM("DEC6 MUX Mux", dec6_mux_enum);
967
968static const struct snd_kcontrol_new dec7_mux =
969 SOC_DAPM_ENUM("DEC7 MUX Mux", dec7_mux_enum);
970
Bradley Rubin229c6a52011-07-12 16:18:48 -0700971static const struct snd_kcontrol_new anc1_mux =
972 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -0700973static const struct snd_kcontrol_new dec8_mux =
974 SOC_DAPM_ENUM("DEC8 MUX Mux", dec8_mux_enum);
975
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -0700976static const struct snd_kcontrol_new dec9_mux =
977 SOC_DAPM_ENUM("DEC9 MUX Mux", dec9_mux_enum);
978
979static const struct snd_kcontrol_new dec10_mux =
980 SOC_DAPM_ENUM("DEC10 MUX Mux", dec10_mux_enum);
981
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700982static const struct snd_kcontrol_new iir1_inp1_mux =
983 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
984
Bradley Rubin229c6a52011-07-12 16:18:48 -0700985static const struct snd_kcontrol_new anc2_mux =
986 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700987
Bradley Rubin229c6a52011-07-12 16:18:48 -0700988static const struct snd_kcontrol_new anc1_fb_mux =
989 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700990
Bradley Rubin229c6a52011-07-12 16:18:48 -0700991static const struct snd_kcontrol_new dac1_switch[] = {
992 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_EAR_EN, 5, 1, 0)
993};
994static const struct snd_kcontrol_new hphl_switch[] = {
995 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
996};
Kiran Kandi8b3a8302011-09-27 16:13:28 -0700997
998static const struct snd_kcontrol_new lineout3_ground_switch =
999 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
1000
1001static const struct snd_kcontrol_new lineout4_ground_switch =
1002 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001003
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001004static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
1005 int enable)
1006{
1007 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1008
1009 pr_debug("%s %d\n", __func__, enable);
1010
1011 if (enable) {
1012 tabla->adc_count++;
1013 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
1014 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
1015 } else {
1016 tabla->adc_count--;
1017 if (!tabla->adc_count) {
1018 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL,
1019 0x2, 0x0);
1020 if (!tabla->mbhc_polling_active)
1021 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS,
1022 0xE0, 0x0);
1023 }
1024 }
1025}
1026
1027static int tabla_codec_enable_adc(struct snd_soc_dapm_widget *w,
1028 struct snd_kcontrol *kcontrol, int event)
1029{
1030 struct snd_soc_codec *codec = w->codec;
1031 u16 adc_reg;
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001032 u8 init_bit_shift;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001033
1034 pr_debug("%s %d\n", __func__, event);
1035
1036 if (w->reg == TABLA_A_TX_1_2_EN)
1037 adc_reg = TABLA_A_TX_1_2_TEST_CTL;
1038 else if (w->reg == TABLA_A_TX_3_4_EN)
1039 adc_reg = TABLA_A_TX_3_4_TEST_CTL;
1040 else if (w->reg == TABLA_A_TX_5_6_EN)
1041 adc_reg = TABLA_A_TX_5_6_TEST_CTL;
1042 else {
1043 pr_err("%s: Error, invalid adc register\n", __func__);
1044 return -EINVAL;
1045 }
1046
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001047 if (w->shift == 3)
1048 init_bit_shift = 6;
1049 else if (w->shift == 7)
1050 init_bit_shift = 7;
1051 else {
1052 pr_err("%s: Error, invalid init bit postion adc register\n",
1053 __func__);
1054 return -EINVAL;
1055 }
1056
1057
1058
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059 switch (event) {
1060 case SND_SOC_DAPM_PRE_PMU:
1061 tabla_codec_enable_adc_block(codec, 1);
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001062 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1063 1 << init_bit_shift);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001064 break;
1065 case SND_SOC_DAPM_POST_PMU:
Kiran Kandi9a2c62a82011-12-07 13:13:26 -08001066
1067 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
1068
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 break;
1070 case SND_SOC_DAPM_POST_PMD:
1071 tabla_codec_enable_adc_block(codec, 0);
1072 break;
1073 }
1074 return 0;
1075}
1076
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001077static int tabla_codec_enable_lineout(struct snd_soc_dapm_widget *w,
1078 struct snd_kcontrol *kcontrol, int event)
1079{
1080 struct snd_soc_codec *codec = w->codec;
1081 u16 lineout_gain_reg;
1082
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001083 pr_debug("%s %d %s\n", __func__, event, w->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001084
1085 switch (w->shift) {
1086 case 0:
1087 lineout_gain_reg = TABLA_A_RX_LINE_1_GAIN;
1088 break;
1089 case 1:
1090 lineout_gain_reg = TABLA_A_RX_LINE_2_GAIN;
1091 break;
1092 case 2:
1093 lineout_gain_reg = TABLA_A_RX_LINE_3_GAIN;
1094 break;
1095 case 3:
1096 lineout_gain_reg = TABLA_A_RX_LINE_4_GAIN;
1097 break;
1098 case 4:
1099 lineout_gain_reg = TABLA_A_RX_LINE_5_GAIN;
1100 break;
1101 default:
1102 pr_err("%s: Error, incorrect lineout register value\n",
1103 __func__);
1104 return -EINVAL;
1105 }
1106
1107 switch (event) {
1108 case SND_SOC_DAPM_PRE_PMU:
1109 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
1110 break;
1111 case SND_SOC_DAPM_POST_PMU:
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001112 pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001113 __func__, w->name);
Krishnankutty Kolathappilly31169f42011-11-17 10:33:11 -08001114 usleep_range(16000, 16000);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001115 break;
1116 case SND_SOC_DAPM_POST_PMD:
1117 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
1118 break;
1119 }
1120 return 0;
1121}
1122
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001123
1124static int tabla_codec_enable_dmic(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001125 struct snd_kcontrol *kcontrol, int event)
1126{
1127 struct snd_soc_codec *codec = w->codec;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001128 u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
1129 u8 dmic_clk_sel, dmic_clk_en;
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001130 unsigned int dmic;
1131 int ret;
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001132
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001133 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
1134 if (ret < 0) {
1135 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001136 return -EINVAL;
1137 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07001139 switch (dmic) {
1140 case 1:
1141 case 2:
1142 dmic_clk_sel = 0x02;
1143 dmic_clk_en = 0x01;
1144 break;
1145
1146 case 3:
1147 case 4:
1148 dmic_clk_sel = 0x08;
1149 dmic_clk_en = 0x04;
1150 break;
1151
1152 case 5:
1153 case 6:
1154 dmic_clk_sel = 0x20;
1155 dmic_clk_en = 0x10;
1156 break;
1157
1158 default:
1159 pr_err("%s: Invalid DMIC Selection\n", __func__);
1160 return -EINVAL;
1161 }
1162
1163 tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
1164 tx_dmic_ctl_reg = TABLA_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
1165
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001166 pr_debug("%s %d\n", __func__, event);
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001167
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168 switch (event) {
1169 case SND_SOC_DAPM_PRE_PMU:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001170 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
1171
1172 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1173 dmic_clk_sel, dmic_clk_sel);
1174
1175 snd_soc_update_bits(codec, tx_dmic_ctl_reg, 0x1, 0x1);
1176
1177 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1178 dmic_clk_en, dmic_clk_en);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001179 break;
1180 case SND_SOC_DAPM_POST_PMD:
Kiran Kandicf45f6a2011-07-17 21:10:19 -07001181 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
1182 dmic_clk_en, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 break;
1184 }
1185 return 0;
1186}
1187
Bradley Rubin229c6a52011-07-12 16:18:48 -07001188static int tabla_codec_enable_anc(struct snd_soc_dapm_widget *w,
1189 struct snd_kcontrol *kcontrol, int event)
1190{
1191 struct snd_soc_codec *codec = w->codec;
1192 const char *filename;
1193 const struct firmware *fw;
1194 int i;
1195 int ret;
Bradley Rubina7096d02011-08-03 18:29:02 -07001196 int num_anc_slots;
1197 struct anc_header *anc_head;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001198 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubina7096d02011-08-03 18:29:02 -07001199 u32 anc_writes_size = 0;
1200 int anc_size_remaining;
1201 u32 *anc_ptr;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001202 u16 reg;
1203 u8 mask, val, old_val;
1204
1205 pr_debug("%s %d\n", __func__, event);
1206 switch (event) {
1207 case SND_SOC_DAPM_PRE_PMU:
1208
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001209 filename = "wcd9310/wcd9310_anc.bin";
Bradley Rubin229c6a52011-07-12 16:18:48 -07001210
1211 ret = request_firmware(&fw, filename, codec->dev);
1212 if (ret != 0) {
1213 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
1214 ret);
1215 return -ENODEV;
1216 }
1217
Bradley Rubina7096d02011-08-03 18:29:02 -07001218 if (fw->size < sizeof(struct anc_header)) {
Bradley Rubin229c6a52011-07-12 16:18:48 -07001219 dev_err(codec->dev, "Not enough data\n");
1220 release_firmware(fw);
1221 return -ENOMEM;
1222 }
1223
1224 /* First number is the number of register writes */
Bradley Rubina7096d02011-08-03 18:29:02 -07001225 anc_head = (struct anc_header *)(fw->data);
1226 anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
1227 anc_size_remaining = fw->size - sizeof(struct anc_header);
1228 num_anc_slots = anc_head->num_anc_slots;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001229
Bradley Rubina7096d02011-08-03 18:29:02 -07001230 if (tabla->anc_slot >= num_anc_slots) {
1231 dev_err(codec->dev, "Invalid ANC slot selected\n");
1232 release_firmware(fw);
1233 return -EINVAL;
1234 }
1235
1236 for (i = 0; i < num_anc_slots; i++) {
1237
1238 if (anc_size_remaining < TABLA_PACKED_REG_SIZE) {
1239 dev_err(codec->dev, "Invalid register format\n");
1240 release_firmware(fw);
1241 return -EINVAL;
1242 }
1243 anc_writes_size = (u32)(*anc_ptr);
1244 anc_size_remaining -= sizeof(u32);
1245 anc_ptr += 1;
1246
1247 if (anc_writes_size * TABLA_PACKED_REG_SIZE
1248 > anc_size_remaining) {
1249 dev_err(codec->dev, "Invalid register format\n");
1250 release_firmware(fw);
1251 return -ENOMEM;
1252 }
1253
1254 if (tabla->anc_slot == i)
1255 break;
1256
1257 anc_size_remaining -= (anc_writes_size *
1258 TABLA_PACKED_REG_SIZE);
Bradley Rubin939ff3f2011-08-26 17:19:34 -07001259 anc_ptr += anc_writes_size;
Bradley Rubina7096d02011-08-03 18:29:02 -07001260 }
1261 if (i == num_anc_slots) {
1262 dev_err(codec->dev, "Selected ANC slot not present\n");
Bradley Rubin229c6a52011-07-12 16:18:48 -07001263 release_firmware(fw);
1264 return -ENOMEM;
1265 }
1266
Bradley Rubina7096d02011-08-03 18:29:02 -07001267 for (i = 0; i < anc_writes_size; i++) {
1268 TABLA_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
Bradley Rubin229c6a52011-07-12 16:18:48 -07001269 mask, val);
1270 old_val = snd_soc_read(codec, reg);
Bradley Rubin4283a4c2011-07-29 16:18:54 -07001271 snd_soc_write(codec, reg, (old_val & ~mask) |
1272 (val & mask));
Bradley Rubin229c6a52011-07-12 16:18:48 -07001273 }
1274 release_firmware(fw);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001275
1276 break;
1277 case SND_SOC_DAPM_POST_PMD:
1278 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
1279 snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
1280 break;
1281 }
1282 return 0;
1283}
1284
1285
Bradley Rubincb3950a2011-08-18 13:07:26 -07001286static void tabla_codec_disable_button_presses(struct snd_soc_codec *codec)
1287{
1288 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
1289 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
1290}
1291
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001292static void tabla_codec_start_hs_polling(struct snd_soc_codec *codec)
1293{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001294 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1295
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001296 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001297 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001298 if (!tabla->no_mic_headset_override) {
1299 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1300 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1301 } else {
1302 tabla_codec_disable_button_presses(codec);
1303 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001304 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1305 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
1306 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1307}
1308
1309static void tabla_codec_pause_hs_polling(struct snd_soc_codec *codec)
1310{
Bradley Rubincb3950a2011-08-18 13:07:26 -07001311 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1312
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001313 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
1314 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
Bradley Rubincb3950a2011-08-18 13:07:26 -07001315 if (!tabla->no_mic_headset_override) {
1316 tabla_disable_irq(codec->control_data,
1317 TABLA_IRQ_MBHC_POTENTIAL);
1318 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
1319 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001320}
1321
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001322static void tabla_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
1323 int mode)
1324{
1325 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1326 u8 reg_mode_val, cur_mode_val;
1327 bool mbhc_was_polling = false;
1328
1329 if (mode)
1330 reg_mode_val = TABLA_CFILT_FAST_MODE;
1331 else
1332 reg_mode_val = TABLA_CFILT_SLOW_MODE;
1333
1334 cur_mode_val = snd_soc_read(codec,
1335 tabla->mbhc_bias_regs.cfilt_ctl) & 0x40;
1336
1337 if (cur_mode_val != reg_mode_val) {
1338 if (tabla->mbhc_polling_active) {
1339 tabla_codec_pause_hs_polling(codec);
1340 mbhc_was_polling = true;
1341 }
1342 snd_soc_update_bits(codec,
1343 tabla->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
1344 if (mbhc_was_polling)
1345 tabla_codec_start_hs_polling(codec);
1346 pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
1347 cur_mode_val, reg_mode_val);
1348 } else {
1349 pr_debug("%s: CFILT Value is already %x\n",
1350 __func__, cur_mode_val);
1351 }
1352}
1353
1354static void tabla_codec_update_cfilt_usage(struct snd_soc_codec *codec,
1355 u8 cfilt_sel, int inc)
1356{
1357 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1358 u32 *cfilt_cnt_ptr = NULL;
1359 u16 micb_cfilt_reg;
1360
1361 switch (cfilt_sel) {
1362 case TABLA_CFILT1_SEL:
1363 cfilt_cnt_ptr = &tabla->cfilt1_cnt;
1364 micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
1365 break;
1366 case TABLA_CFILT2_SEL:
1367 cfilt_cnt_ptr = &tabla->cfilt2_cnt;
1368 micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
1369 break;
1370 case TABLA_CFILT3_SEL:
1371 cfilt_cnt_ptr = &tabla->cfilt3_cnt;
1372 micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
1373 break;
1374 default:
1375 return; /* should not happen */
1376 }
1377
1378 if (inc) {
1379 if (!(*cfilt_cnt_ptr)++) {
1380 /* Switch CFILT to slow mode if MBHC CFILT being used */
1381 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1382 tabla_codec_switch_cfilt_mode(codec, 0);
1383
1384 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
1385 }
1386 } else {
1387 /* check if count not zero, decrement
1388 * then check if zero, go ahead disable cfilter
1389 */
1390 if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
1391 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
1392
1393 /* Switch CFILT to fast mode if MBHC CFILT being used */
1394 if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
1395 tabla_codec_switch_cfilt_mode(codec, 1);
1396 }
1397 }
1398}
1399
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001400static int tabla_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
1401{
1402 int rc = -EINVAL;
1403 unsigned min_mv, max_mv;
1404
1405 switch (ldoh_v) {
1406 case TABLA_LDOH_1P95_V:
1407 min_mv = 160;
1408 max_mv = 1800;
1409 break;
1410 case TABLA_LDOH_2P35_V:
1411 min_mv = 200;
1412 max_mv = 2200;
1413 break;
1414 case TABLA_LDOH_2P75_V:
1415 min_mv = 240;
1416 max_mv = 2600;
1417 break;
1418 case TABLA_LDOH_2P85_V:
1419 min_mv = 250;
1420 max_mv = 2700;
1421 break;
1422 default:
1423 goto done;
1424 }
1425
1426 if (cfilt_mv < min_mv || cfilt_mv > max_mv)
1427 goto done;
1428
1429 for (rc = 4; rc <= 44; rc++) {
1430 min_mv = max_mv * (rc) / 44;
1431 if (min_mv >= cfilt_mv) {
1432 rc -= 4;
1433 break;
1434 }
1435 }
1436done:
1437 return rc;
1438}
1439
1440static bool tabla_is_hph_pa_on(struct snd_soc_codec *codec)
1441{
1442 u8 hph_reg_val = 0;
1443 hph_reg_val = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_EN);
1444
1445 return (hph_reg_val & 0x30) ? true : false;
1446}
1447
Joonwoo Parka9444452011-12-08 18:48:27 -08001448static bool tabla_is_hph_dac_on(struct snd_soc_codec *codec, int left)
1449{
1450 u8 hph_reg_val = 0;
1451 if (left)
1452 hph_reg_val = snd_soc_read(codec,
1453 TABLA_A_RX_HPH_L_DAC_CTL);
1454 else
1455 hph_reg_val = snd_soc_read(codec,
1456 TABLA_A_RX_HPH_R_DAC_CTL);
1457
1458 return (hph_reg_val & 0xC0) ? true : false;
1459}
1460
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001461static void tabla_codec_switch_micbias(struct snd_soc_codec *codec,
1462 int vddio_switch)
1463{
1464 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1465 int cfilt_k_val;
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001466 bool mbhc_was_polling = false;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001467
1468 switch (vddio_switch) {
1469 case 1:
1470 if (tabla->mbhc_polling_active) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001471
1472 tabla_codec_pause_hs_polling(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08001473 /* VDDIO switch enabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001474 tabla->cfilt_k_value = snd_soc_read(codec,
1475 tabla->mbhc_bias_regs.cfilt_val);
1476 cfilt_k_val = tabla_find_k_value(
1477 tabla->pdata->micbias.ldoh_v, 1800);
1478 snd_soc_update_bits(codec,
1479 tabla->mbhc_bias_regs.cfilt_val,
1480 0xFC, (cfilt_k_val << 2));
1481
1482 snd_soc_update_bits(codec,
1483 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x80);
1484 snd_soc_update_bits(codec,
1485 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001486 tabla_codec_start_hs_polling(codec);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001487
1488 tabla->mbhc_micbias_switched = true;
Joonwoo Park0976d012011-12-22 11:48:18 -08001489 pr_debug("%s: VDDIO switch enabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001490 }
1491 break;
1492
1493 case 0:
1494 if (tabla->mbhc_micbias_switched) {
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001495 if (tabla->mbhc_polling_active) {
1496 tabla_codec_pause_hs_polling(codec);
1497 mbhc_was_polling = true;
1498 }
Joonwoo Park0976d012011-12-22 11:48:18 -08001499 /* VDDIO switch disabled */
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001500 if (tabla->cfilt_k_value != 0)
1501 snd_soc_update_bits(codec,
1502 tabla->mbhc_bias_regs.cfilt_val, 0XFC,
1503 tabla->cfilt_k_value);
1504 snd_soc_update_bits(codec,
1505 tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
1506 snd_soc_update_bits(codec,
1507 tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
1508
Bhalchandra Gajarec1e19c42011-11-18 11:22:56 -08001509 if (mbhc_was_polling)
1510 tabla_codec_start_hs_polling(codec);
1511
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001512 tabla->mbhc_micbias_switched = false;
Joonwoo Park0976d012011-12-22 11:48:18 -08001513 pr_debug("%s: VDDIO switch disabled\n", __func__);
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001514 }
1515 break;
1516 }
1517}
1518
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001519static int tabla_codec_enable_micbias(struct snd_soc_dapm_widget *w,
1520 struct snd_kcontrol *kcontrol, int event)
1521{
1522 struct snd_soc_codec *codec = w->codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07001523 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1524 u16 micb_int_reg;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001525 int micb_line;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001526 u8 cfilt_sel_val = 0;
Bradley Rubin229c6a52011-07-12 16:18:48 -07001527 char *internal1_text = "Internal1";
1528 char *internal2_text = "Internal2";
1529 char *internal3_text = "Internal3";
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001530
1531 pr_debug("%s %d\n", __func__, event);
1532 switch (w->reg) {
1533 case TABLA_A_MICB_1_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534 micb_int_reg = TABLA_A_MICB_1_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001535 cfilt_sel_val = tabla->pdata->micbias.bias1_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001536 micb_line = TABLA_MICBIAS1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001537 break;
1538 case TABLA_A_MICB_2_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001539 micb_int_reg = TABLA_A_MICB_2_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001540 cfilt_sel_val = tabla->pdata->micbias.bias2_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001541 micb_line = TABLA_MICBIAS2;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001542 break;
1543 case TABLA_A_MICB_3_CTL:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544 micb_int_reg = TABLA_A_MICB_3_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001545 cfilt_sel_val = tabla->pdata->micbias.bias3_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001546 micb_line = TABLA_MICBIAS3;
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001547 break;
1548 case TABLA_A_MICB_4_CTL:
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001549 micb_int_reg = TABLA_A_MICB_4_INT_RBIAS;
Patrick Lai3043fba2011-08-01 14:15:57 -07001550 cfilt_sel_val = tabla->pdata->micbias.bias4_cfilt_sel;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001551 micb_line = TABLA_MICBIAS4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552 break;
1553 default:
1554 pr_err("%s: Error, invalid micbias register\n", __func__);
1555 return -EINVAL;
1556 }
1557
1558 switch (event) {
1559 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001560 /* Decide whether to switch the micbias for MBHC */
1561 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1562 && tabla->mbhc_micbias_switched)
1563 tabla_codec_switch_micbias(codec, 0);
1564
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07001565 snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
Patrick Lai3043fba2011-08-01 14:15:57 -07001566 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001567
1568 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001569 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001570 else if (strnstr(w->name, internal2_text, 30))
1571 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
1572 else if (strnstr(w->name, internal3_text, 30))
1573 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
1574
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001575 break;
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001576 case SND_SOC_DAPM_POST_PMU:
1577 if (tabla->mbhc_polling_active &&
Joonwoo Park0976d012011-12-22 11:48:18 -08001578 tabla->micbias == micb_line) {
Bradley Rubin4d09cf42011-08-17 17:59:16 -07001579 tabla_codec_pause_hs_polling(codec);
1580 tabla_codec_start_hs_polling(codec);
1581 }
1582 break;
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001583
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001585
1586 if ((w->reg == tabla->mbhc_bias_regs.ctl_reg)
1587 && tabla_is_hph_pa_on(codec))
1588 tabla_codec_switch_micbias(codec, 1);
1589
Bradley Rubin229c6a52011-07-12 16:18:48 -07001590 if (strnstr(w->name, internal1_text, 30))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001591 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
Bradley Rubin229c6a52011-07-12 16:18:48 -07001592 else if (strnstr(w->name, internal2_text, 30))
1593 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
1594 else if (strnstr(w->name, internal3_text, 30))
1595 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
1596
Patrick Lai3043fba2011-08-01 14:15:57 -07001597 tabla_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001598 break;
1599 }
1600
1601 return 0;
1602}
1603
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001604static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
1605 struct snd_kcontrol *kcontrol, int event)
1606{
1607 struct snd_soc_codec *codec = w->codec;
1608 u16 dec_reset_reg;
1609
1610 pr_debug("%s %d\n", __func__, event);
1611
1612 if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
1613 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
1614 else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
1615 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B2_CTL;
1616 else {
1617 pr_err("%s: Error, incorrect dec\n", __func__);
1618 return -EINVAL;
1619 }
1620
1621 switch (event) {
1622 case SND_SOC_DAPM_PRE_PMU:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001623 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1624 1 << w->shift);
1625 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
1626 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001627 }
1628 return 0;
1629}
1630
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001631static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001632 struct snd_kcontrol *kcontrol, int event)
1633{
1634 struct snd_soc_codec *codec = w->codec;
1635
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001636 pr_debug("%s %d %s\n", __func__, event, w->name);
1637
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001638 switch (event) {
1639 case SND_SOC_DAPM_PRE_PMU:
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001640 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1641 1 << w->shift, 1 << w->shift);
1642 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1643 1 << w->shift, 0x0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001644 break;
1645 }
1646 return 0;
1647}
1648
Bradley Rubin229c6a52011-07-12 16:18:48 -07001649static int tabla_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
1650 struct snd_kcontrol *kcontrol, int event)
1651{
1652 switch (event) {
1653 case SND_SOC_DAPM_POST_PMU:
1654 case SND_SOC_DAPM_POST_PMD:
1655 usleep_range(1000, 1000);
1656 break;
1657 }
1658 return 0;
1659}
1660
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001661
1662static void tabla_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
1663{
1664 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1665
1666 if (enable) {
1667 tabla->rx_bias_count++;
1668 if (tabla->rx_bias_count == 1)
1669 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1670 0x80, 0x80);
1671 } else {
1672 tabla->rx_bias_count--;
1673 if (!tabla->rx_bias_count)
1674 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS,
1675 0x80, 0x00);
1676 }
1677}
1678
1679static int tabla_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1680 struct snd_kcontrol *kcontrol, int event)
1681{
1682 struct snd_soc_codec *codec = w->codec;
1683
1684 pr_debug("%s %d\n", __func__, event);
1685
1686 switch (event) {
1687 case SND_SOC_DAPM_PRE_PMU:
1688 tabla_enable_rx_bias(codec, 1);
1689 break;
1690 case SND_SOC_DAPM_POST_PMD:
1691 tabla_enable_rx_bias(codec, 0);
1692 break;
1693 }
1694 return 0;
1695}
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001696static int tabla_hphr_dac_event(struct snd_soc_dapm_widget *w,
1697 struct snd_kcontrol *kcontrol, int event)
1698{
1699 struct snd_soc_codec *codec = w->codec;
1700
1701 pr_debug("%s %s %d\n", __func__, w->name, event);
1702
1703 switch (event) {
1704 case SND_SOC_DAPM_PRE_PMU:
1705 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1706 break;
1707 case SND_SOC_DAPM_POST_PMD:
1708 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1709 break;
1710 }
1711 return 0;
1712}
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07001713
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001714static void tabla_snd_soc_jack_report(struct tabla_priv *tabla,
1715 struct snd_soc_jack *jack, int status,
1716 int mask)
1717{
1718 /* XXX: wake_lock_timeout()? */
1719 snd_soc_jack_report(jack, status, mask);
1720}
1721
Patrick Lai49efeac2011-11-03 11:01:12 -07001722static void hphocp_off_report(struct tabla_priv *tabla,
1723 u32 jack_status, int irq)
1724{
1725 struct snd_soc_codec *codec;
1726
1727 if (tabla) {
1728 pr_info("%s: clear ocp status %x\n", __func__, jack_status);
1729 codec = tabla->codec;
1730 tabla->hph_status &= ~jack_status;
1731 if (tabla->headset_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08001732 tabla_snd_soc_jack_report(tabla, tabla->headset_jack,
1733 tabla->hph_status,
1734 TABLA_JACK_MASK);
Joonwoo Park0976d012011-12-22 11:48:18 -08001735 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x00);
1736 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10, 0x10);
Patrick Laic7cae882011-11-18 11:52:49 -08001737 /* reset retry counter as PA is turned off signifying
1738 * start of new OCP detection session
1739 */
1740 if (TABLA_IRQ_HPH_PA_OCPL_FAULT)
1741 tabla->hphlocp_cnt = 0;
1742 else
1743 tabla->hphrocp_cnt = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07001744 tabla_enable_irq(codec->control_data, irq);
1745 } else {
1746 pr_err("%s: Bad tabla private data\n", __func__);
1747 }
1748}
1749
1750static void hphlocp_off_report(struct work_struct *work)
1751{
1752 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1753 hphlocp_work);
1754 hphocp_off_report(tabla, SND_JACK_OC_HPHL, TABLA_IRQ_HPH_PA_OCPL_FAULT);
1755}
1756
1757static void hphrocp_off_report(struct work_struct *work)
1758{
1759 struct tabla_priv *tabla = container_of(work, struct tabla_priv,
1760 hphrocp_work);
1761 hphocp_off_report(tabla, SND_JACK_OC_HPHR, TABLA_IRQ_HPH_PA_OCPR_FAULT);
1762}
1763
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001764static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w,
1765 struct snd_kcontrol *kcontrol, int event)
1766{
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001767 struct snd_soc_codec *codec = w->codec;
1768 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1769 u8 mbhc_micb_ctl_val;
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001770 pr_debug("%s: event = %d\n", __func__, event);
1771
1772 switch (event) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001773 case SND_SOC_DAPM_PRE_PMU:
1774 mbhc_micb_ctl_val = snd_soc_read(codec,
1775 tabla->mbhc_bias_regs.ctl_reg);
1776
1777 if (!(mbhc_micb_ctl_val & 0x80)
1778 && !tabla->mbhc_micbias_switched)
1779 tabla_codec_switch_micbias(codec, 1);
1780
1781 break;
1782
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001783 case SND_SOC_DAPM_POST_PMD:
Patrick Lai49efeac2011-11-03 11:01:12 -07001784 /* schedule work is required because at the time HPH PA DAPM
1785 * event callback is called by DAPM framework, CODEC dapm mutex
1786 * would have been locked while snd_soc_jack_report also
1787 * attempts to acquire same lock.
1788 */
Joonwoo Parka9444452011-12-08 18:48:27 -08001789 if (w->shift == 5) {
1790 clear_bit(TABLA_HPHL_PA_OFF_ACK,
1791 &tabla->hph_pa_dac_state);
1792 clear_bit(TABLA_HPHL_DAC_OFF_ACK,
1793 &tabla->hph_pa_dac_state);
1794 if (tabla->hph_status & SND_JACK_OC_HPHL)
1795 schedule_work(&tabla->hphlocp_work);
1796 } else if (w->shift == 4) {
1797 clear_bit(TABLA_HPHR_PA_OFF_ACK,
1798 &tabla->hph_pa_dac_state);
1799 clear_bit(TABLA_HPHR_DAC_OFF_ACK,
1800 &tabla->hph_pa_dac_state);
1801 if (tabla->hph_status & SND_JACK_OC_HPHR)
1802 schedule_work(&tabla->hphrocp_work);
1803 }
1804
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001805 if (tabla->mbhc_micbias_switched)
1806 tabla_codec_switch_micbias(codec, 0);
1807
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001808 pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
1809 w->name);
1810 usleep_range(10000, 10000);
1811
1812 break;
1813 }
1814 return 0;
1815}
1816
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001817static void tabla_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
1818 struct mbhc_micbias_regs *micbias_regs)
1819{
1820 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001821 unsigned int cfilt;
1822
Joonwoo Park0976d012011-12-22 11:48:18 -08001823 switch (tabla->micbias) {
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001824 case TABLA_MICBIAS1:
1825 cfilt = tabla->pdata->micbias.bias1_cfilt_sel;
1826 micbias_regs->mbhc_reg = TABLA_A_MICB_1_MBHC;
1827 micbias_regs->int_rbias = TABLA_A_MICB_1_INT_RBIAS;
1828 micbias_regs->ctl_reg = TABLA_A_MICB_1_CTL;
1829 break;
1830 case TABLA_MICBIAS2:
1831 cfilt = tabla->pdata->micbias.bias2_cfilt_sel;
1832 micbias_regs->mbhc_reg = TABLA_A_MICB_2_MBHC;
1833 micbias_regs->int_rbias = TABLA_A_MICB_2_INT_RBIAS;
1834 micbias_regs->ctl_reg = TABLA_A_MICB_2_CTL;
1835 break;
1836 case TABLA_MICBIAS3:
1837 cfilt = tabla->pdata->micbias.bias3_cfilt_sel;
1838 micbias_regs->mbhc_reg = TABLA_A_MICB_3_MBHC;
1839 micbias_regs->int_rbias = TABLA_A_MICB_3_INT_RBIAS;
1840 micbias_regs->ctl_reg = TABLA_A_MICB_3_CTL;
1841 break;
1842 case TABLA_MICBIAS4:
1843 cfilt = tabla->pdata->micbias.bias4_cfilt_sel;
1844 micbias_regs->mbhc_reg = TABLA_A_MICB_4_MBHC;
1845 micbias_regs->int_rbias = TABLA_A_MICB_4_INT_RBIAS;
1846 micbias_regs->ctl_reg = TABLA_A_MICB_4_CTL;
1847 break;
1848 default:
1849 /* Should never reach here */
1850 pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
Jordan Crouse239d8412011-11-23 11:47:02 -07001851 return;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001852 }
1853
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08001854 micbias_regs->cfilt_sel = cfilt;
1855
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001856 switch (cfilt) {
1857 case TABLA_CFILT1_SEL:
1858 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_1_VAL;
1859 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_1_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001860 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt1_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001861 break;
1862 case TABLA_CFILT2_SEL:
1863 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_2_VAL;
1864 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_2_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001865 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt2_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001866 break;
1867 case TABLA_CFILT3_SEL:
1868 micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_3_VAL;
1869 micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_3_CTL;
Joonwoo Park0976d012011-12-22 11:48:18 -08001870 tabla->mbhc_data.micb_mv = tabla->pdata->micbias.cfilt3_mv;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001871 break;
1872 }
1873}
Santosh Mardie15e2302011-11-15 10:39:23 +05301874static const struct snd_soc_dapm_widget tabla_dapm_i2s_widgets[] = {
1875 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TABLA_A_CDC_CLK_RX_I2S_CTL,
1876 4, 0, NULL, 0),
1877 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TABLA_A_CDC_CLK_TX_I2S_CTL, 4,
1878 0, NULL, 0),
1879};
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07001880
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001881static int tabla_lineout_dac_event(struct snd_soc_dapm_widget *w,
1882 struct snd_kcontrol *kcontrol, int event)
1883{
1884 struct snd_soc_codec *codec = w->codec;
1885
1886 pr_debug("%s %s %d\n", __func__, w->name, event);
1887
1888 switch (event) {
1889 case SND_SOC_DAPM_PRE_PMU:
1890 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1891 break;
1892
1893 case SND_SOC_DAPM_POST_PMD:
1894 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1895 break;
1896 }
1897 return 0;
1898}
1899
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
1901 /*RX stuff */
1902 SND_SOC_DAPM_OUTPUT("EAR"),
1903
Kiran Kandid2d86b52011-09-09 17:44:28 -07001904 SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001905
Bradley Rubin229c6a52011-07-12 16:18:48 -07001906 SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
1907 ARRAY_SIZE(dac1_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001908
Bradley Rubin229c6a52011-07-12 16:18:48 -07001909 SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1910 SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Santosh Mardie15e2302011-11-15 10:39:23 +05301911 SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1912 SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001913
1914 /* Headphone */
1915 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001916 SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001917 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1918 SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07001919 SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
1920 hphl_switch, ARRAY_SIZE(hphl_switch)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001921
Kiran Kandibf0b1ff2011-09-15 13:55:21 -07001922 SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07001923 tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
1924 SND_SOC_DAPM_POST_PMD),
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001925
1926 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
1927 tabla_hphr_dac_event,
1928 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001929
1930 /* Speaker */
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001931 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
1932 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
1933 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
1934 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
1935 SND_SOC_DAPM_OUTPUT("LINEOUT5"),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001936
Kiran Kandidb0a4b02011-08-23 09:32:09 -07001937 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
1938 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1939 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1940 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
1941 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1942 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1943 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
1944 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1945 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1946 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
1947 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1948 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1949 SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001950 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
1951 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001952
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001953 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
1954 , tabla_lineout_dac_event,
1955 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1956 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
1957 , tabla_lineout_dac_event,
1958 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1959 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
1960 , tabla_lineout_dac_event,
1961 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1962 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
1963 &lineout3_ground_switch),
1964 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
1965 , tabla_lineout_dac_event,
1966 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1967 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
1968 &lineout4_ground_switch),
1969 SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
1970 , tabla_lineout_dac_event,
1971 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001972
Bradley Rubin229c6a52011-07-12 16:18:48 -07001973 SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
1974 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1975 SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
1976 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1977 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
1978 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1979 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
1980 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1981 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
1982 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
1983 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
1984 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07001985 SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
1986 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07001987
Kiran Kandi8b3a8302011-09-27 16:13:28 -07001988
1989 SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
1990 &rx4_dsm_mux, tabla_codec_reset_interpolator,
1991 SND_SOC_DAPM_PRE_PMU),
1992
1993 SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
1994 &rx6_dsm_mux, tabla_codec_reset_interpolator,
1995 SND_SOC_DAPM_PRE_PMU),
1996
Bradley Rubin229c6a52011-07-12 16:18:48 -07001997 SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
1998 SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
1999
2000 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2001 &rx_mix1_inp1_mux),
2002 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2003 &rx_mix1_inp2_mux),
2004 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2005 &rx2_mix1_inp1_mux),
2006 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2007 &rx2_mix1_inp2_mux),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002008 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2009 &rx3_mix1_inp1_mux),
2010 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2011 &rx3_mix1_inp2_mux),
2012 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2013 &rx4_mix1_inp1_mux),
2014 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2015 &rx4_mix1_inp2_mux),
2016 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2017 &rx5_mix1_inp1_mux),
2018 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2019 &rx5_mix1_inp2_mux),
2020 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2021 &rx6_mix1_inp1_mux),
2022 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2023 &rx6_mix1_inp2_mux),
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002024 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2025 &rx7_mix1_inp1_mux),
2026 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2027 &rx7_mix1_inp2_mux),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002028
Bradley Rubin229c6a52011-07-12 16:18:48 -07002029 SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
2030 tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
2031 SND_SOC_DAPM_PRE_PMD),
2032
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002033 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
2034 tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
2035 SND_SOC_DAPM_POST_PMD),
2036
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002037 /* TX */
Bradley Rubin229c6a52011-07-12 16:18:48 -07002038
Bradley Rubine1d08622011-07-20 18:01:35 -07002039 SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
2040 0),
2041
Bradley Rubin229c6a52011-07-12 16:18:48 -07002042 SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
2043 tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
2044
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002045 SND_SOC_DAPM_INPUT("AMIC1"),
2046 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
2047 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002048 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002049 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
2050 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002051 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002052 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002053 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002054 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002055 SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
2056 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2057 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2058
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002059 SND_SOC_DAPM_INPUT("AMIC3"),
2060 SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
2061 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2062 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2063
2064 SND_SOC_DAPM_INPUT("AMIC4"),
2065 SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
2066 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2067 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2068
2069 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_A_MICB_4_CTL, 7, 0,
2070 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002071 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002072
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002073 SND_SOC_DAPM_INPUT("AMIC5"),
2074 SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
2075 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2076
2077 SND_SOC_DAPM_INPUT("AMIC6"),
2078 SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
2079 tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
2080
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002081 SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002082 &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002083
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002084 SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002085 &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002086
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002087 SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002088 &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002089
2090 SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002091 &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002092
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002093 SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002094 &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002095
2096 SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002097 &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002098
2099 SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002100 &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002101
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002102 SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002103 &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002104
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002105 SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002106 &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002107
2108 SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
Bradley Rubine1d08622011-07-20 18:01:35 -07002109 &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002110
Bradley Rubin229c6a52011-07-12 16:18:48 -07002111 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
2112 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
2113
2114 SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
2115 tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
2116 SND_SOC_DAPM_POST_PMD),
2117
2118 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
2119
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002120 SND_SOC_DAPM_INPUT("AMIC2"),
2121 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
2122 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002123 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002124 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
2125 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002126 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002127 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
2128 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002129 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002130 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002131 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002132 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002133 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
2134 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002135 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002136 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
2137 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002138 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin229c6a52011-07-12 16:18:48 -07002139 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002140 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
Bradley Rubin4d09cf42011-08-17 17:59:16 -07002141 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002142 SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
2143 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2144 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2145
2146 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
2147 SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
2148 0, 0),
2149
2150 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
2151 SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
2152 4, 0),
2153
2154 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
2155 SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
2156 5, 0),
2157
2158 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
2159 SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
2160 0, 0),
2161
2162 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
2163 SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
2164 0, 0),
2165
Kiran Kandi3426e512011-09-13 22:50:10 -07002166 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
2167 SND_SOC_DAPM_AIF_OUT("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
2168 0, 0),
2169
2170 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
2171 SND_SOC_DAPM_AIF_OUT("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
2172 0, 0),
2173
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002174 /* Digital Mic Inputs */
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002175 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
2176 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2177 SND_SOC_DAPM_POST_PMD),
2178
2179 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
2180 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2181 SND_SOC_DAPM_POST_PMD),
2182
2183 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
2184 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2185 SND_SOC_DAPM_POST_PMD),
2186
2187 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
2188 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2189 SND_SOC_DAPM_POST_PMD),
2190
2191 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
2192 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2193 SND_SOC_DAPM_POST_PMD),
2194
2195 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
2196 tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2197 SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002198
2199 /* Sidetone */
2200 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
2201 SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
2202};
2203
Santosh Mardie15e2302011-11-15 10:39:23 +05302204static const struct snd_soc_dapm_route audio_i2s_map[] = {
2205 {"RX_I2S_CLK", NULL, "CDC_CONN"},
2206 {"SLIM RX1", NULL, "RX_I2S_CLK"},
2207 {"SLIM RX2", NULL, "RX_I2S_CLK"},
2208 {"SLIM RX3", NULL, "RX_I2S_CLK"},
2209 {"SLIM RX4", NULL, "RX_I2S_CLK"},
2210
2211 {"SLIM TX7", NULL, "TX_I2S_CLK"},
2212 {"SLIM TX8", NULL, "TX_I2S_CLK"},
2213 {"SLIM TX9", NULL, "TX_I2S_CLK"},
2214 {"SLIM TX10", NULL, "TX_I2S_CLK"},
2215};
2216
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002217static const struct snd_soc_dapm_route audio_map[] = {
2218 /* SLIMBUS Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002219
2220 {"SLIM TX1", NULL, "SLIM TX1 MUX"},
2221 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
2222
2223 {"SLIM TX5", NULL, "SLIM TX5 MUX"},
2224 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
2225
2226 {"SLIM TX6", NULL, "SLIM TX6 MUX"},
2227 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
2228
2229 {"SLIM TX7", NULL, "SLIM TX7 MUX"},
2230 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002231 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002232 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
2233 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002234 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
2235 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
Bhalchandra Gajare0d77e1b2011-07-08 10:54:14 -07002236 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
2237 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002238 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
2239 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002240
2241 {"SLIM TX8", NULL, "SLIM TX8 MUX"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002242 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
2243 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
2244 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
Bhalchandra Gajare9ec83cd2011-09-23 17:25:07 -07002245 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002246 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
2247 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
2248
Kiran Kandi3426e512011-09-13 22:50:10 -07002249 {"SLIM TX9", NULL, "SLIM TX9 MUX"},
2250 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
2251 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
2252 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
2253 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
2254 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
2255 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
2256 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
2257 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
2258 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
2259 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
2260
2261 {"SLIM TX10", NULL, "SLIM TX10 MUX"},
2262 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
2263 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
2264 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
2265 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
2266 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
2267 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
2268 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
2269 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
2270 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
2271 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
2272
2273
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002274 /* Earpiece (RX MIX1) */
2275 {"EAR", NULL, "EAR PA"},
Kiran Kandiac034ac2011-07-29 16:39:08 -07002276 {"EAR PA", NULL, "DAC1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002277 {"DAC1", NULL, "CP"},
2278
2279 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX1"},
2280 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX1"},
2281 {"ANC", NULL, "ANC1 FB MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002282
2283 /* Headset (RX MIX1 and RX MIX2) */
2284 {"HEADPHONE", NULL, "HPHL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002285 {"HEADPHONE", NULL, "HPHR"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002286
2287 {"HPHL", NULL, "HPHL DAC"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002288 {"HPHR", NULL, "HPHR DAC"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002289
2290 {"HPHL DAC", NULL, "CP"},
2291 {"HPHR DAC", NULL, "CP"},
2292
2293 {"ANC", NULL, "ANC1 MUX"},
2294 {"ANC", NULL, "ANC2 MUX"},
2295 {"ANC1 MUX", "ADC1", "ADC1"},
2296 {"ANC1 MUX", "ADC2", "ADC2"},
2297 {"ANC1 MUX", "ADC3", "ADC3"},
2298 {"ANC1 MUX", "ADC4", "ADC4"},
2299 {"ANC2 MUX", "ADC1", "ADC1"},
2300 {"ANC2 MUX", "ADC2", "ADC2"},
2301 {"ANC2 MUX", "ADC3", "ADC3"},
2302 {"ANC2 MUX", "ADC4", "ADC4"},
2303
Bradley Rubine1d08622011-07-20 18:01:35 -07002304 {"ANC", NULL, "CDC_CONN"},
2305
Bradley Rubin229c6a52011-07-12 16:18:48 -07002306 {"DAC1", "Switch", "RX1 CHAIN"},
2307 {"HPHL DAC", "Switch", "RX1 CHAIN"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002308 {"HPHR DAC", NULL, "RX2 CHAIN"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002309
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002310 {"LINEOUT1", NULL, "LINEOUT1 PA"},
2311 {"LINEOUT2", NULL, "LINEOUT2 PA"},
2312 {"LINEOUT3", NULL, "LINEOUT3 PA"},
2313 {"LINEOUT4", NULL, "LINEOUT4 PA"},
2314 {"LINEOUT5", NULL, "LINEOUT5 PA"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002315
Kiran Kandidb0a4b02011-08-23 09:32:09 -07002316 {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
2317 {"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
2318 {"LINEOUT3 PA", NULL, "LINEOUT3 DAC"},
2319 {"LINEOUT4 PA", NULL, "LINEOUT4 DAC"},
2320 {"LINEOUT5 PA", NULL, "LINEOUT5 DAC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002321
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002322 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
2323 {"LINEOUT5 DAC", NULL, "RX7 MIX1"},
2324
Bradley Rubin229c6a52011-07-12 16:18:48 -07002325 {"RX1 CHAIN", NULL, "RX1 MIX1"},
2326 {"RX2 CHAIN", NULL, "RX2 MIX1"},
2327 {"RX1 CHAIN", NULL, "ANC"},
2328 {"RX2 CHAIN", NULL, "ANC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002329
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002330 {"CP", NULL, "RX_BIAS"},
2331 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
2332 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
2333 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
2334 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002335 {"LINEOUT5 DAC", NULL, "RX_BIAS"},
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002336
Bradley Rubin229c6a52011-07-12 16:18:48 -07002337 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
2338 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
2339 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
2340 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002341 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
2342 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
2343 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
2344 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
2345 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
2346 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
2347 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
2348 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002349 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
2350 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -07002351
Bradley Rubin229c6a52011-07-12 16:18:48 -07002352 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
2353 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302354 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
2355 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002356 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
2357 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
2358 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302359 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
2360 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002361 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
2362 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
2363 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302364 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
2365 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002366 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002367 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
2368 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302369 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
2370 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002371 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002372 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
2373 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302374 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
2375 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002376 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002377 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
2378 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302379 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
2380 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002381 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002382 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
2383 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302384 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
2385 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002386 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002387 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
2388 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302389 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
2390 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002391 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002392 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
2393 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302394 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
2395 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002396 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002397 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
2398 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302399 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
2400 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002401 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002402 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
2403 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302404 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
2405 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002406 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002407 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
2408 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302409 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
2410 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002411 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002412 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
2413 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302414 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
2415 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002416 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Bhalchandra Gajare0a8ad172011-08-12 13:32:22 -07002417 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
2418 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
Santosh Mardie15e2302011-11-15 10:39:23 +05302419 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
2420 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
Patrick Lai16261e82011-09-30 13:25:52 -07002421 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002422
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002423 /* Decimator Inputs */
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002424 {"DEC1 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002425 {"DEC1 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002426 {"DEC1 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002427 {"DEC2 MUX", "DMIC2", "DMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002428 {"DEC2 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002429 {"DEC2 MUX", NULL, "CDC_CONN"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002430 {"DEC3 MUX", "DMIC3", "DMIC3"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002431 {"DEC3 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002432 {"DEC3 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002433 {"DEC4 MUX", "DMIC4", "DMIC4"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002434 {"DEC4 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002435 {"DEC4 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002436 {"DEC5 MUX", "DMIC5", "DMIC5"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002437 {"DEC5 MUX", "ADC2", "ADC2"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002438 {"DEC5 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajare7cf018e2011-08-11 18:58:32 -07002439 {"DEC6 MUX", "DMIC6", "DMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002440 {"DEC6 MUX", "ADC1", "ADC1"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002441 {"DEC6 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002442 {"DEC7 MUX", "DMIC1", "DMIC1"},
Kiran Kandicf45f6a2011-07-17 21:10:19 -07002443 {"DEC7 MUX", "ADC6", "ADC6"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002444 {"DEC7 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002445 {"DEC8 MUX", "ADC5", "ADC5"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002446 {"DEC8 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002447 {"DEC9 MUX", "ADC3", "ADC3"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002448 {"DEC9 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002449 {"DEC10 MUX", "ADC4", "ADC4"},
Bradley Rubine1d08622011-07-20 18:01:35 -07002450 {"DEC10 MUX", NULL, "CDC_CONN"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002451
2452 /* ADC Connections */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002453 {"ADC1", NULL, "AMIC1"},
2454 {"ADC2", NULL, "AMIC2"},
Bhalchandra Gajarecc6ffa02011-07-14 18:35:41 -07002455 {"ADC3", NULL, "AMIC3"},
2456 {"ADC4", NULL, "AMIC4"},
2457 {"ADC5", NULL, "AMIC5"},
2458 {"ADC6", NULL, "AMIC6"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002459
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002460 {"IIR1", NULL, "IIR1 INP1 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002461 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
2462 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
2463 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
2464 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
2465 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
Patrick Lai16261e82011-09-30 13:25:52 -07002467 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
2468 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
2469 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
2470 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
Bradley Rubin229c6a52011-07-12 16:18:48 -07002471
2472 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
2473 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
2474 {"MIC BIAS1 External", NULL, "LDO_H"},
2475 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
2476 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
2477 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
2478 {"MIC BIAS2 External", NULL, "LDO_H"},
2479 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
2480 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
2481 {"MIC BIAS3 External", NULL, "LDO_H"},
2482 {"MIC BIAS4 External", NULL, "LDO_H"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002483};
2484
Kiran Kandi8b3a8302011-09-27 16:13:28 -07002485static const struct snd_soc_dapm_route tabla_1_x_lineout_2_to_4_map[] = {
2486
2487 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2488 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2489
2490 {"LINEOUT2 DAC", NULL, "RX4 DSM MUX"},
2491
2492 {"LINEOUT3 DAC", NULL, "RX5 MIX1"},
2493 {"LINEOUT3 DAC GROUND", "Switch", "RX3 MIX1"},
2494 {"LINEOUT3 DAC", NULL, "LINEOUT3 DAC GROUND"},
2495
2496 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2497 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2498
2499 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2500 {"LINEOUT4 DAC GROUND", "Switch", "RX4 DSM MUX"},
2501 {"LINEOUT4 DAC", NULL, "LINEOUT4 DAC GROUND"},
2502};
2503
Kiran Kandi7a9fd902011-11-14 13:51:45 -08002504
2505static const struct snd_soc_dapm_route tabla_2_x_lineout_2_to_4_map[] = {
2506
2507 {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
2508 {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
2509
2510 {"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
2511
2512 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
2513
2514 {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
2515 {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
2516
2517 {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
2518};
2519
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002520static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
2521{
2522 return tabla_reg_readable[reg];
2523}
2524
2525static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
2526{
2527 /* Registers lower than 0x100 are top level registers which can be
2528 * written by the Tabla core driver.
2529 */
2530
2531 if ((reg >= TABLA_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
2532 return 1;
2533
Ben Romberger1f045a72011-11-04 10:14:57 -07002534 /* IIR Coeff registers are not cacheable */
2535 if ((reg >= TABLA_A_CDC_IIR1_COEF_B1_CTL) &&
2536 (reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
2537 return 1;
2538
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002539 return 0;
2540}
2541
2542#define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
2543static int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
2544 unsigned int value)
2545{
2546 int ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002547
2548 BUG_ON(reg > TABLA_MAX_REGISTER);
2549
2550 if (!tabla_volatile(codec, reg)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002551 ret = snd_soc_cache_write(codec, reg, value);
2552 if (ret != 0)
2553 dev_err(codec->dev, "Cache write to %x failed: %d\n",
2554 reg, ret);
2555 }
2556
2557 return tabla_reg_write(codec->control_data, reg, value);
2558}
2559static unsigned int tabla_read(struct snd_soc_codec *codec,
2560 unsigned int reg)
2561{
2562 unsigned int val;
2563 int ret;
2564
2565 BUG_ON(reg > TABLA_MAX_REGISTER);
2566
2567 if (!tabla_volatile(codec, reg) && tabla_readable(codec, reg) &&
2568 reg < codec->driver->reg_cache_size) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002569 ret = snd_soc_cache_read(codec, reg, &val);
2570 if (ret >= 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002571 return val;
2572 } else
2573 dev_err(codec->dev, "Cache read from %x failed: %d\n",
2574 reg, ret);
2575 }
2576
2577 val = tabla_reg_read(codec->control_data, reg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002578 return val;
2579}
2580
2581static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
2582{
2583 snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
2584 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2585 0x80);
2586 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
2587 0x04);
2588 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
2589 0x01);
2590 usleep_range(1000, 1000);
2591 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2592 0x00);
2593}
2594
2595static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
2596 enum tabla_bandgap_type choice)
2597{
2598 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2599
2600 /* TODO lock resources accessed by audio streams and threaded
2601 * interrupt handlers
2602 */
2603
2604 pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
2605 tabla->bandgap_type);
2606
2607 if (tabla->bandgap_type == choice)
2608 return;
2609
2610 if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
2611 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2612 tabla_codec_enable_audio_mode_bandgap(codec);
2613 } else if ((tabla->bandgap_type == TABLA_BANDGAP_AUDIO_MODE) &&
2614 (choice == TABLA_BANDGAP_MBHC_MODE)) {
2615 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
2616 0x2);
2617 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2618 0x80);
2619 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
2620 0x4);
2621 usleep_range(1000, 1000);
2622 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
2623 0x00);
2624 } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
2625 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
2626 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2627 usleep_range(100, 100);
2628 tabla_codec_enable_audio_mode_bandgap(codec);
2629 } else if (choice == TABLA_BANDGAP_OFF) {
2630 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
2631 } else {
2632 pr_err("%s: Error, Invalid bandgap settings\n", __func__);
2633 }
2634 tabla->bandgap_type = choice;
2635}
2636
2637static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
2638 int enable)
2639{
2640 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2641
2642 if (enable) {
2643 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
2644 snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
2645 usleep_range(5, 5);
2646 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
2647 0x80);
2648 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
2649 0x80);
2650 usleep_range(10, 10);
2651 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
2652 usleep_range(20, 20);
2653 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
2654 } else {
2655 snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
2656 0);
2657 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
2658 }
2659 tabla->config_mode_active = enable ? true : false;
2660
2661 return 0;
2662}
2663
2664static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
2665 int config_mode)
2666{
2667 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2668
2669 pr_debug("%s\n", __func__);
2670
2671 if (config_mode) {
2672 tabla_codec_enable_config_mode(codec, 1);
2673 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
2674 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2675 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
2676 usleep_range(1000, 1000);
2677 } else
2678 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
2679
2680 if (!config_mode && tabla->mbhc_polling_active) {
2681 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
2682 tabla_codec_enable_config_mode(codec, 0);
2683
2684 }
2685
2686 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
2687 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
2688 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
2689 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
2690 usleep_range(50, 50);
2691 tabla->clock_active = true;
2692 return 0;
2693}
2694static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
2695{
2696 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2697 pr_debug("%s\n", __func__);
2698 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
2699 ndelay(160);
2700 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
2701 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
2702 tabla->clock_active = false;
2703}
2704
Bradley Rubincb1e2732011-06-23 16:49:20 -07002705static void tabla_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
2706{
Joonwoo Park0976d012011-12-22 11:48:18 -08002707 u8 *n_cic;
2708 struct tabla_mbhc_btn_detect_cfg *btn_det;
2709 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002710
Joonwoo Park0976d012011-12-22 11:48:18 -08002711 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002712
Joonwoo Park0976d012011-12-22 11:48:18 -08002713 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
2714 tabla->mbhc_data.v_ins_hu & 0xFF);
2715 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
2716 (tabla->mbhc_data.v_ins_hu >> 8) & 0xFF);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002717
Joonwoo Park0976d012011-12-22 11:48:18 -08002718 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
2719 tabla->mbhc_data.v_b1_hu & 0xFF);
2720 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
2721 (tabla->mbhc_data.v_b1_hu >> 8) & 0xFF);
2722
2723 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
2724 tabla->mbhc_data.v_b1_h & 0xFF);
2725 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
2726 (tabla->mbhc_data.v_b1_h >> 8) & 0xFF);
2727
2728 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL,
2729 tabla->mbhc_data.v_brh & 0xFF);
2730 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL,
2731 (tabla->mbhc_data.v_brh >> 8) & 0xFF);
2732
2733 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B11_CTL,
2734 tabla->mbhc_data.v_brl & 0xFF);
2735 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B12_CTL,
2736 (tabla->mbhc_data.v_brl >> 8) & 0xFF);
2737
2738 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL,
2739 tabla->mbhc_data.nready);
2740 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL,
2741 tabla->mbhc_data.npoll);
2742 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL,
2743 tabla->mbhc_data.nbounce_wait);
2744
2745 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
2746 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, n_cic[0]);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002747}
2748
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002749static int tabla_startup(struct snd_pcm_substream *substream,
2750 struct snd_soc_dai *dai)
2751{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002752 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2753 substream->name, substream->stream);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002754
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002755 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002756}
2757
2758static void tabla_shutdown(struct snd_pcm_substream *substream,
2759 struct snd_soc_dai *dai)
2760{
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002761 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
2762 substream->name, substream->stream);
2763}
2764
2765int tabla_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
2766{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002767 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
2768
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002769 pr_debug("%s() mclk_enable = %u\n", __func__, mclk_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002770
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002771 if (mclk_enable) {
2772 tabla->mclk_enabled = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002773
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002774 if (tabla->mbhc_polling_active && (tabla->mclk_enabled)) {
Bradley Rubincb1e2732011-06-23 16:49:20 -07002775 tabla_codec_pause_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002776 tabla_codec_enable_bandgap(codec,
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002777 TABLA_BANDGAP_AUDIO_MODE);
2778 tabla_codec_enable_clock_block(codec, 0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07002779 tabla_codec_calibrate_hs_polling(codec);
2780 tabla_codec_start_hs_polling(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002781 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002782 } else {
2783
2784 if (!tabla->mclk_enabled) {
2785 pr_err("Error, MCLK already diabled\n");
2786 return -EINVAL;
2787 }
2788 tabla->mclk_enabled = false;
2789
2790 if (tabla->mbhc_polling_active) {
2791 if (!tabla->mclk_enabled) {
2792 tabla_codec_pause_hs_polling(codec);
2793 tabla_codec_enable_bandgap(codec,
2794 TABLA_BANDGAP_MBHC_MODE);
2795 tabla_enable_rx_bias(codec, 1);
2796 tabla_codec_enable_clock_block(codec, 1);
2797 tabla_codec_calibrate_hs_polling(codec);
2798 tabla_codec_start_hs_polling(codec);
2799 }
2800 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1,
2801 0x05, 0x01);
2802 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002803 }
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07002804 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002805}
2806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002807static int tabla_set_dai_sysclk(struct snd_soc_dai *dai,
2808 int clk_id, unsigned int freq, int dir)
2809{
2810 pr_debug("%s\n", __func__);
2811 return 0;
2812}
2813
2814static int tabla_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2815{
Santosh Mardie15e2302011-11-15 10:39:23 +05302816 u8 val = 0;
2817 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
2818
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002819 pr_debug("%s\n", __func__);
Santosh Mardie15e2302011-11-15 10:39:23 +05302820 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2821 case SND_SOC_DAIFMT_CBS_CFS:
2822 /* CPU is master */
2823 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2824 if (dai->id == TABLA_TX_DAI_ID)
2825 snd_soc_update_bits(dai->codec,
2826 TABLA_A_CDC_CLK_TX_I2S_CTL,
2827 TABLA_I2S_MASTER_MODE_MASK, 0);
2828 else if (dai->id == TABLA_RX_DAI_ID)
2829 snd_soc_update_bits(dai->codec,
2830 TABLA_A_CDC_CLK_RX_I2S_CTL,
2831 TABLA_I2S_MASTER_MODE_MASK, 0);
2832 }
2833 break;
2834 case SND_SOC_DAIFMT_CBM_CFM:
2835 /* CPU is slave */
2836 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2837 val = TABLA_I2S_MASTER_MODE_MASK;
2838 if (dai->id == TABLA_TX_DAI_ID)
2839 snd_soc_update_bits(dai->codec,
2840 TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
2841 else if (dai->id == TABLA_RX_DAI_ID)
2842 snd_soc_update_bits(dai->codec,
2843 TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
2844 }
2845 break;
2846 default:
2847 return -EINVAL;
2848 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002849 return 0;
2850}
2851
2852static int tabla_hw_params(struct snd_pcm_substream *substream,
2853 struct snd_pcm_hw_params *params,
2854 struct snd_soc_dai *dai)
2855{
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002856 struct snd_soc_codec *codec = dai->codec;
Santosh Mardie15e2302011-11-15 10:39:23 +05302857 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
Bhalchandra Gajare038bf3a2011-09-02 15:32:30 -07002858 u8 path, shift;
2859 u16 tx_fs_reg, rx_fs_reg;
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002860 u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
2861
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002862 pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002863
2864 switch (params_rate(params)) {
2865 case 8000:
2866 tx_fs_rate = 0x00;
2867 rx_fs_rate = 0x00;
2868 break;
2869 case 16000:
2870 tx_fs_rate = 0x01;
2871 rx_fs_rate = 0x20;
2872 break;
2873 case 32000:
2874 tx_fs_rate = 0x02;
2875 rx_fs_rate = 0x40;
2876 break;
2877 case 48000:
2878 tx_fs_rate = 0x03;
2879 rx_fs_rate = 0x60;
2880 break;
2881 default:
2882 pr_err("%s: Invalid sampling rate %d\n", __func__,
2883 params_rate(params));
2884 return -EINVAL;
2885 }
2886
2887
2888 /**
2889 * If current dai is a tx dai, set sample rate to
2890 * all the txfe paths that are currently not active
2891 */
2892 if (dai->id == TABLA_TX_DAI_ID) {
2893
2894 tx_state = snd_soc_read(codec,
2895 TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
2896
2897 for (path = 1, shift = 0;
2898 path <= NUM_DECIMATORS; path++, shift++) {
2899
2900 if (path == BITS_PER_REG + 1) {
2901 shift = 0;
2902 tx_state = snd_soc_read(codec,
2903 TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL);
2904 }
2905
2906 if (!(tx_state & (1 << shift))) {
2907 tx_fs_reg = TABLA_A_CDC_TX1_CLK_FS_CTL
2908 + (BITS_PER_REG*(path-1));
2909 snd_soc_update_bits(codec, tx_fs_reg,
2910 0x03, tx_fs_rate);
2911 }
2912 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302913 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2914 switch (params_format(params)) {
2915 case SNDRV_PCM_FORMAT_S16_LE:
2916 snd_soc_update_bits(codec,
2917 TABLA_A_CDC_CLK_TX_I2S_CTL,
2918 0x20, 0x20);
2919 break;
2920 case SNDRV_PCM_FORMAT_S32_LE:
2921 snd_soc_update_bits(codec,
2922 TABLA_A_CDC_CLK_TX_I2S_CTL,
2923 0x20, 0x00);
2924 break;
2925 default:
2926 pr_err("invalid format\n");
2927 break;
2928 }
2929 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
2930 0x03, tx_fs_rate);
2931 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002932 }
2933
2934 /**
2935 * TODO: Need to handle case where same RX chain takes 2 or more inputs
2936 * with varying sample rates
2937 */
2938
2939 /**
2940 * If current dai is a rx dai, set sample rate to
2941 * all the rx paths that are currently not active
2942 */
2943 if (dai->id == TABLA_RX_DAI_ID) {
2944
2945 rx_state = snd_soc_read(codec,
2946 TABLA_A_CDC_CLK_RX_B1_CTL);
2947
2948 for (path = 1, shift = 0;
2949 path <= NUM_INTERPOLATORS; path++, shift++) {
2950
2951 if (!(rx_state & (1 << shift))) {
2952 rx_fs_reg = TABLA_A_CDC_RX1_B5_CTL
2953 + (BITS_PER_REG*(path-1));
2954 snd_soc_update_bits(codec, rx_fs_reg,
2955 0xE0, rx_fs_rate);
2956 }
2957 }
Santosh Mardie15e2302011-11-15 10:39:23 +05302958 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
2959 switch (params_format(params)) {
2960 case SNDRV_PCM_FORMAT_S16_LE:
2961 snd_soc_update_bits(codec,
2962 TABLA_A_CDC_CLK_RX_I2S_CTL,
2963 0x20, 0x20);
2964 break;
2965 case SNDRV_PCM_FORMAT_S32_LE:
2966 snd_soc_update_bits(codec,
2967 TABLA_A_CDC_CLK_RX_I2S_CTL,
2968 0x20, 0x00);
2969 break;
2970 default:
2971 pr_err("invalid format\n");
2972 break;
2973 }
2974 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
2975 0x03, (rx_fs_rate >> 0x05));
2976 }
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002977 }
2978
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002979 return 0;
2980}
2981
2982static struct snd_soc_dai_ops tabla_dai_ops = {
2983 .startup = tabla_startup,
2984 .shutdown = tabla_shutdown,
2985 .hw_params = tabla_hw_params,
2986 .set_sysclk = tabla_set_dai_sysclk,
2987 .set_fmt = tabla_set_dai_fmt,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002988};
2989
2990static struct snd_soc_dai_driver tabla_dai[] = {
2991 {
2992 .name = "tabla_rx1",
2993 .id = 1,
2994 .playback = {
2995 .stream_name = "AIF1 Playback",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07002996 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002997 .formats = TABLA_FORMATS,
2998 .rate_max = 48000,
2999 .rate_min = 8000,
3000 .channels_min = 1,
Kiran Kandi3426e512011-09-13 22:50:10 -07003001 .channels_max = 4,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003002 },
3003 .ops = &tabla_dai_ops,
3004 },
3005 {
3006 .name = "tabla_tx1",
3007 .id = 2,
3008 .capture = {
3009 .stream_name = "AIF1 Capture",
Bhalchandra Gajare9a901fd2011-08-01 10:07:15 -07003010 .rates = WCD9310_RATES,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003011 .formats = TABLA_FORMATS,
3012 .rate_max = 48000,
3013 .rate_min = 8000,
3014 .channels_min = 1,
3015 .channels_max = 2,
3016 },
3017 .ops = &tabla_dai_ops,
3018 },
3019};
Santosh Mardie15e2302011-11-15 10:39:23 +05303020
3021static struct snd_soc_dai_driver tabla_i2s_dai[] = {
3022 {
3023 .name = "tabla_i2s_rx1",
3024 .id = 1,
3025 .playback = {
3026 .stream_name = "AIF1 Playback",
3027 .rates = WCD9310_RATES,
3028 .formats = TABLA_FORMATS,
3029 .rate_max = 48000,
3030 .rate_min = 8000,
3031 .channels_min = 1,
3032 .channels_max = 4,
3033 },
3034 .ops = &tabla_dai_ops,
3035 },
3036 {
3037 .name = "tabla_i2s_tx1",
3038 .id = 2,
3039 .capture = {
3040 .stream_name = "AIF1 Capture",
3041 .rates = WCD9310_RATES,
3042 .formats = TABLA_FORMATS,
3043 .rate_max = 48000,
3044 .rate_min = 8000,
3045 .channels_min = 1,
3046 .channels_max = 4,
3047 },
3048 .ops = &tabla_dai_ops,
3049 },
3050};
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003051static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003052{
3053 u8 bias_msb, bias_lsb;
3054 short bias_value;
3055
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003056 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B3_STATUS);
3057 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B2_STATUS);
3058 bias_value = (bias_msb << 8) | bias_lsb;
3059 return bias_value;
3060}
3061
3062static short tabla_codec_read_dce_result(struct snd_soc_codec *codec)
3063{
3064 u8 bias_msb, bias_lsb;
3065 short bias_value;
3066
3067 bias_msb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B5_STATUS);
3068 bias_lsb = snd_soc_read(codec, TABLA_A_CDC_MBHC_B4_STATUS);
3069 bias_value = (bias_msb << 8) | bias_lsb;
3070 return bias_value;
3071}
3072
Joonwoo Park0976d012011-12-22 11:48:18 -08003073static short tabla_codec_sta_dce(struct snd_soc_codec *codec, int dce)
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003074{
Joonwoo Park0976d012011-12-22 11:48:18 -08003075 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003076 short bias_value;
3077
Joonwoo Park925914c2012-01-05 13:35:18 -08003078 /* Turn on the override */
3079 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003080 if (dce) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003081 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3082 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
3083 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
3084 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
Joonwoo Park0976d012011-12-22 11:48:18 -08003085 usleep_range(tabla->mbhc_data.t_dce,
3086 tabla->mbhc_data.t_dce);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003087 bias_value = tabla_codec_read_dce_result(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003088 } else {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003089 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003090 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3091 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003092 usleep_range(50, 50);
Joonwoo Park0976d012011-12-22 11:48:18 -08003093 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
3094 usleep_range(tabla->mbhc_data.t_sta,
3095 tabla->mbhc_data.t_sta);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003096 bias_value = tabla_codec_read_sta_result(codec);
3097 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3098 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003099 }
Joonwoo Park925914c2012-01-05 13:35:18 -08003100 /* Turn off the override after measuring mic voltage */
3101 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003102
Joonwoo Park0976d012011-12-22 11:48:18 -08003103 pr_debug("read microphone bias value %04x\n", bias_value);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003104 return bias_value;
3105}
3106
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003107static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003108{
3109 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003110 short bias_value;
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003111 u8 cfilt_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003112
Joonwoo Park0976d012011-12-22 11:48:18 -08003113 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003114 pr_err("Error, no tabla calibration\n");
Bradley Rubincb1e2732011-06-23 16:49:20 -07003115 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003116 }
3117
3118 tabla->mbhc_polling_active = true;
3119
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003120 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003121 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_MBHC_MODE);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003122 tabla_enable_rx_bias(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003123 tabla_codec_enable_clock_block(codec, 1);
3124 }
3125
3126 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01);
3127
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003128 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
3129
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003130 /* Make sure CFILT is in fast mode, save current mode */
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003131 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3132 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
Patrick Lai3043fba2011-08-01 14:15:57 -07003133
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003134 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003135
3136 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003137 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003138
3139 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x80);
3140 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x1F, 0x1C);
3141 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
3142
3143 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003144 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3145 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003146
Joonwoo Park925914c2012-01-05 13:35:18 -08003147 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003148 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
3149
Bradley Rubincb1e2732011-06-23 16:49:20 -07003150 tabla_codec_calibrate_hs_polling(codec);
3151
Joonwoo Park0976d012011-12-22 11:48:18 -08003152 bias_value = tabla_codec_sta_dce(codec, 0);
3153 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3154 cfilt_mode);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003155 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003156
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003157 return bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003158}
3159
3160static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
3161 int insertion)
3162{
3163 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003164 int central_bias_enabled = 0;
Joonwoo Park0976d012011-12-22 11:48:18 -08003165 const struct tabla_mbhc_general_cfg *generic =
3166 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3167 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3168 TABLA_MBHC_CAL_PLUG_DET_PTR(tabla->calibration);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003169 u8 wg_time;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003170
Joonwoo Park0976d012011-12-22 11:48:18 -08003171 if (!tabla->calibration) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003172 pr_err("Error, no tabla calibration\n");
3173 return -EINVAL;
3174 }
3175
3176 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0);
3177
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003178 if (insertion) {
3179 /* Make sure mic bias and Mic line schmitt trigger
3180 * are turned OFF
3181 */
3182 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg,
3183 0x81, 0x01);
3184 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3185 0x90, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003186 wg_time = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_WG_TIME) ;
3187 wg_time += 1;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003188
3189 /* Enable HPH Schmitt Trigger */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003190 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x11, 0x11);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003191 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x0C,
Joonwoo Park0976d012011-12-22 11:48:18 -08003192 plug_det->hph_current << 2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003193
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003194 /* Turn off HPH PAs and DAC's during insertion detection to
3195 * avoid false insertion interrupts
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003196 */
3197 if (tabla->mbhc_micbias_switched)
3198 tabla_codec_switch_micbias(codec, 0);
3199 snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003200 snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003201 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003202 snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_DAC_CTL,
Joonwoo Park0976d012011-12-22 11:48:18 -08003203 0xC0, 0x00);
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003204 usleep_range(wg_time * 1000, wg_time * 1000);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003205
3206 /* setup for insetion detection */
Bhalchandra Gajare5ea376d2011-11-30 14:21:20 -08003207 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x02, 0x02);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003208 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003209 } else {
3210 /* Make sure the HPH schmitt trigger is OFF */
3211 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12, 0x00);
3212
3213 /* enable the mic line schmitt trigger */
3214 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x60,
Joonwoo Park0976d012011-12-22 11:48:18 -08003215 plug_det->mic_current << 5);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003216 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3217 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003218 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003219 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
3220 0x10, 0x10);
3221
3222 /* Setup for low power removal detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003223 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003224 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003225
3226 if (snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x4) {
3227 if (!(tabla->clock_active)) {
3228 tabla_codec_enable_config_mode(codec, 1);
3229 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003230 0x06, 0);
Joonwoo Park0976d012011-12-22 11:48:18 -08003231 usleep_range(generic->t_shutdown_plug_rem,
3232 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003233 tabla_codec_enable_config_mode(codec, 0);
3234 } else
3235 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07003236 0x06, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003237 }
3238
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003239 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.int_rbias, 0x80, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003240
3241 /* If central bandgap disabled */
3242 if (!(snd_soc_read(codec, TABLA_A_PIN_CTL_OE1) & 1)) {
3243 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x3, 0x3);
Joonwoo Park0976d012011-12-22 11:48:18 -08003244 usleep_range(generic->t_bg_fast_settle,
3245 generic->t_bg_fast_settle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003246 central_bias_enabled = 1;
3247 }
3248
3249 /* If LDO_H disabled */
3250 if (snd_soc_read(codec, TABLA_A_PIN_CTL_OE0) & 0x80) {
3251 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x10, 0);
3252 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0x80);
Joonwoo Park0976d012011-12-22 11:48:18 -08003253 usleep_range(generic->t_ldoh, generic->t_ldoh);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003254 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0);
3255
3256 if (central_bias_enabled)
3257 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0);
3258 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003259
Joonwoo Park0976d012011-12-22 11:48:18 -08003260 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, tabla->micbias);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003261
3262 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
3263 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
3264 return 0;
3265}
3266
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003267static void tabla_lock_sleep(struct tabla_priv *tabla)
3268{
3269 int ret;
3270 while (!(ret = wait_event_timeout(tabla->pm_wq,
3271 atomic_inc_not_zero(&tabla->pm_cnt),
3272 2 * HZ))) {
3273 pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
3274 __func__, ret, atomic_read(&tabla->pm_cnt));
3275 WARN_ON_ONCE(1);
3276 }
3277}
3278
3279static void tabla_unlock_sleep(struct tabla_priv *tabla)
3280{
3281 atomic_dec(&tabla->pm_cnt);
3282 wake_up(&tabla->pm_wq);
3283}
3284
Joonwoo Park0976d012011-12-22 11:48:18 -08003285static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
3286 s16 vin_mv)
3287{
3288 short diff, zero;
3289 struct tabla_priv *tabla;
3290 u32 mb_mv, in;
3291
3292 tabla = snd_soc_codec_get_drvdata(codec);
3293 mb_mv = tabla->mbhc_data.micb_mv;
3294
3295 if (mb_mv == 0) {
3296 pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
3297 return -EINVAL;
3298 }
3299
3300 if (dce) {
3301 diff = tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z;
3302 zero = tabla->mbhc_data.dce_z;
3303 } else {
3304 diff = tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z;
3305 zero = tabla->mbhc_data.sta_z;
3306 }
3307 in = (u32) diff * vin_mv;
3308
3309 return (u16) (in / mb_mv) + zero;
3310}
3311
3312static s32 tabla_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
3313 u16 bias_value)
3314{
3315 struct tabla_priv *tabla;
3316 s32 mv;
3317
3318 tabla = snd_soc_codec_get_drvdata(codec);
3319
3320 if (dce) {
3321 mv = ((s32)bias_value - (s32)tabla->mbhc_data.dce_z) *
3322 (s32)tabla->mbhc_data.micb_mv /
3323 (s32)(tabla->mbhc_data.dce_mb - tabla->mbhc_data.dce_z);
3324 } else {
3325 mv = ((s32)bias_value - (s32)tabla->mbhc_data.sta_z) *
3326 (s32)tabla->mbhc_data.micb_mv /
3327 (s32)(tabla->mbhc_data.sta_mb - tabla->mbhc_data.sta_z);
3328 }
3329
3330 return mv;
3331}
3332
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003333static void btn0_lpress_fn(struct work_struct *work)
3334{
3335 struct delayed_work *delayed_work;
3336 struct tabla_priv *tabla;
Joonwoo Park0976d012011-12-22 11:48:18 -08003337 short bias_value;
3338 int dce_mv, sta_mv;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003339
3340 pr_debug("%s:\n", __func__);
3341
3342 delayed_work = to_delayed_work(work);
3343 tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
3344
3345 if (tabla) {
3346 if (tabla->button_jack) {
Joonwoo Park0976d012011-12-22 11:48:18 -08003347 bias_value = tabla_codec_read_sta_result(tabla->codec);
3348 sta_mv = tabla_codec_sta_dce_v(tabla->codec, 0,
3349 bias_value);
3350 bias_value = tabla_codec_read_dce_result(tabla->codec);
3351 dce_mv = tabla_codec_sta_dce_v(tabla->codec, 1,
3352 bias_value);
3353 pr_debug("%s: Reporting long button press event"
3354 " STA: %d, DCE: %d\n", __func__,
3355 sta_mv, dce_mv);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003356 tabla_snd_soc_jack_report(tabla, tabla->button_jack,
3357 SND_JACK_BTN_0,
3358 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003359 }
3360 } else {
3361 pr_err("%s: Bad tabla private data\n", __func__);
3362 }
3363
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003364 tabla_unlock_sleep(tabla);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003365}
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07003366
Joonwoo Park0976d012011-12-22 11:48:18 -08003367void tabla_mbhc_cal(struct snd_soc_codec *codec)
3368{
3369 struct tabla_priv *tabla;
3370 struct tabla_mbhc_btn_detect_cfg *btn_det;
3371 u8 cfilt_mode, bg_mode;
3372 u8 ncic, nmeas, navg;
3373 u32 mclk_rate;
3374 u32 dce_wait, sta_wait;
3375 u8 *n_cic;
3376
3377 tabla = snd_soc_codec_get_drvdata(codec);
3378
3379 /* First compute the DCE / STA wait times
3380 * depending on tunable parameters.
3381 * The value is computed in microseconds
3382 */
3383 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3384 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3385 ncic = n_cic[0];
3386 nmeas = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration)->n_meas;
3387 navg = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration)->mbhc_navg;
3388 mclk_rate = tabla->mclk_freq;
3389 dce_wait = (1000 * 512 * ncic * nmeas) / (mclk_rate / 1000);
3390 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
3391 dce_wait = dce_wait + 10000;
3392 else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
3393 dce_wait = dce_wait + 9810;
3394 else
3395 WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
3396
3397 sta_wait = (1000 * 128 * navg) / (mclk_rate / 1000);
3398
3399 /* Add 10 microseconds to handle error margin */
3400 dce_wait = dce_wait + 10;
3401 sta_wait = sta_wait + 10;
3402
3403 tabla->mbhc_data.t_dce = dce_wait;
3404 tabla->mbhc_data.t_sta = sta_wait;
3405
3406 /* LDOH and CFILT are already configured during pdata handling.
3407 * Only need to make sure CFILT and bandgap are in Fast mode.
3408 * Need to restore defaults once calculation is done.
3409 */
3410 cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
3411 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
3412 bg_mode = snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02,
3413 0x02);
3414
3415 /* Micbias, CFILT, LDOH, MBHC MUX mode settings
3416 * to perform ADC calibration
3417 */
3418 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x60,
3419 tabla->micbias << 5);
3420 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
3421 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x60, 0x60);
3422 snd_soc_write(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x78);
3423 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
3424
3425 /* DCE measurement for 0 volts */
3426 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3427 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3428 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3429 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3430 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3431 usleep_range(100, 100);
3432 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3433 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3434 tabla->mbhc_data.dce_z = tabla_codec_read_dce_result(codec);
3435
3436 /* DCE measurment for MB voltage */
3437 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3438 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3439 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3440 usleep_range(100, 100);
3441 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
3442 usleep_range(tabla->mbhc_data.t_dce, tabla->mbhc_data.t_dce);
3443 tabla->mbhc_data.dce_mb = tabla_codec_read_dce_result(codec);
3444
3445 /* Sta measuremnt for 0 volts */
3446 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
3447 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3448 snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x02);
3449 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3450 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x81);
3451 usleep_range(100, 100);
3452 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3453 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3454 tabla->mbhc_data.sta_z = tabla_codec_read_sta_result(codec);
3455
3456 /* STA Measurement for MB Voltage */
3457 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x82);
3458 usleep_range(100, 100);
3459 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x02);
3460 usleep_range(tabla->mbhc_data.t_sta, tabla->mbhc_data.t_sta);
3461 tabla->mbhc_data.sta_mb = tabla_codec_read_sta_result(codec);
3462
3463 /* Restore default settings. */
3464 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
3465 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
3466 cfilt_mode);
3467 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
3468
3469 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
3470 usleep_range(100, 100);
3471}
3472
3473void *tabla_mbhc_cal_btn_det_mp(const struct tabla_mbhc_btn_detect_cfg* btn_det,
3474 const enum tabla_mbhc_btn_det_mem mem)
3475{
3476 void *ret = &btn_det->_v_btn_low;
3477
3478 switch (mem) {
3479 case TABLA_BTN_DET_GAIN:
3480 ret += sizeof(btn_det->_n_cic);
3481 case TABLA_BTN_DET_N_CIC:
3482 ret += sizeof(btn_det->_n_ready);
3483 case TABLA_BTN_DET_V_N_READY:
3484 ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
3485 case TABLA_BTN_DET_V_BTN_HIGH:
3486 ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
3487 case TABLA_BTN_DET_V_BTN_LOW:
3488 /* do nothing */
3489 break;
3490 default:
3491 ret = NULL;
3492 }
3493
3494 return ret;
3495}
3496
3497static void tabla_mbhc_calc_thres(struct snd_soc_codec *codec)
3498{
3499 struct tabla_priv *tabla;
3500 s16 btn_mv = 0, btn_delta_mv;
3501 struct tabla_mbhc_btn_detect_cfg *btn_det;
3502 struct tabla_mbhc_plug_type_cfg *plug_type;
3503 u16 *btn_high;
3504 int i;
3505
3506 tabla = snd_soc_codec_get_drvdata(codec);
3507 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3508 plug_type = TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla->calibration);
3509
3510 if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ) {
3511 tabla->mbhc_data.nready = 3;
3512 tabla->mbhc_data.npoll = 9;
3513 tabla->mbhc_data.nbounce_wait = 30;
3514 } else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ) {
3515 tabla->mbhc_data.nready = 2;
3516 tabla->mbhc_data.npoll = 7;
3517 tabla->mbhc_data.nbounce_wait = 23;
3518 }
3519
3520 tabla->mbhc_data.v_ins_hu =
3521 tabla_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
3522 tabla->mbhc_data.v_ins_h =
3523 tabla_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
3524
3525 btn_high = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_HIGH);
3526 for (i = 0; i < btn_det->num_btn; i++)
3527 btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
3528
3529 tabla->mbhc_data.v_b1_h = tabla_codec_v_sta_dce(codec, DCE, btn_mv);
3530 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
3531
3532 tabla->mbhc_data.v_b1_hu =
3533 tabla_codec_v_sta_dce(codec, STA, btn_delta_mv);
3534
3535 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
3536
3537 tabla->mbhc_data.v_b1_huc =
3538 tabla_codec_v_sta_dce(codec, DCE, btn_delta_mv);
3539
3540 tabla->mbhc_data.v_brh = tabla->mbhc_data.v_b1_h;
3541 tabla->mbhc_data.v_brl = 0xFA55;
3542
3543 tabla->mbhc_data.v_no_mic =
3544 tabla_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
3545}
3546
3547void tabla_mbhc_init(struct snd_soc_codec *codec)
3548{
3549 struct tabla_priv *tabla;
3550 struct tabla_mbhc_general_cfg *generic;
3551 struct tabla_mbhc_btn_detect_cfg *btn_det;
3552 int n;
3553 u8 tabla_ver;
3554 u8 *n_cic, *gain;
3555
3556 tabla = snd_soc_codec_get_drvdata(codec);
3557 generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
3558 btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration);
3559
3560 tabla_ver = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
3561 tabla_ver &= 0x1F;
3562
3563 for (n = 0; n < 8; n++) {
3564 if ((tabla_ver != TABLA_VERSION_1_0 &&
3565 tabla_ver != TABLA_VERSION_1_1) || n != 7) {
3566 snd_soc_update_bits(codec,
3567 TABLA_A_CDC_MBHC_FEATURE_B1_CFG,
3568 0x07, n);
3569 snd_soc_write(codec, TABLA_A_CDC_MBHC_FEATURE_B2_CFG,
3570 btn_det->c[n]);
3571 }
3572 }
3573 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x07,
3574 btn_det->nc);
3575
3576 n_cic = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_N_CIC);
3577 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
3578 n_cic[0]);
3579
3580 gain = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_GAIN);
3581 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B2_CTL, 0x78, gain[0] << 3);
3582
3583 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
3584 generic->mbhc_nsa << 4);
3585
3586 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
3587 btn_det->n_meas);
3588
3589 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
3590
3591 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
3592
3593 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x78,
3594 btn_det->mbhc_nsc << 3);
3595
3596 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x03, TABLA_MICBIAS2);
3597
3598 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
3599}
3600
Patrick Lai64b43262011-12-06 17:29:15 -08003601static bool tabla_mbhc_fw_validate(const struct firmware *fw)
3602{
3603 u32 cfg_offset;
3604 struct tabla_mbhc_imped_detect_cfg *imped_cfg;
3605 struct tabla_mbhc_btn_detect_cfg *btn_cfg;
3606
3607 if (fw->size < TABLA_MBHC_CAL_MIN_SIZE)
3608 return false;
3609
3610 /* previous check guarantees that there is enough fw data up
3611 * to num_btn
3612 */
3613 btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(fw->data);
3614 cfg_offset = (u32) ((void *) btn_cfg - (void *) fw->data);
3615 if (fw->size < (cfg_offset + TABLA_MBHC_CAL_BTN_SZ(btn_cfg)))
3616 return false;
3617
3618 /* previous check guarantees that there is enough fw data up
3619 * to start of impedance detection configuration
3620 */
3621 imped_cfg = TABLA_MBHC_CAL_IMPED_DET_PTR(fw->data);
3622 cfg_offset = (u32) ((void *) imped_cfg - (void *) fw->data);
3623
3624 if (fw->size < (cfg_offset + TABLA_MBHC_CAL_IMPED_MIN_SZ))
3625 return false;
3626
3627 if (fw->size < (cfg_offset + TABLA_MBHC_CAL_IMPED_SZ(imped_cfg)))
3628 return false;
3629
3630 return true;
3631}
3632static void mbhc_fw_read(struct work_struct *work)
3633{
3634 struct delayed_work *dwork;
3635 struct tabla_priv *tabla;
3636 struct snd_soc_codec *codec;
3637 const struct firmware *fw;
3638 int ret = -1, retry = 0, rc;
3639
3640 dwork = to_delayed_work(work);
3641 tabla = container_of(dwork, struct tabla_priv,
3642 mbhc_firmware_dwork);
3643 codec = tabla->codec;
3644
3645 while (retry < MBHC_FW_READ_ATTEMPTS) {
3646 retry++;
3647 pr_info("%s:Attempt %d to request MBHC firmware\n",
3648 __func__, retry);
3649 ret = request_firmware(&fw, "wcd9310/wcd9310_mbhc.bin",
3650 codec->dev);
3651
3652 if (ret != 0) {
3653 usleep_range(MBHC_FW_READ_TIMEOUT,
3654 MBHC_FW_READ_TIMEOUT);
3655 } else {
3656 pr_info("%s: MBHC Firmware read succesful\n", __func__);
3657 break;
3658 }
3659 }
3660
3661 if (ret != 0) {
3662 pr_err("%s: Cannot load MBHC firmware use default cal\n",
3663 __func__);
3664 } else if (tabla_mbhc_fw_validate(fw) == false) {
3665 pr_err("%s: Invalid MBHC cal data size use default cal\n",
3666 __func__);
3667 release_firmware(fw);
3668 } else {
3669 tabla->calibration = (void *)fw->data;
3670 tabla->mbhc_fw = fw;
3671 }
3672
3673 tabla->mclk_cb(codec, 1);
3674 tabla_mbhc_init(codec);
3675 tabla_mbhc_cal(codec);
3676 tabla_mbhc_calc_thres(codec);
3677 tabla->mclk_cb(codec, 0);
3678 tabla_codec_calibrate_hs_polling(codec);
3679 rc = tabla_codec_enable_hs_detect(codec, 1);
3680
3681 if (IS_ERR_VALUE(rc))
3682 pr_err("%s: Failed to setup MBHC detection\n", __func__);
3683
3684}
3685
Bradley Rubincb1e2732011-06-23 16:49:20 -07003686int tabla_hs_detect(struct snd_soc_codec *codec,
Joonwoo Park0976d012011-12-22 11:48:18 -08003687 struct snd_soc_jack *headset_jack,
3688 struct snd_soc_jack *button_jack,
3689 void *calibration, enum tabla_micbias_num micbias,
3690 int (*mclk_cb_fn) (struct snd_soc_codec*, int),
3691 int read_fw_bin, u32 mclk_rate)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003692{
3693 struct tabla_priv *tabla;
Patrick Lai64b43262011-12-06 17:29:15 -08003694 int rc = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07003695
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003696 if (!codec || !calibration) {
3697 pr_err("Error: no codec or calibration\n");
3698 return -EINVAL;
3699 }
3700 tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003701 tabla->headset_jack = headset_jack;
3702 tabla->button_jack = button_jack;
Joonwoo Park0976d012011-12-22 11:48:18 -08003703 tabla->micbias = micbias;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003704 tabla->calibration = calibration;
Joonwoo Park0976d012011-12-22 11:48:18 -08003705 tabla->mclk_cb = mclk_cb_fn;
3706 tabla->mclk_freq = mclk_rate;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07003707 tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003708
Bhalchandra Gajare19d9c132011-11-18 14:57:08 -08003709 /* Put CFILT in fast mode by default */
3710 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl,
3711 0x40, TABLA_CFILT_FAST_MODE);
Patrick Lai64b43262011-12-06 17:29:15 -08003712 INIT_DELAYED_WORK(&tabla->mbhc_firmware_dwork, mbhc_fw_read);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003713 INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn);
Patrick Lai49efeac2011-11-03 11:01:12 -07003714 INIT_WORK(&tabla->hphlocp_work, hphlocp_off_report);
3715 INIT_WORK(&tabla->hphrocp_work, hphrocp_off_report);
Joonwoo Park0976d012011-12-22 11:48:18 -08003716
3717 if (!read_fw_bin) {
3718 tabla->mclk_cb(codec, 1);
3719 tabla_mbhc_init(codec);
3720 tabla_mbhc_cal(codec);
3721 tabla_mbhc_calc_thres(codec);
3722 tabla->mclk_cb(codec, 0);
3723 tabla_codec_calibrate_hs_polling(codec);
3724 rc = tabla_codec_enable_hs_detect(codec, 1);
3725 } else {
Patrick Lai64b43262011-12-06 17:29:15 -08003726 schedule_delayed_work(&tabla->mbhc_firmware_dwork,
3727 usecs_to_jiffies(MBHC_FW_READ_TIMEOUT));
Joonwoo Park0976d012011-12-22 11:48:18 -08003728 }
Patrick Lai49efeac2011-11-03 11:01:12 -07003729
3730 if (!IS_ERR_VALUE(rc)) {
3731 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3732 0x10);
3733 tabla_enable_irq(codec->control_data,
3734 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3735 tabla_enable_irq(codec->control_data,
3736 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3737 }
3738
3739 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003740}
3741EXPORT_SYMBOL_GPL(tabla_hs_detect);
3742
Bradley Rubincb1e2732011-06-23 16:49:20 -07003743static irqreturn_t tabla_dce_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003744{
3745 struct tabla_priv *priv = data;
3746 struct snd_soc_codec *codec = priv->codec;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003747 short bias_value;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003748
3749 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
3750 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003751 tabla_lock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003752
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003753 bias_value = tabla_codec_read_dce_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003754 pr_debug("%s: button press interrupt, DCE: %d,%d\n",
3755 __func__, bias_value,
3756 tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07003757
Bhalchandra Gajare30cf4842011-10-17 18:12:52 -07003758 bias_value = tabla_codec_read_sta_result(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003759 pr_debug("%s: button press interrupt, STA: %d,%d\n",
3760 __func__, bias_value,
3761 tabla_codec_sta_dce_v(codec, 0, bias_value));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003762 /*
3763 * TODO: If button pressed is not button 0,
3764 * report the button press event immediately.
3765 */
3766 priv->buttons_pressed |= SND_JACK_BTN_0;
Bradley Rubincb1e2732011-06-23 16:49:20 -07003767
Bradley Rubin688c66a2011-08-16 12:25:13 -07003768 msleep(100);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003769
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003770 if (schedule_delayed_work(&priv->btn0_dwork,
3771 msecs_to_jiffies(400)) == 0) {
3772 WARN(1, "Button pressed twice without release event\n");
3773 tabla_unlock_sleep(priv);
3774 }
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003775
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003776 return IRQ_HANDLED;
3777}
3778
Bradley Rubincb1e2732011-06-23 16:49:20 -07003779static irqreturn_t tabla_release_handler(int irq, void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003780{
3781 struct tabla_priv *priv = data;
3782 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003783 int ret, mb_v;
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003784
Bradley Rubin4d09cf42011-08-17 17:59:16 -07003785 pr_debug("%s\n", __func__);
3786 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003787 tabla_lock_sleep(priv);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003788
Bradley Rubincb1e2732011-06-23 16:49:20 -07003789 if (priv->buttons_pressed & SND_JACK_BTN_0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003790 ret = cancel_delayed_work(&priv->btn0_dwork);
3791
3792 if (ret == 0) {
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003793 pr_debug("%s: Reporting long button release event\n",
3794 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003795 if (priv->button_jack)
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003796 tabla_snd_soc_jack_report(priv,
3797 priv->button_jack, 0,
3798 SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003799 } else {
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003800 /* if scheduled btn0_dwork is canceled from here,
3801 * we have to unlock from here instead btn0_work */
3802 tabla_unlock_sleep(priv);
Joonwoo Park0976d012011-12-22 11:48:18 -08003803 mb_v = tabla_codec_sta_dce(codec, 0);
3804 pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
3805 __func__, mb_v,
3806 tabla_codec_sta_dce_v(codec, 0, mb_v));
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003807
Joonwoo Park0976d012011-12-22 11:48:18 -08003808 if (mb_v < -2000 || mb_v > -670)
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003809 pr_debug("%s: Fake buttton press interrupt\n",
3810 __func__);
Joonwoo Park0976d012011-12-22 11:48:18 -08003811 else if (priv->button_jack) {
3812 pr_debug("%s:reporting short button "
3813 "press and release\n", __func__);
3814 tabla_snd_soc_jack_report(priv,
3815 priv->button_jack,
3816 SND_JACK_BTN_0,
3817 SND_JACK_BTN_0);
3818 tabla_snd_soc_jack_report(priv,
3819 priv->button_jack,
3820 0, SND_JACK_BTN_0);
Bhalchandra Gajare0a792b12011-09-06 16:36:58 -07003821 }
3822 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003823
Bradley Rubincb1e2732011-06-23 16:49:20 -07003824 priv->buttons_pressed &= ~SND_JACK_BTN_0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003825 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003826
Bradley Rubin688c66a2011-08-16 12:25:13 -07003827 tabla_codec_start_hs_polling(codec);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003828 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003829 return IRQ_HANDLED;
3830}
3831
Bradley Rubincb1e2732011-06-23 16:49:20 -07003832static void tabla_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
3833{
3834 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Joonwoo Park0976d012011-12-22 11:48:18 -08003835 const struct tabla_mbhc_general_cfg *generic =
3836 TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003837
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003838 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003839 tabla_codec_enable_config_mode(codec, 1);
3840
3841 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
3842 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003843
Joonwoo Park0976d012011-12-22 11:48:18 -08003844 snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
3845
3846 usleep_range(generic->t_shutdown_plug_rem,
3847 generic->t_shutdown_plug_rem);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003848
3849 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003850 if (!tabla->mclk_enabled && !tabla->mbhc_polling_active)
Bradley Rubincb1e2732011-06-23 16:49:20 -07003851 tabla_codec_enable_config_mode(codec, 0);
3852
3853 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x00);
3854}
3855
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003856static void tabla_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
3857{
3858 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003859
3860 tabla_codec_shutdown_hs_removal_detect(codec);
3861
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07003862 if (!tabla->mclk_enabled) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003863 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0x00);
3864 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
3865 tabla_codec_enable_clock_block(codec, 0);
3866 }
3867
3868 tabla->mbhc_polling_active = false;
3869}
3870
Patrick Lai49efeac2011-11-03 11:01:12 -07003871static irqreturn_t tabla_hphl_ocp_irq(int irq, void *data)
3872{
3873 struct tabla_priv *tabla = data;
3874 struct snd_soc_codec *codec;
3875
3876 pr_info("%s: received HPHL OCP irq\n", __func__);
3877
3878 if (tabla) {
3879 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003880 if (tabla->hphlocp_cnt++ < TABLA_OCP_ATTEMPT) {
3881 pr_info("%s: retry\n", __func__);
3882 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3883 0x00);
3884 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3885 0x10);
3886 } else {
3887 tabla_disable_irq(codec->control_data,
3888 TABLA_IRQ_HPH_PA_OCPL_FAULT);
3889 tabla->hphlocp_cnt = 0;
3890 tabla->hph_status |= SND_JACK_OC_HPHL;
3891 if (tabla->headset_jack)
3892 tabla_snd_soc_jack_report(tabla,
3893 tabla->headset_jack,
3894 tabla->hph_status,
3895 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003896 }
3897 } else {
3898 pr_err("%s: Bad tabla private data\n", __func__);
3899 }
3900
3901 return IRQ_HANDLED;
3902}
3903
3904static irqreturn_t tabla_hphr_ocp_irq(int irq, void *data)
3905{
3906 struct tabla_priv *tabla = data;
3907 struct snd_soc_codec *codec;
3908
3909 pr_info("%s: received HPHR OCP irq\n", __func__);
3910
3911 if (tabla) {
3912 codec = tabla->codec;
Patrick Laic7cae882011-11-18 11:52:49 -08003913 if (tabla->hphrocp_cnt++ < TABLA_OCP_ATTEMPT) {
3914 pr_info("%s: retry\n", __func__);
3915 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3916 0x00);
3917 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
3918 0x10);
3919 } else {
3920 tabla_disable_irq(codec->control_data,
3921 TABLA_IRQ_HPH_PA_OCPR_FAULT);
3922 tabla->hphrocp_cnt = 0;
3923 tabla->hph_status |= SND_JACK_OC_HPHR;
3924 if (tabla->headset_jack)
3925 tabla_snd_soc_jack_report(tabla,
3926 tabla->headset_jack,
3927 tabla->hph_status,
3928 TABLA_JACK_MASK);
Patrick Lai49efeac2011-11-03 11:01:12 -07003929 }
3930 } else {
3931 pr_err("%s: Bad tabla private data\n", __func__);
3932 }
3933
3934 return IRQ_HANDLED;
3935}
3936
Joonwoo Parka9444452011-12-08 18:48:27 -08003937static void tabla_sync_hph_state(struct tabla_priv *tabla)
3938{
3939 if (test_and_clear_bit(TABLA_HPHR_PA_OFF_ACK,
3940 &tabla->hph_pa_dac_state)) {
3941 pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
3942 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x10,
3943 1 << 4);
3944 }
3945 if (test_and_clear_bit(TABLA_HPHL_PA_OFF_ACK,
3946 &tabla->hph_pa_dac_state)) {
3947 pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
3948 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x20,
3949 1 << 5);
3950 }
3951
3952 if (test_and_clear_bit(TABLA_HPHR_DAC_OFF_ACK,
3953 &tabla->hph_pa_dac_state)) {
3954 pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
3955 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_R_DAC_CTL,
3956 0xC0, 0xC0);
3957 }
3958 if (test_and_clear_bit(TABLA_HPHL_DAC_OFF_ACK,
3959 &tabla->hph_pa_dac_state)) {
3960 pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
3961 snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_L_DAC_CTL,
3962 0xC0, 0xC0);
3963 }
3964}
3965
Bradley Rubincb1e2732011-06-23 16:49:20 -07003966static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
3967{
3968 struct tabla_priv *priv = data;
3969 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08003970 const struct tabla_mbhc_plug_detect_cfg *plug_det =
3971 TABLA_MBHC_CAL_PLUG_DET_PTR(priv->calibration);
Bradley Rubin355611a2011-08-24 14:01:18 -07003972 int ldo_h_on, micb_cfilt_on;
Joonwoo Park0976d012011-12-22 11:48:18 -08003973 short mb_v;
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003974 u8 is_removal;
Joonwoo Park0976d012011-12-22 11:48:18 -08003975 int mic_mv;
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07003976
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003977 pr_debug("%s: enter\n", __func__);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003978 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08003979 tabla_lock_sleep(priv);
3980
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003981 is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
3982 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
3983
3984 /* Turn off both HPH and MIC line schmitt triggers */
Joonwoo Park0976d012011-12-22 11:48:18 -08003985 snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07003986 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
Bradley Rubincb1e2732011-06-23 16:49:20 -07003987
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003988 if (priv->mbhc_fake_ins_start &&
3989 time_after(jiffies, priv->mbhc_fake_ins_start +
3990 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003991 pr_debug("%s: fake context interrupt, reset insertion\n",
Joonwoo Parkf4267c22012-01-10 13:25:24 -08003992 __func__);
3993 priv->mbhc_fake_ins_start = 0;
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08003994 tabla_codec_shutdown_hs_polling(codec);
3995 tabla_codec_enable_hs_detect(codec, 1);
3996 return IRQ_HANDLED;
3997 }
3998
Bradley Rubin355611a2011-08-24 14:01:18 -07003999 ldo_h_on = snd_soc_read(codec, TABLA_A_LDO_H_MODE_1) & 0x80;
Joonwoo Park0976d012011-12-22 11:48:18 -08004000 micb_cfilt_on = snd_soc_read(codec, priv->mbhc_bias_regs.cfilt_ctl)
4001 & 0x80;
Bradley Rubin355611a2011-08-24 14:01:18 -07004002
4003 if (!ldo_h_on)
4004 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x80);
4005 if (!micb_cfilt_on)
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004006 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08004007 0x80, 0x80);
4008 if (plug_det->t_ins_complete > 20)
4009 msleep(plug_det->t_ins_complete);
4010 else
4011 usleep_range(plug_det->t_ins_complete * 1000,
4012 plug_det->t_ins_complete * 1000);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004013
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07004014 if (!ldo_h_on)
4015 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x0);
4016 if (!micb_cfilt_on)
4017 snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
Joonwoo Park0976d012011-12-22 11:48:18 -08004018 0x80, 0x0);
Bhalchandra Gajare7fc72332011-10-13 19:01:55 -07004019
4020 if (is_removal) {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004021 /*
4022 * If headphone is removed while playback is in progress,
4023 * it is possible that micbias will be switched to VDDIO.
4024 */
4025 if (priv->mbhc_micbias_switched)
4026 tabla_codec_switch_micbias(codec, 0);
Patrick Lai72aa4da2011-12-08 12:38:18 -08004027 priv->hph_status &= ~SND_JACK_HEADPHONE;
Joonwoo Parka9444452011-12-08 18:48:27 -08004028
4029 /* If headphone PA is on, check if userspace receives
4030 * removal event to sync-up PA's state */
4031 if (tabla_is_hph_pa_on(codec)) {
4032 set_bit(TABLA_HPHL_PA_OFF_ACK, &priv->hph_pa_dac_state);
4033 set_bit(TABLA_HPHR_PA_OFF_ACK, &priv->hph_pa_dac_state);
4034 }
4035
4036 if (tabla_is_hph_dac_on(codec, 1))
4037 set_bit(TABLA_HPHL_DAC_OFF_ACK,
4038 &priv->hph_pa_dac_state);
4039 if (tabla_is_hph_dac_on(codec, 0))
4040 set_bit(TABLA_HPHR_DAC_OFF_ACK,
4041 &priv->hph_pa_dac_state);
4042
Bradley Rubincb1e2732011-06-23 16:49:20 -07004043 if (priv->headset_jack) {
4044 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004045 tabla_snd_soc_jack_report(priv, priv->headset_jack,
4046 priv->hph_status,
4047 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004048 }
4049 tabla_codec_shutdown_hs_removal_detect(codec);
4050 tabla_codec_enable_hs_detect(codec, 1);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004051 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004052 return IRQ_HANDLED;
4053 }
4054
Joonwoo Park0976d012011-12-22 11:48:18 -08004055 mb_v = tabla_codec_setup_hs_polling(codec);
4056 mic_mv = tabla_codec_sta_dce_v(codec, 0, mb_v);
Bradley Rubin355611a2011-08-24 14:01:18 -07004057
Joonwoo Park0976d012011-12-22 11:48:18 -08004058 if (mb_v > (short) priv->mbhc_data.v_ins_hu) {
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004059 pr_debug("%s: Fake insertion interrupt since %dmsec ago, "
4060 "STA : %d,%d\n", __func__,
4061 (priv->mbhc_fake_ins_start ?
4062 jiffies_to_msecs(jiffies -
4063 priv->mbhc_fake_ins_start) :
4064 0),
4065 mb_v, mic_mv);
4066 if (time_after(jiffies,
4067 priv->mbhc_fake_ins_start +
4068 msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
4069 /* Disable HPH trigger and enable MIC line trigger */
4070 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12,
4071 0x00);
4072 snd_soc_update_bits(codec,
4073 priv->mbhc_bias_regs.mbhc_reg, 0x60,
4074 plug_det->mic_current << 5);
4075 snd_soc_update_bits(codec,
4076 priv->mbhc_bias_regs.mbhc_reg,
4077 0x80, 0x80);
4078 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
4079 snd_soc_update_bits(codec,
4080 priv->mbhc_bias_regs.mbhc_reg,
4081 0x10, 0x10);
4082 } else {
4083 if (priv->mbhc_fake_ins_start == 0)
4084 priv->mbhc_fake_ins_start = jiffies;
4085 /* Setup normal insert detection
4086 * Enable HPH Schmitt Trigger
4087 */
4088 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH,
4089 0x13 | 0x0C,
4090 0x13 | plug_det->hph_current << 2);
4091 }
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08004092 /* Setup for insertion detection */
4093 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
Bhalchandra Gajare9494fa262011-11-10 19:25:59 -08004094 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
4095 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
4096
Joonwoo Park0976d012011-12-22 11:48:18 -08004097 } else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
4098 pr_debug("%s: Headphone Detected, mb_v: %d,%d\n",
4099 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004100 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07004101 priv->hph_status |= SND_JACK_HEADPHONE;
Bradley Rubincb1e2732011-06-23 16:49:20 -07004102 if (priv->headset_jack) {
4103 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08004104 SND_JACK_HEADPHONE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004105 tabla_snd_soc_jack_report(priv, priv->headset_jack,
4106 priv->hph_status,
4107 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004108 }
4109 tabla_codec_shutdown_hs_polling(codec);
4110 tabla_codec_enable_hs_detect(codec, 0);
Joonwoo Parka9444452011-12-08 18:48:27 -08004111 tabla_sync_hph_state(priv);
Bhalchandra Gajare343cbb02011-09-07 18:58:19 -07004112 } else {
Joonwoo Park0976d012011-12-22 11:48:18 -08004113 pr_debug("%s: Headset detected, mb_v: %d,%d\n",
4114 __func__, mb_v, mic_mv);
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004115 priv->mbhc_fake_ins_start = 0;
Patrick Lai49efeac2011-11-03 11:01:12 -07004116 priv->hph_status |= SND_JACK_HEADSET;
Bradley Rubincb1e2732011-06-23 16:49:20 -07004117 if (priv->headset_jack) {
4118 pr_debug("%s: Reporting insertion %d\n", __func__,
Joonwoo Park0976d012011-12-22 11:48:18 -08004119 SND_JACK_HEADSET);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004120 tabla_snd_soc_jack_report(priv, priv->headset_jack,
4121 priv->hph_status,
4122 TABLA_JACK_MASK);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004123 }
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004124 /* avoid false button press detect */
4125 msleep(50);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004126 tabla_codec_start_hs_polling(codec);
Joonwoo Parka9444452011-12-08 18:48:27 -08004127 tabla_sync_hph_state(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004128 }
4129
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004130 tabla_unlock_sleep(priv);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004131 return IRQ_HANDLED;
4132}
4133
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004134static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
4135{
4136 struct tabla_priv *priv = data;
4137 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park0976d012011-12-22 11:48:18 -08004138 const struct tabla_mbhc_general_cfg *generic =
4139 TABLA_MBHC_CAL_GENERAL_PTR(priv->calibration);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004140 short bias_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004141
4142 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4143 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004144 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004145 tabla_lock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004146
Joonwoo Park0976d012011-12-22 11:48:18 -08004147 usleep_range(generic->t_shutdown_plug_rem,
4148 generic->t_shutdown_plug_rem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004149
Joonwoo Park0976d012011-12-22 11:48:18 -08004150 bias_value = tabla_codec_sta_dce(codec, 1);
4151 pr_debug("removal interrupt, DCE: %d,%d\n",
4152 bias_value, tabla_codec_sta_dce_v(codec, 1, bias_value));
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004153
Joonwoo Park0976d012011-12-22 11:48:18 -08004154 if (bias_value < (short) priv->mbhc_data.v_ins_h) {
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004155 pr_debug("False alarm, headset not actually removed\n");
4156 tabla_codec_start_hs_polling(codec);
4157 } else {
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004158 /*
4159 * If this removal is not false, first check the micbias
4160 * switch status and switch it to LDOH if it is already
4161 * switched to VDDIO.
4162 */
4163 if (priv->mbhc_micbias_switched)
4164 tabla_codec_switch_micbias(codec, 0);
Patrick Lai49efeac2011-11-03 11:01:12 -07004165 priv->hph_status &= ~SND_JACK_HEADSET;
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004166 if (priv->headset_jack) {
4167 pr_debug("%s: Reporting removal\n", __func__);
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004168 tabla_snd_soc_jack_report(priv, priv->headset_jack, 0,
4169 TABLA_JACK_MASK);
Bradley Rubin89ffd0a2011-07-21 16:04:06 -07004170 }
4171 tabla_codec_shutdown_hs_polling(codec);
4172
4173 tabla_codec_enable_hs_detect(codec, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004174 }
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004175
4176 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004177 return IRQ_HANDLED;
4178}
4179
4180static unsigned long slimbus_value;
4181
4182static irqreturn_t tabla_slimbus_irq(int irq, void *data)
4183{
4184 struct tabla_priv *priv = data;
4185 struct snd_soc_codec *codec = priv->codec;
4186 int i, j;
4187 u8 val;
4188
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004189 tabla_lock_sleep(priv);
4190
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004191 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
4192 slimbus_value = tabla_interface_reg_read(codec->control_data,
4193 TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
4194 for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
4195 val = tabla_interface_reg_read(codec->control_data,
4196 TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
4197 if (val & 0x1)
4198 pr_err_ratelimited("overflow error on port %x,"
4199 " value %x\n", i*8 + j, val);
4200 if (val & 0x2)
4201 pr_err_ratelimited("underflow error on port %x,"
4202 " value %x\n", i*8 + j, val);
4203 }
4204 tabla_interface_reg_write(codec->control_data,
4205 TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
4206 }
4207
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004208 tabla_unlock_sleep(priv);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004209 return IRQ_HANDLED;
4210}
4211
Patrick Lai3043fba2011-08-01 14:15:57 -07004212
4213static int tabla_handle_pdata(struct tabla_priv *tabla)
4214{
4215 struct snd_soc_codec *codec = tabla->codec;
4216 struct tabla_pdata *pdata = tabla->pdata;
4217 int k1, k2, k3, rc = 0;
Santosh Mardi22920282011-10-26 02:38:40 +05304218 u8 leg_mode = pdata->amic_settings.legacy_mode;
4219 u8 txfe_bypass = pdata->amic_settings.txfe_enable;
4220 u8 txfe_buff = pdata->amic_settings.txfe_buff;
4221 u8 flag = pdata->amic_settings.use_pdata;
4222 u8 i = 0, j = 0;
4223 u8 val_txfe = 0, value = 0;
Patrick Lai3043fba2011-08-01 14:15:57 -07004224
4225 if (!pdata) {
4226 rc = -ENODEV;
4227 goto done;
4228 }
4229
4230 /* Make sure settings are correct */
4231 if ((pdata->micbias.ldoh_v > TABLA_LDOH_2P85_V) ||
4232 (pdata->micbias.bias1_cfilt_sel > TABLA_CFILT3_SEL) ||
4233 (pdata->micbias.bias2_cfilt_sel > TABLA_CFILT3_SEL) ||
4234 (pdata->micbias.bias3_cfilt_sel > TABLA_CFILT3_SEL) ||
4235 (pdata->micbias.bias4_cfilt_sel > TABLA_CFILT3_SEL)) {
4236 rc = -EINVAL;
4237 goto done;
4238 }
4239
4240 /* figure out k value */
4241 k1 = tabla_find_k_value(pdata->micbias.ldoh_v,
4242 pdata->micbias.cfilt1_mv);
4243 k2 = tabla_find_k_value(pdata->micbias.ldoh_v,
4244 pdata->micbias.cfilt2_mv);
4245 k3 = tabla_find_k_value(pdata->micbias.ldoh_v,
4246 pdata->micbias.cfilt3_mv);
4247
4248 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
4249 rc = -EINVAL;
4250 goto done;
4251 }
4252
4253 /* Set voltage level and always use LDO */
4254 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x0C,
4255 (pdata->micbias.ldoh_v << 2));
4256
4257 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_1_VAL, 0xFC,
4258 (k1 << 2));
4259 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_2_VAL, 0xFC,
4260 (k2 << 2));
4261 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_3_VAL, 0xFC,
4262 (k3 << 2));
4263
4264 snd_soc_update_bits(codec, TABLA_A_MICB_1_CTL, 0x60,
4265 (pdata->micbias.bias1_cfilt_sel << 5));
4266 snd_soc_update_bits(codec, TABLA_A_MICB_2_CTL, 0x60,
4267 (pdata->micbias.bias2_cfilt_sel << 5));
4268 snd_soc_update_bits(codec, TABLA_A_MICB_3_CTL, 0x60,
4269 (pdata->micbias.bias3_cfilt_sel << 5));
4270 snd_soc_update_bits(codec, TABLA_A_MICB_4_CTL, 0x60,
4271 (pdata->micbias.bias4_cfilt_sel << 5));
4272
Santosh Mardi22920282011-10-26 02:38:40 +05304273 for (i = 0; i < 6; j++, i += 2) {
4274 if (flag & (0x01 << i)) {
4275 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
4276 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
4277 val_txfe = val_txfe |
4278 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
4279 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4280 0x10, value);
4281 snd_soc_update_bits(codec,
4282 TABLA_A_TX_1_2_TEST_EN + j * 10,
4283 0x30, val_txfe);
4284 }
4285 if (flag & (0x01 << (i + 1))) {
4286 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
4287 val_txfe = (txfe_bypass &
4288 (0x01 << (i + 1))) ? 0x02 : 0x00;
4289 val_txfe |= (txfe_buff &
4290 (0x01 << (i + 1))) ? 0x01 : 0x00;
4291 snd_soc_update_bits(codec, TABLA_A_TX_1_2_EN + j * 10,
4292 0x01, value);
4293 snd_soc_update_bits(codec,
4294 TABLA_A_TX_1_2_TEST_EN + j * 10,
4295 0x03, val_txfe);
4296 }
4297 }
4298 if (flag & 0x40) {
4299 value = (leg_mode & 0x40) ? 0x10 : 0x00;
4300 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
4301 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
4302 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN,
4303 0x13, value);
4304 }
Patrick Lai49efeac2011-11-03 11:01:12 -07004305
4306 if (pdata->ocp.use_pdata) {
4307 /* not defined in CODEC specification */
4308 if (pdata->ocp.hph_ocp_limit == 1 ||
4309 pdata->ocp.hph_ocp_limit == 5) {
4310 rc = -EINVAL;
4311 goto done;
4312 }
4313 snd_soc_update_bits(codec, TABLA_A_RX_COM_OCP_CTL,
4314 0x0F, pdata->ocp.num_attempts);
4315 snd_soc_write(codec, TABLA_A_RX_COM_OCP_COUNT,
4316 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
4317 snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL,
4318 0xE0, (pdata->ocp.hph_ocp_limit << 5));
4319 }
Patrick Lai3043fba2011-08-01 14:15:57 -07004320done:
4321 return rc;
4322}
4323
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004324static const struct tabla_reg_mask_val tabla_1_1_reg_defaults[] = {
4325
4326 /* Tabla 1.1 MICBIAS changes */
4327 TABLA_REG_VAL(TABLA_A_MICB_1_INT_RBIAS, 0x24),
4328 TABLA_REG_VAL(TABLA_A_MICB_2_INT_RBIAS, 0x24),
4329 TABLA_REG_VAL(TABLA_A_MICB_3_INT_RBIAS, 0x24),
4330 TABLA_REG_VAL(TABLA_A_MICB_4_INT_RBIAS, 0x24),
4331
4332 /* Tabla 1.1 HPH changes */
4333 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_PA, 0x57),
4334 TABLA_REG_VAL(TABLA_A_RX_HPH_BIAS_LDO, 0x56),
4335
4336 /* Tabla 1.1 EAR PA changes */
4337 TABLA_REG_VAL(TABLA_A_RX_EAR_BIAS_PA, 0xA6),
4338 TABLA_REG_VAL(TABLA_A_RX_EAR_GAIN, 0x02),
4339 TABLA_REG_VAL(TABLA_A_RX_EAR_VCM, 0x03),
4340
4341 /* Tabla 1.1 Lineout_5 Changes */
4342 TABLA_REG_VAL(TABLA_A_RX_LINE_5_GAIN, 0x10),
4343
4344 /* Tabla 1.1 RX Changes */
4345 TABLA_REG_VAL(TABLA_A_CDC_RX1_B5_CTL, 0x78),
4346 TABLA_REG_VAL(TABLA_A_CDC_RX2_B5_CTL, 0x78),
4347 TABLA_REG_VAL(TABLA_A_CDC_RX3_B5_CTL, 0x78),
4348 TABLA_REG_VAL(TABLA_A_CDC_RX4_B5_CTL, 0x78),
4349 TABLA_REG_VAL(TABLA_A_CDC_RX5_B5_CTL, 0x78),
4350 TABLA_REG_VAL(TABLA_A_CDC_RX6_B5_CTL, 0x78),
4351 TABLA_REG_VAL(TABLA_A_CDC_RX7_B5_CTL, 0x78),
4352
4353 /* Tabla 1.1 RX1 and RX2 Changes */
4354 TABLA_REG_VAL(TABLA_A_CDC_RX1_B6_CTL, 0xA0),
4355 TABLA_REG_VAL(TABLA_A_CDC_RX2_B6_CTL, 0xA0),
4356
4357 /* Tabla 1.1 RX3 to RX7 Changes */
4358 TABLA_REG_VAL(TABLA_A_CDC_RX3_B6_CTL, 0x80),
4359 TABLA_REG_VAL(TABLA_A_CDC_RX4_B6_CTL, 0x80),
4360 TABLA_REG_VAL(TABLA_A_CDC_RX5_B6_CTL, 0x80),
4361 TABLA_REG_VAL(TABLA_A_CDC_RX6_B6_CTL, 0x80),
4362 TABLA_REG_VAL(TABLA_A_CDC_RX7_B6_CTL, 0x80),
4363
4364 /* Tabla 1.1 CLASSG Changes */
4365 TABLA_REG_VAL(TABLA_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
4366};
4367
4368static const struct tabla_reg_mask_val tabla_2_0_reg_defaults[] = {
4369
4370 /* Tabla 2.0 MICBIAS changes */
4371 TABLA_REG_VAL(TABLA_A_MICB_2_MBHC, 0x02),
4372};
4373
4374static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
4375{
4376 u32 i;
4377
4378 for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
4379 snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
4380 tabla_1_1_reg_defaults[i].val);
4381
4382 for (i = 0; i < ARRAY_SIZE(tabla_2_0_reg_defaults); i++)
4383 snd_soc_write(codec, tabla_2_0_reg_defaults[i].reg,
4384 tabla_2_0_reg_defaults[i].val);
4385}
4386
4387static const struct tabla_reg_mask_val tabla_codec_reg_init_val[] = {
Patrick Laic7cae882011-11-18 11:52:49 -08004388 /* Initialize current threshold to 350MA
4389 * number of wait and run cycles to 4096
4390 */
Patrick Lai49efeac2011-11-03 11:01:12 -07004391 {TABLA_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
Patrick Laic7cae882011-11-18 11:52:49 -08004392 {TABLA_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004393
Santosh Mardi32171012011-10-28 23:32:06 +05304394 {TABLA_A_QFUSE_CTL, 0xFF, 0x03},
4395
Kiran Kandi1f6fd722011-08-11 10:36:11 -07004396 /* Initialize gain registers to use register gain */
4397 {TABLA_A_RX_HPH_L_GAIN, 0x10, 0x10},
4398 {TABLA_A_RX_HPH_R_GAIN, 0x10, 0x10},
4399 {TABLA_A_RX_LINE_1_GAIN, 0x10, 0x10},
4400 {TABLA_A_RX_LINE_2_GAIN, 0x10, 0x10},
4401 {TABLA_A_RX_LINE_3_GAIN, 0x10, 0x10},
4402 {TABLA_A_RX_LINE_4_GAIN, 0x10, 0x10},
4403
4404 /* Initialize mic biases to differential mode */
4405 {TABLA_A_MICB_1_INT_RBIAS, 0x24, 0x24},
4406 {TABLA_A_MICB_2_INT_RBIAS, 0x24, 0x24},
4407 {TABLA_A_MICB_3_INT_RBIAS, 0x24, 0x24},
4408 {TABLA_A_MICB_4_INT_RBIAS, 0x24, 0x24},
4409
4410 {TABLA_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
4411
4412 /* Use 16 bit sample size for TX1 to TX6 */
4413 {TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
4414 {TABLA_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
4415 {TABLA_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
4416 {TABLA_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
4417 {TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
4418 {TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
4419
4420 /* Use 16 bit sample size for TX7 to TX10 */
4421 {TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
4422 {TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
4423 {TABLA_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
4424 {TABLA_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
4425
4426 /* Use 16 bit sample size for RX */
4427 {TABLA_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
4428 {TABLA_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
4429
4430 /*enable HPF filter for TX paths */
4431 {TABLA_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
4432 {TABLA_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
4433 {TABLA_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
4434 {TABLA_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
4435 {TABLA_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
4436 {TABLA_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
4437 {TABLA_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
4438 {TABLA_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
4439 {TABLA_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
4440 {TABLA_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
4441};
4442
4443static void tabla_codec_init_reg(struct snd_soc_codec *codec)
4444{
4445 u32 i;
4446
4447 for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
4448 snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
4449 tabla_codec_reg_init_val[i].mask,
4450 tabla_codec_reg_init_val[i].val);
4451}
4452
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004453static int tabla_codec_probe(struct snd_soc_codec *codec)
4454{
4455 struct tabla *control;
4456 struct tabla_priv *tabla;
4457 struct snd_soc_dapm_context *dapm = &codec->dapm;
4458 int ret = 0;
4459 int i;
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004460 u8 tabla_version;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004461
4462 codec->control_data = dev_get_drvdata(codec->dev->parent);
4463 control = codec->control_data;
4464
4465 tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL);
4466 if (!tabla) {
4467 dev_err(codec->dev, "Failed to allocate private data\n");
4468 return -ENOMEM;
4469 }
4470
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004471 /* Make sure mbhc micbias register addresses are zeroed out */
4472 memset(&tabla->mbhc_bias_regs, 0,
4473 sizeof(struct mbhc_micbias_regs));
Bhalchandra Gajared9ebb6c2011-10-03 19:54:41 -07004474 tabla->cfilt_k_value = 0;
4475 tabla->mbhc_micbias_switched = false;
Bhalchandra Gajare02d90cd2011-09-30 16:14:00 -07004476
Joonwoo Park0976d012011-12-22 11:48:18 -08004477 /* Make sure mbhc intenal calibration data is zeroed out */
4478 memset(&tabla->mbhc_data, 0,
4479 sizeof(struct mbhc_internal_cal_data));
4480 tabla->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
4481 tabla->mbhc_data.t_sta = DEFAULT_STA_WAIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004482 snd_soc_codec_set_drvdata(codec, tabla);
4483
Kiran Kandi6fae8bf2011-08-15 10:36:42 -07004484 tabla->mclk_enabled = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004485 tabla->bandgap_type = TABLA_BANDGAP_OFF;
4486 tabla->clock_active = false;
4487 tabla->config_mode_active = false;
4488 tabla->mbhc_polling_active = false;
Joonwoo Parkf4267c22012-01-10 13:25:24 -08004489 tabla->mbhc_fake_ins_start = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004490 tabla->no_mic_headset_override = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004491 tabla->codec = codec;
Patrick Lai3043fba2011-08-01 14:15:57 -07004492 tabla->pdata = dev_get_platdata(codec->dev->parent);
Santosh Mardie15e2302011-11-15 10:39:23 +05304493 tabla->intf_type = tabla_get_intf_type();
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004494 atomic_set(&tabla->pm_cnt, 1);
4495 init_waitqueue_head(&tabla->pm_wq);
Patrick Lai3043fba2011-08-01 14:15:57 -07004496
Santosh Mardi22920282011-10-26 02:38:40 +05304497 tabla_update_reg_defaults(codec);
4498 tabla_codec_init_reg(codec);
Patrick Lai3043fba2011-08-01 14:15:57 -07004499
Santosh Mardi22920282011-10-26 02:38:40 +05304500 ret = tabla_handle_pdata(tabla);
Patrick Lai3043fba2011-08-01 14:15:57 -07004501 if (IS_ERR_VALUE(ret)) {
4502 pr_err("%s: bad pdata\n", __func__);
4503 goto err_pdata;
4504 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004505
4506 /* TODO only enable bandgap when necessary in order to save power */
4507 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
4508 tabla_codec_enable_clock_block(codec, 0);
4509
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004510 snd_soc_add_controls(codec, tabla_snd_controls,
4511 ARRAY_SIZE(tabla_snd_controls));
4512 snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
4513 ARRAY_SIZE(tabla_dapm_widgets));
Santosh Mardie15e2302011-11-15 10:39:23 +05304514 if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
4515 snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
4516 ARRAY_SIZE(tabla_dapm_i2s_widgets));
4517 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
4518 ARRAY_SIZE(audio_i2s_map));
4519 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004520 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004521
4522 tabla_version = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
Joonwoo Park0976d012011-12-22 11:48:18 -08004523 pr_info("%s : Tabla version reg 0x%2x\n", __func__,
4524 (u32)tabla_version);
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004525
4526 tabla_version &= 0x1F;
4527 pr_info("%s : Tabla version %u\n", __func__, (u32)tabla_version);
4528
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004529 if ((tabla_version == TABLA_VERSION_1_0) ||
4530 (tabla_version == TABLA_VERSION_1_1)) {
4531 snd_soc_dapm_add_routes(dapm, tabla_1_x_lineout_2_to_4_map,
Kiran Kandi8b3a8302011-09-27 16:13:28 -07004532 ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
4533
Kiran Kandi7a9fd902011-11-14 13:51:45 -08004534 } else if (tabla_version == TABLA_VERSION_2_0) {
4535 snd_soc_dapm_add_routes(dapm, tabla_2_x_lineout_2_to_4_map,
4536 ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
4537 } else {
4538 pr_err("%s : ERROR. Unsupported Tabla version 0x%2x\n",
4539 __func__, (u32)tabla_version);
4540 goto err_pdata;
4541 }
4542
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004543 snd_soc_dapm_sync(dapm);
4544
4545 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
4546 tabla_hs_insert_irq, "Headset insert detect", tabla);
4547 if (ret) {
4548 pr_err("%s: Failed to request irq %d\n", __func__,
4549 TABLA_IRQ_MBHC_INSERTION);
4550 goto err_insert_irq;
4551 }
4552 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
4553
4554 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
4555 tabla_hs_remove_irq, "Headset remove detect", tabla);
4556 if (ret) {
4557 pr_err("%s: Failed to request irq %d\n", __func__,
4558 TABLA_IRQ_MBHC_REMOVAL);
4559 goto err_remove_irq;
4560 }
4561 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
4562
4563 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
Bradley Rubincb1e2732011-06-23 16:49:20 -07004564 tabla_dce_handler, "DC Estimation detect", tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004565 if (ret) {
4566 pr_err("%s: Failed to request irq %d\n", __func__,
4567 TABLA_IRQ_MBHC_POTENTIAL);
4568 goto err_potential_irq;
4569 }
4570 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
4571
Bradley Rubincb1e2732011-06-23 16:49:20 -07004572 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
4573 tabla_release_handler, "Button Release detect", tabla);
4574 if (ret) {
4575 pr_err("%s: Failed to request irq %d\n", __func__,
4576 TABLA_IRQ_MBHC_RELEASE);
4577 goto err_release_irq;
4578 }
Bradley Rubin4d09cf42011-08-17 17:59:16 -07004579 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004580
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004581 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
4582 tabla_slimbus_irq, "SLIMBUS Slave", tabla);
4583 if (ret) {
4584 pr_err("%s: Failed to request irq %d\n", __func__,
4585 TABLA_IRQ_SLIMBUS);
4586 goto err_slimbus_irq;
4587 }
4588
4589 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
4590 tabla_interface_reg_write(codec->control_data,
4591 TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
4592
Patrick Lai49efeac2011-11-03 11:01:12 -07004593 ret = tabla_request_irq(codec->control_data,
4594 TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
4595 "HPH_L OCP detect", tabla);
4596 if (ret) {
4597 pr_err("%s: Failed to request irq %d\n", __func__,
4598 TABLA_IRQ_HPH_PA_OCPL_FAULT);
4599 goto err_hphl_ocp_irq;
4600 }
Patrick Lai92032be2011-12-19 14:14:25 -08004601 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004602
4603 ret = tabla_request_irq(codec->control_data,
4604 TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
4605 "HPH_R OCP detect", tabla);
4606 if (ret) {
4607 pr_err("%s: Failed to request irq %d\n", __func__,
4608 TABLA_IRQ_HPH_PA_OCPR_FAULT);
4609 goto err_hphr_ocp_irq;
4610 }
Patrick Lai92032be2011-12-19 14:14:25 -08004611 tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
Patrick Lai49efeac2011-11-03 11:01:12 -07004612
Bradley Rubincb3950a2011-08-18 13:07:26 -07004613#ifdef CONFIG_DEBUG_FS
4614 debug_tabla_priv = tabla;
4615#endif
4616
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004617 return ret;
4618
Patrick Lai49efeac2011-11-03 11:01:12 -07004619err_hphr_ocp_irq:
4620 tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
4621err_hphl_ocp_irq:
4622 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004623err_slimbus_irq:
Bradley Rubincb1e2732011-06-23 16:49:20 -07004624 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
4625err_release_irq:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004626 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4627err_potential_irq:
4628 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4629err_remove_irq:
4630 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4631err_insert_irq:
Patrick Lai3043fba2011-08-01 14:15:57 -07004632err_pdata:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004633 kfree(tabla);
4634 return ret;
4635}
4636static int tabla_codec_remove(struct snd_soc_codec *codec)
4637{
4638 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
4639 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
Bradley Rubincb1e2732011-06-23 16:49:20 -07004640 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004641 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
4642 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
4643 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
4644 tabla_codec_disable_clock_block(codec);
4645 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
Patrick Lai64b43262011-12-06 17:29:15 -08004646 if (tabla->mbhc_fw)
4647 release_firmware(tabla->mbhc_fw);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004648 kfree(tabla);
4649 return 0;
4650}
4651static struct snd_soc_codec_driver soc_codec_dev_tabla = {
4652 .probe = tabla_codec_probe,
4653 .remove = tabla_codec_remove,
4654 .read = tabla_read,
4655 .write = tabla_write,
4656
4657 .readable_register = tabla_readable,
4658 .volatile_register = tabla_volatile,
4659
4660 .reg_cache_size = TABLA_CACHE_SIZE,
4661 .reg_cache_default = tabla_reg_defaults,
4662 .reg_word_size = 1,
4663};
Bradley Rubincb3950a2011-08-18 13:07:26 -07004664
4665#ifdef CONFIG_DEBUG_FS
4666static struct dentry *debugfs_poke;
4667
4668static int codec_debug_open(struct inode *inode, struct file *file)
4669{
4670 file->private_data = inode->i_private;
4671 return 0;
4672}
4673
4674static ssize_t codec_debug_write(struct file *filp,
4675 const char __user *ubuf, size_t cnt, loff_t *ppos)
4676{
4677 char lbuf[32];
4678 char *buf;
4679 int rc;
4680
4681 if (cnt > sizeof(lbuf) - 1)
4682 return -EINVAL;
4683
4684 rc = copy_from_user(lbuf, ubuf, cnt);
4685 if (rc)
4686 return -EFAULT;
4687
4688 lbuf[cnt] = '\0';
4689 buf = (char *)lbuf;
4690 debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
4691 ? false : true;
4692
4693 return rc;
4694}
4695
4696static const struct file_operations codec_debug_ops = {
4697 .open = codec_debug_open,
4698 .write = codec_debug_write,
4699};
4700#endif
4701
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004702#ifdef CONFIG_PM
4703static int tabla_suspend(struct device *dev)
4704{
4705 int ret = 0, cnt;
4706 struct platform_device *pdev = to_platform_device(dev);
4707 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4708
4709 cnt = atomic_read(&tabla->pm_cnt);
4710 if (cnt > 0) {
4711 if (wait_event_timeout(tabla->pm_wq,
4712 (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
4713 == 1), 5 * HZ)) {
4714 dev_dbg(dev, "system suspend pm_cnt %d\n",
4715 atomic_read(&tabla->pm_cnt));
4716 } else {
4717 dev_err(dev, "%s timed out pm_cnt = %d\n",
4718 __func__, atomic_read(&tabla->pm_cnt));
4719 WARN_ON_ONCE(1);
4720 ret = -EBUSY;
4721 }
4722 } else if (cnt == 0)
4723 dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
4724 atomic_read(&tabla->pm_cnt));
4725 else {
4726 WARN(1, "unexpected pm_cnt %d\n", cnt);
4727 ret = -EFAULT;
4728 }
4729
4730 return ret;
4731}
4732
4733static int tabla_resume(struct device *dev)
4734{
4735 int ret = 0, cnt;
4736 struct platform_device *pdev = to_platform_device(dev);
4737 struct tabla_priv *tabla = platform_get_drvdata(pdev);
4738
4739 cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
4740 if (cnt == 0) {
4741 dev_dbg(dev, "system resume, pm_cnt %d\n",
4742 atomic_read(&tabla->pm_cnt));
4743 wake_up_all(&tabla->pm_wq);
4744 } else if (cnt > 0)
4745 dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
4746 else {
4747 WARN(1, "unexpected pm_cnt %d\n", cnt);
4748 ret = -EFAULT;
4749 }
4750
4751 return ret;
4752}
4753
4754static const struct dev_pm_ops tabla_pm_ops = {
4755 .suspend = tabla_suspend,
4756 .resume = tabla_resume,
4757};
4758#endif
4759
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004760static int __devinit tabla_probe(struct platform_device *pdev)
4761{
Santosh Mardie15e2302011-11-15 10:39:23 +05304762 int ret = 0;
Bradley Rubincb3950a2011-08-18 13:07:26 -07004763#ifdef CONFIG_DEBUG_FS
4764 debugfs_poke = debugfs_create_file("TRRS",
4765 S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
4766
4767#endif
Santosh Mardie15e2302011-11-15 10:39:23 +05304768 if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
4769 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4770 tabla_dai, ARRAY_SIZE(tabla_dai));
4771 else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
4772 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
4773 tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
4774 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004775}
4776static int __devexit tabla_remove(struct platform_device *pdev)
4777{
4778 snd_soc_unregister_codec(&pdev->dev);
Bradley Rubincb3950a2011-08-18 13:07:26 -07004779
4780#ifdef CONFIG_DEBUG_FS
4781 debugfs_remove(debugfs_poke);
4782#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004783 return 0;
4784}
4785static struct platform_driver tabla_codec_driver = {
4786 .probe = tabla_probe,
4787 .remove = tabla_remove,
4788 .driver = {
4789 .name = "tabla_codec",
4790 .owner = THIS_MODULE,
Joonwoo Park8b1f0982011-12-08 17:12:45 -08004791#ifdef CONFIG_PM
4792 .pm = &tabla_pm_ops,
4793#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004794 },
4795};
4796
4797static int __init tabla_codec_init(void)
4798{
4799 return platform_driver_register(&tabla_codec_driver);
4800}
4801
4802static void __exit tabla_codec_exit(void)
4803{
4804 platform_driver_unregister(&tabla_codec_driver);
4805}
4806
4807module_init(tabla_codec_init);
4808module_exit(tabla_codec_exit);
4809
4810MODULE_DESCRIPTION("Tabla codec driver");
4811MODULE_VERSION("1.0");
4812MODULE_LICENSE("GPL v2");