blob: 4a527ee777359d8602794a5479ba12381b87e114 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
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>
14#include <linux/slab.h>
15#include <linux/platform_device.h>
16#include <linux/printk.h>
17#include <linux/ratelimit.h>
18#include <linux/mfd/wcd9310/core.h>
19#include <linux/mfd/wcd9310/registers.h>
20#include <sound/jack.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/tlv.h>
24#include <linux/bitops.h>
25#include <linux/delay.h>
26#include "wcd9310.h"
27
28static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
29static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
30static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
31
32enum tabla_bandgap_type {
33 TABLA_BANDGAP_OFF = 0,
34 TABLA_BANDGAP_AUDIO_MODE,
35 TABLA_BANDGAP_MBHC_MODE,
36};
37
38struct tabla_priv { /* member undecided */
39 struct snd_soc_codec *codec;
40 u32 ref_cnt;
41 u32 adc_count;
42 u32 dec_count;
43 enum tabla_bandgap_type bandgap_type;
44 bool clock_active;
45 bool config_mode_active;
46 bool mbhc_polling_active;
47
48 struct tabla_mbhc_calibration *calibration;
49
50 struct snd_soc_jack *jack;
51};
52
53static int tabla_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
54 struct snd_kcontrol *kcontrol, int event)
55{
56 struct snd_soc_codec *codec = w->codec;
57 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
58
59 pr_debug("%s %d\n", __func__, event);
60 switch (event) {
61 case SND_SOC_DAPM_POST_PMU:
62 if ((tabla->bandgap_type != TABLA_BANDGAP_AUDIO_MODE) ||
63 (!tabla->clock_active)) {
64 pr_err("%s: Error, Tabla must have clocks enabled for "
65 "charge pump\n", __func__);
66 return -EINVAL;
67 }
68
69 snd_soc_update_bits(codec, TABLA_A_CP_EN, 0x01, 0x01);
70 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
71 0x01);
72 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x08);
73 usleep_range(200, 200);
74 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x00);
75 break;
76 case SND_SOC_DAPM_PRE_PMD:
77 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
78 0x10);
79 usleep_range(20, 20);
80 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x08);
81 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x10, 0x10);
82 snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x00);
83 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
84 0x00);
85 snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x00);
86 snd_soc_update_bits(codec, TABLA_A_CP_EN, 0x01, 0x00);
87 break;
88 }
89 return 0;
90}
91
92static const struct snd_kcontrol_new tabla_snd_controls[] = {
93 SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
94 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -070095 SOC_SINGLE_TLV("LINEOUT2 Volume", TABLA_A_RX_LINE_2_GAIN, 0, 12, 1,
96 line_gain),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070097 SOC_SINGLE_TLV("LINEOUT3 Volume", TABLA_A_RX_LINE_3_GAIN, 0, 12, 1,
98 line_gain),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -070099 SOC_SINGLE_TLV("LINEOUT4 Volume", TABLA_A_RX_LINE_4_GAIN, 0, 12, 1,
100 line_gain),
101
102 SOC_SINGLE("RX1 CHAIN INVERT Switch", TABLA_A_CDC_RX1_B6_CTL, 4, 1, 0),
103 SOC_SINGLE("RX2 CHAIN INVERT Switch", TABLA_A_CDC_RX2_B6_CTL, 4, 1, 0),
104 SOC_SINGLE("RX3 CHAIN INVERT Switch", TABLA_A_CDC_RX3_B6_CTL, 4, 1, 0),
105 SOC_SINGLE("RX4 CHAIN INVERT Switch", TABLA_A_CDC_RX4_B6_CTL, 4, 1, 0),
106 SOC_SINGLE("RX5 CHAIN INVERT Switch", TABLA_A_CDC_RX5_B6_CTL, 4, 1, 0),
107 SOC_SINGLE("RX6 CHAIN INVERT Switch", TABLA_A_CDC_RX6_B6_CTL, 4, 1, 0),
108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109 SOC_SINGLE_TLV("HPHL Volume", TABLA_A_RX_HPH_L_GAIN, 0, 12, 1,
110 line_gain),
111 SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
112 line_gain),
113
114 SOC_SINGLE_TLV("RX1 Digital Volume", TABLA_A_CDC_RX1_VOL_CTL_B2_CTL, 0,
115 100, 0, digital_gain),
116 SOC_SINGLE_TLV("RX2 Digital Volume", TABLA_A_CDC_RX2_VOL_CTL_B2_CTL, 0,
117 100, 0, digital_gain),
118
119 SOC_SINGLE_TLV("DEC5 Volume", TABLA_A_CDC_TX5_VOL_CTL_GAIN, 0, 100, 0,
120 digital_gain),
121 SOC_SINGLE_TLV("DEC6 Volume", TABLA_A_CDC_TX6_VOL_CTL_GAIN, 0, 100, 0,
122 digital_gain),
123
124 SOC_SINGLE_TLV("ADC1 Volume", TABLA_A_TX_1_2_EN, 1, 3, 0, analog_gain),
125 SOC_SINGLE_TLV("ADC2 Volume", TABLA_A_TX_1_2_EN, 5, 3, 0, analog_gain),
126
127 SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
128};
129
130static const char *rx_mix1_text[] = {
131 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
132 "RX5", "RX6", "RX7"
133};
134
135static const char *sb_tx1_mux_text[] = {
136 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
137 "DEC1"
138};
139
140static const char *sb_tx5_mux_text[] = {
141 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
142 "DEC5"
143};
144
145static const char *sb_tx6_mux_text[] = {
146 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
147 "DEC6"
148};
149
150static const char const *sb_tx7_to_tx10_mux_text[] = {
151 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
152 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
153 "DEC9", "DEC10"
154};
155
156static const char *dec1_mux_text[] = {
157 "ZERO", "DMIC1", "ADC6",
158};
159
160static const char *dec5_mux_text[] = {
161 "ZERO", "DMIC5", "ADC2",
162};
163
164static const char *dec6_mux_text[] = {
165 "ZERO", "DMIC6", "ADC1",
166};
167
168static const char const *dec7_mux_text[] = {
169 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
170};
171
172static const char *iir1_inp1_text[] = {
173 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
174 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
175};
176
177static const struct soc_enum rx_mix1_inp1_chain_enum =
178 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
179
180static const struct soc_enum rx2_mix1_inp1_chain_enum =
181 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
182
183static const struct soc_enum rx3_mix1_inp1_chain_enum =
184 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
185
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700186static const struct soc_enum rx3_mix1_inp2_chain_enum =
187 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189static const struct soc_enum rx4_mix1_inp1_chain_enum =
190 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
191
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700192static const struct soc_enum rx4_mix1_inp2_chain_enum =
193 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195static const struct soc_enum rx5_mix1_inp1_chain_enum =
196 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
197
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700198static const struct soc_enum rx5_mix1_inp2_chain_enum =
199 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
200
201static const struct soc_enum rx6_mix1_inp1_chain_enum =
202 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
203
204static const struct soc_enum rx6_mix1_inp2_chain_enum =
205 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
206
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207static const struct soc_enum sb_tx5_mux_enum =
208 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
209
210static const struct soc_enum sb_tx6_mux_enum =
211 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
212
213static const struct soc_enum sb_tx7_mux_enum =
214 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
215 sb_tx7_to_tx10_mux_text);
216
217static const struct soc_enum sb_tx8_mux_enum =
218 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
219 sb_tx7_to_tx10_mux_text);
220
221static const struct soc_enum sb_tx1_mux_enum =
222 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
223
224static const struct soc_enum dec1_mux_enum =
225 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
226
227static const struct soc_enum dec5_mux_enum =
228 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
229
230static const struct soc_enum dec6_mux_enum =
231 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
232
233static const struct soc_enum dec7_mux_enum =
234 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
235
236static const struct soc_enum iir1_inp1_mux_enum =
237 SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
238
239static const struct snd_kcontrol_new rx_mix1_inp1_mux =
240 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
241
242static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
243 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
244
245static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
246 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
247
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700248static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
249 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
250
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
252 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
253
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700254static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
255 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
256
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700257static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
258 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
259
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700260static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
261 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
262
263static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
264 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
265
266static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
267 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
268
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269static const struct snd_kcontrol_new sb_tx5_mux =
270 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
271
272static const struct snd_kcontrol_new sb_tx6_mux =
273 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
274
275static const struct snd_kcontrol_new sb_tx7_mux =
276 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
277
278static const struct snd_kcontrol_new sb_tx8_mux =
279 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
280
281static const struct snd_kcontrol_new sb_tx1_mux =
282 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
283
284static const struct snd_kcontrol_new dec1_mux =
285 SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
286
287static const struct snd_kcontrol_new dec5_mux =
288 SOC_DAPM_ENUM("DEC5 MUX Mux", dec5_mux_enum);
289
290static const struct snd_kcontrol_new dec6_mux =
291 SOC_DAPM_ENUM("DEC6 MUX Mux", dec6_mux_enum);
292
293static const struct snd_kcontrol_new dec7_mux =
294 SOC_DAPM_ENUM("DEC7 MUX Mux", dec7_mux_enum);
295
296static const struct snd_kcontrol_new iir1_inp1_mux =
297 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
298
299static const struct snd_kcontrol_new dac1_control =
300 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_EAR_EN, 5, 1, 0);
301
302static const struct snd_kcontrol_new hphl_switch =
303 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0);
304
305static const struct snd_kcontrol_new hphr_switch =
306 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_R_DAC_CTL, 6, 1, 0);
307
308static const struct snd_kcontrol_new lineout1_switch =
309 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_1_DAC_CTL, 6, 1, 0);
310
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700311static const struct snd_kcontrol_new lineout2_switch =
312 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_2_DAC_CTL, 6, 1, 0);
313
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700314static const struct snd_kcontrol_new lineout3_switch =
315 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
316
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700317static const struct snd_kcontrol_new lineout4_switch =
318 SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
319
320
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
322 int enable)
323{
324 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
325
326 pr_debug("%s %d\n", __func__, enable);
327
328 if (enable) {
329 tabla->adc_count++;
330 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
331 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
332 } else {
333 tabla->adc_count--;
334 if (!tabla->adc_count) {
335 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL,
336 0x2, 0x0);
337 if (!tabla->mbhc_polling_active)
338 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS,
339 0xE0, 0x0);
340 }
341 }
342}
343
344static int tabla_codec_enable_adc(struct snd_soc_dapm_widget *w,
345 struct snd_kcontrol *kcontrol, int event)
346{
347 struct snd_soc_codec *codec = w->codec;
348 u16 adc_reg;
349
350 pr_debug("%s %d\n", __func__, event);
351
352 if (w->reg == TABLA_A_TX_1_2_EN)
353 adc_reg = TABLA_A_TX_1_2_TEST_CTL;
354 else if (w->reg == TABLA_A_TX_3_4_EN)
355 adc_reg = TABLA_A_TX_3_4_TEST_CTL;
356 else if (w->reg == TABLA_A_TX_5_6_EN)
357 adc_reg = TABLA_A_TX_5_6_TEST_CTL;
358 else {
359 pr_err("%s: Error, invalid adc register\n", __func__);
360 return -EINVAL;
361 }
362
363 switch (event) {
364 case SND_SOC_DAPM_PRE_PMU:
365 tabla_codec_enable_adc_block(codec, 1);
366 break;
367 case SND_SOC_DAPM_POST_PMU:
368 snd_soc_update_bits(codec, adc_reg, 1 << w->shift,
369 1 << w->shift);
370 usleep_range(1000, 1000);
371 snd_soc_update_bits(codec, adc_reg, 1 << w->shift, 0x00);
372 usleep_range(1000, 1000);
373 break;
374 case SND_SOC_DAPM_POST_PMD:
375 tabla_codec_enable_adc_block(codec, 0);
376 break;
377 }
378 return 0;
379}
380
381static int tabla_codec_enable_pamp_gain(struct snd_soc_dapm_widget *w,
382 struct snd_kcontrol *kcontrol, int event)
383{
384 struct snd_soc_codec *codec = w->codec;
385
386 pr_debug("%s %d\n", __func__, event);
387 switch (event) {
388 case SND_SOC_DAPM_PRE_PMU:
389 snd_soc_update_bits(codec, TABLA_A_RX_EAR_GAIN, 0x80, 0x80);
390 break;
391 case SND_SOC_DAPM_POST_PMD:
392 snd_soc_update_bits(codec, TABLA_A_RX_EAR_GAIN, 0x80, 0x00);
393 break;
394 }
395 return 0;
396}
397
398static int tabla_codec_enable_lineout(struct snd_soc_dapm_widget *w,
399 struct snd_kcontrol *kcontrol, int event)
400{
401 struct snd_soc_codec *codec = w->codec;
402 u16 lineout_gain_reg;
403
404 pr_debug("%s %d\n", __func__, event);
405
406 switch (w->shift) {
407 case 0:
408 lineout_gain_reg = TABLA_A_RX_LINE_1_GAIN;
409 break;
410 case 1:
411 lineout_gain_reg = TABLA_A_RX_LINE_2_GAIN;
412 break;
413 case 2:
414 lineout_gain_reg = TABLA_A_RX_LINE_3_GAIN;
415 break;
416 case 3:
417 lineout_gain_reg = TABLA_A_RX_LINE_4_GAIN;
418 break;
419 case 4:
420 lineout_gain_reg = TABLA_A_RX_LINE_5_GAIN;
421 break;
422 default:
423 pr_err("%s: Error, incorrect lineout register value\n",
424 __func__);
425 return -EINVAL;
426 }
427
428 switch (event) {
429 case SND_SOC_DAPM_PRE_PMU:
430 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
431 break;
432 case SND_SOC_DAPM_POST_PMU:
433 usleep_range(40000, 40000);
434 break;
435 case SND_SOC_DAPM_POST_PMD:
436 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
437 break;
438 }
439 return 0;
440}
441
442static int tabla_codec_enable_dmic1(struct snd_soc_dapm_widget *w,
443 struct snd_kcontrol *kcontrol, int event)
444{
445 struct snd_soc_codec *codec = w->codec;
446
447 pr_debug("%s %d\n", __func__, event);
448 switch (event) {
449 case SND_SOC_DAPM_PRE_PMU:
450 snd_soc_update_bits(codec, TABLA_A_CDC_TX1_MUX_CTL, 0x1, 0x1);
451 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL, 0x2, 0x2);
452 snd_soc_update_bits(codec, TABLA_A_CDC_TX1_DMIC_CTL, 0x1, 0x1);
453 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL, 0x1, 0x1);
454 break;
455 case SND_SOC_DAPM_POST_PMD:
456 snd_soc_update_bits(codec, TABLA_A_CDC_TX1_DMIC_CTL, 0x1, 0);
457 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL, 0x3, 0);
458 break;
459 }
460 return 0;
461}
462
463static int tabla_codec_enable_micbias(struct snd_soc_dapm_widget *w,
464 struct snd_kcontrol *kcontrol, int event)
465{
466 struct snd_soc_codec *codec = w->codec;
467 u16 micb_cfilt_reg, micb_int_reg;
468 char *internal_text = "Internal";
469
470 pr_debug("%s %d\n", __func__, event);
471 switch (w->reg) {
472 case TABLA_A_MICB_1_CTL:
473 micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
474 micb_int_reg = TABLA_A_MICB_1_INT_RBIAS;
475 break;
476 case TABLA_A_MICB_2_CTL:
477 micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
478 micb_int_reg = TABLA_A_MICB_2_INT_RBIAS;
479 break;
480 case TABLA_A_MICB_3_CTL:
481 micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
482 micb_int_reg = TABLA_A_MICB_3_INT_RBIAS;
483 break;
484 default:
485 pr_err("%s: Error, invalid micbias register\n", __func__);
486 return -EINVAL;
487 }
488
489 switch (event) {
490 case SND_SOC_DAPM_PRE_PMU:
491 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
492 if (strnstr(w->name, internal_text, 20))
493 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
494 break;
495 case SND_SOC_DAPM_POST_PMD:
496 if (strnstr(w->name, internal_text, 20))
497 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
498 snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
499 break;
500 }
501
502 return 0;
503}
504
505static void tabla_codec_enable_dec_clock(struct snd_soc_codec *codec,
506 int enable)
507{
508 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
509
510 if (enable) {
511 tabla->dec_count++;
512 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x4, 0x4);
513 } else {
514 tabla->dec_count--;
515 if (!tabla->dec_count)
516 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL,
517 0x4, 0x0);
518 }
519}
520
521static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
522 struct snd_kcontrol *kcontrol, int event)
523{
524 struct snd_soc_codec *codec = w->codec;
525 u16 dec_reset_reg;
526
527 pr_debug("%s %d\n", __func__, event);
528
529 if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
530 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
531 else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
532 dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B2_CTL;
533 else {
534 pr_err("%s: Error, incorrect dec\n", __func__);
535 return -EINVAL;
536 }
537
538 switch (event) {
539 case SND_SOC_DAPM_PRE_PMU:
540 tabla_codec_enable_dec_clock(codec, 1);
541 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
542 1 << w->shift);
543 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
544 break;
545 case SND_SOC_DAPM_POST_PMD:
546 tabla_codec_enable_dec_clock(codec, 0);
547 break;
548 }
549 return 0;
550}
551
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700552static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 struct snd_kcontrol *kcontrol, int event)
554{
555 struct snd_soc_codec *codec = w->codec;
556
557 switch (event) {
558 case SND_SOC_DAPM_PRE_PMU:
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700559 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
560 1 << w->shift, 1 << w->shift);
561 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
562 1 << w->shift, 0x0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 break;
564 }
565 return 0;
566}
567
568static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
569 /*RX stuff */
570 SND_SOC_DAPM_OUTPUT("EAR"),
571
572 SND_SOC_DAPM_PGA_E("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0,
573 tabla_codec_enable_pamp_gain, SND_SOC_DAPM_POST_PMU |
574 SND_SOC_DAPM_PRE_PMD),
575
576 SND_SOC_DAPM_PGA("EAR PA Input", TABLA_A_CDC_CLSG_CTL, 2, 0, NULL, 0),
577
578 SND_SOC_DAPM_SWITCH("DAC1", TABLA_A_RX_EAR_EN, 6, 0, &dac1_control),
579 SND_SOC_DAPM_PGA_E("RX1 CP", SND_SOC_NOPM, 0, 0, NULL, 0,
580 tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
581 SND_SOC_DAPM_PRE_PMD),
582 SND_SOC_DAPM_PGA("RX BIAS", TABLA_A_RX_COM_BIAS, 7, 0, NULL, 0),
583 SND_SOC_DAPM_MUX_E("RX1 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0,
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700584 &rx_mix1_inp1_mux, tabla_codec_reset_interpolator,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585 SND_SOC_DAPM_PRE_PMU),
586 SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0,
587 TABLA_A_CDC_RX1_B6_CTL, 5, 0),
588
589 /* RX 2 path */
590 SND_SOC_DAPM_PGA_E("RX2 CP", SND_SOC_NOPM, 0, 0, NULL, 0,
591 tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
592 SND_SOC_DAPM_PRE_PMD),
593 SND_SOC_DAPM_MUX_E("RX2 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0,
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700594 &rx2_mix1_inp1_mux, tabla_codec_reset_interpolator,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700595 SND_SOC_DAPM_PRE_PMU),
596 SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0,
597 TABLA_A_CDC_RX2_B6_CTL, 5, 0),
598
599 /* Headphone */
600 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
601 SND_SOC_DAPM_PGA("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0),
602 SND_SOC_DAPM_SWITCH("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
603 &hphl_switch),
604
605 SND_SOC_DAPM_PGA("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0),
606 SND_SOC_DAPM_SWITCH("HPHR DAC", TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
607 &hphr_switch),
608
609 /* Speaker */
610 SND_SOC_DAPM_OUTPUT("LINEOUT"),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700611
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612 SND_SOC_DAPM_PGA_E("LINEOUT1", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL, 0,
613 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
614 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700615 SND_SOC_DAPM_PGA_E("LINEOUT2", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL, 0,
616 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
617 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700618 SND_SOC_DAPM_PGA_E("LINEOUT3", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL, 0,
619 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
620 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700621 SND_SOC_DAPM_PGA_E("LINEOUT4", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL, 0,
622 tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
623 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
624
625 SND_SOC_DAPM_SWITCH("LINEOUT1 DAC", TABLA_A_RX_LINE_1_DAC_CTL, 7, 0,
626 &lineout1_switch),
627 SND_SOC_DAPM_SWITCH("LINEOUT2 DAC", TABLA_A_RX_LINE_2_DAC_CTL, 7, 0,
628 &lineout2_switch),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700629 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC", TABLA_A_RX_LINE_3_DAC_CTL, 7, 0,
630 &lineout3_switch),
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700631 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC", TABLA_A_RX_LINE_4_DAC_CTL, 7, 0,
632 &lineout4_switch),
633
634 SND_SOC_DAPM_PGA_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL, 0,
635 tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
636 SND_SOC_DAPM_PGA_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL, 0,
637 tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
638 SND_SOC_DAPM_PGA_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL, 0,
639 tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
640 SND_SOC_DAPM_PGA_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL, 0,
641 tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
642
643 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
644 &rx3_mix1_inp1_mux),
645 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
646 &rx3_mix1_inp2_mux),
647 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
648 &rx4_mix1_inp1_mux),
649 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
650 &rx4_mix1_inp2_mux),
651 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
652 &rx5_mix1_inp1_mux),
653 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
654 &rx5_mix1_inp2_mux),
655 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
656 &rx6_mix1_inp1_mux),
657 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
658 &rx6_mix1_inp2_mux),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659
660 /* TX */
661 SND_SOC_DAPM_INPUT("AMIC1"),
662 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
663 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
664 SND_SOC_DAPM_POST_PMD),
665 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal", TABLA_A_MICB_1_CTL, 7, 0,
666 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
667 SND_SOC_DAPM_POST_PMD),
668 SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
669 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
670 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
671
672 SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
673 &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU |
674 SND_SOC_DAPM_POST_PMD),
675
676 SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
677 &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU |
678 SND_SOC_DAPM_POST_PMD),
679
680 SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
681 &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU |
682 SND_SOC_DAPM_POST_PMD),
683
684 SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
685 &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU |
686 SND_SOC_DAPM_POST_PMD),
687
688 SND_SOC_DAPM_INPUT("AMIC2"),
689 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
690 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
691 SND_SOC_DAPM_POST_PMD),
692 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal", TABLA_A_MICB_2_CTL, 7, 0,
693 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
694 SND_SOC_DAPM_POST_PMD),
695 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
696 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
697 SND_SOC_DAPM_POST_PMD),
698 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal", TABLA_A_MICB_3_CTL, 7, 0,
699 tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
700 SND_SOC_DAPM_POST_PMD),
701 SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
702 tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
703 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
704
705 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
706 SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
707 0, 0),
708
709 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
710 SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
711 4, 0),
712
713 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
714 SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
715 5, 0),
716
717 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
718 SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
719 0, 0),
720
721 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
722 SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
723 0, 0),
724
725 /* Digital Mic */
726 SND_SOC_DAPM_INPUT("DMIC1 IN"),
727 SND_SOC_DAPM_MIC("DMIC1", &tabla_codec_enable_dmic1),
728
729 /* Sidetone */
730 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
731 SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
732};
733
734static const struct snd_soc_dapm_route audio_map[] = {
735 /* SLIMBUS Connections */
736 {"RX BIAS", NULL, "SLIM RX1"},
737 {"RX BIAS", NULL, "SLIM RX2"},
738
739 {"SLIM TX1", NULL, "SLIM TX1 MUX"},
740 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
741
742 {"SLIM TX5", NULL, "SLIM TX5 MUX"},
743 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
744
745 {"SLIM TX6", NULL, "SLIM TX6 MUX"},
746 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
747
748 {"SLIM TX7", NULL, "SLIM TX7 MUX"},
749 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
750 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
751 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
752 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
753
754 {"SLIM TX8", NULL, "SLIM TX8 MUX"},
755 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
756 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
757
758 /* Earpiece (RX MIX1) */
759 {"EAR", NULL, "EAR PA"},
760 {"EAR PA", NULL, "EAR PA Input"},
761 {"EAR PA Input", NULL, "DAC1"},
762 {"DAC1", "Switch", "RX1 CP"},
763 {"RX1 CP", NULL, "RX1 MIX1 INP1"},
764 {"RX1 MIX1 INP1", "RX1", "RX BIAS"},
765
766 /* Headset (RX MIX1 and RX MIX2) */
767 {"HEADPHONE", NULL, "HPHL"},
768 {"HPHL", NULL, "HPHL DAC"},
769 {"HPHL DAC", "Switch", "RX1 MIX1 INP1"},
770
771 {"HEADPHONE", NULL, "HPHR"},
772 {"HPHR", NULL, "HPHR DAC"},
773 {"HPHR DAC", "Switch", "RX2 CP"},
774 {"RX2 CP", NULL, "RX2 MIX1 INP1"},
775 {"RX2 MIX1 INP1", "RX2", "RX BIAS"},
776
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 {"LINEOUT", NULL, "LINEOUT1"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700778 {"LINEOUT", NULL, "LINEOUT2"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700779 {"LINEOUT", NULL, "LINEOUT3"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700780 {"LINEOUT", NULL, "LINEOUT4"},
781
782 {"LINEOUT1", NULL, "LINEOUT1 DAC"},
783 {"LINEOUT2", NULL, "LINEOUT2 DAC"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 {"LINEOUT3", NULL, "LINEOUT3 DAC"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700785 {"LINEOUT4", NULL, "LINEOUT4 DAC"},
786
787 {"LINEOUT1 DAC", "Switch", "RX3 MIX1"},
788 {"LINEOUT2 DAC", "Switch", "RX4 MIX1"},
789 {"LINEOUT3 DAC", "Switch", "RX5 MIX1"},
790 {"LINEOUT4 DAC", "Switch", "RX6 MIX1"},
791
792 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
793 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
794 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
795 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
796 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
797 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
798 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
799 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
800
801 {"RX3 MIX1 INP1", "RX1", "RX BIAS"},
802 {"RX3 MIX1 INP1", "RX2", "RX BIAS"},
803 {"RX3 MIX1 INP2", "RX1", "RX BIAS"},
804 {"RX3 MIX1 INP2", "RX2", "RX BIAS"},
805 {"RX4 MIX1 INP1", "RX1", "RX BIAS"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 {"RX4 MIX1 INP1", "RX2", "RX BIAS"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700807 {"RX4 MIX1 INP2", "RX1", "RX BIAS"},
808 {"RX4 MIX1 INP2", "RX2", "RX BIAS"},
809 {"RX5 MIX1 INP1", "RX1", "RX BIAS"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 {"RX5 MIX1 INP1", "RX2", "RX BIAS"},
Bradley Rubin74a9b4a2011-06-13 15:03:43 -0700811 {"RX5 MIX1 INP2", "RX1", "RX BIAS"},
812 {"RX5 MIX1 INP2", "RX2", "RX BIAS"},
813 {"RX6 MIX1 INP1", "RX1", "RX BIAS"},
814 {"RX6 MIX1 INP1", "RX2", "RX BIAS"},
815 {"RX6 MIX1 INP2", "RX1", "RX BIAS"},
816 {"RX6 MIX1 INP2", "RX2", "RX BIAS"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817
818 /* Handset TX */
819 {"DEC5 MUX", "ADC2", "ADC2"},
820 {"DEC6 MUX", "ADC1", "ADC1"},
821 {"ADC1", NULL, "AMIC1"},
822 {"ADC2", NULL, "AMIC2"},
823
824 /* Digital Mic */
825 {"DEC1 MUX", "DMIC1", "DMIC1"},
826 {"DEC7 MUX", "DMIC1", "DMIC1"},
827 {"DMIC1", NULL, "DMIC1 IN"},
828
829 /* Sidetone (IIR1) */
830 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
831 {"IIR1", NULL, "IIR1 INP1 MUX"},
832 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
833
834};
835
836static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
837{
838 return tabla_reg_readable[reg];
839}
840
841static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
842{
843 /* Registers lower than 0x100 are top level registers which can be
844 * written by the Tabla core driver.
845 */
846
847 if ((reg >= TABLA_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
848 return 1;
849
850 return 0;
851}
852
853#define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
854static int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
855 unsigned int value)
856{
857 int ret;
858 pr_debug("%s: write reg %x val %x\n", __func__, reg, value);
859
860 BUG_ON(reg > TABLA_MAX_REGISTER);
861
862 if (!tabla_volatile(codec, reg)) {
863 pr_debug("writing to cache\n");
864 ret = snd_soc_cache_write(codec, reg, value);
865 if (ret != 0)
866 dev_err(codec->dev, "Cache write to %x failed: %d\n",
867 reg, ret);
868 }
869
870 return tabla_reg_write(codec->control_data, reg, value);
871}
872static unsigned int tabla_read(struct snd_soc_codec *codec,
873 unsigned int reg)
874{
875 unsigned int val;
876 int ret;
877
878 BUG_ON(reg > TABLA_MAX_REGISTER);
879
880 if (!tabla_volatile(codec, reg) && tabla_readable(codec, reg) &&
881 reg < codec->driver->reg_cache_size) {
882 pr_debug("reading from cache\n");
883 ret = snd_soc_cache_read(codec, reg, &val);
884 if (ret >= 0) {
885 pr_debug("register %d, value %d\n", reg, val);
886 return val;
887 } else
888 dev_err(codec->dev, "Cache read from %x failed: %d\n",
889 reg, ret);
890 }
891
892 val = tabla_reg_read(codec->control_data, reg);
893 pr_debug("%s: read reg %x val %x\n", __func__, reg, val);
894 return val;
895}
896
897static void tabla_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
898{
899 snd_soc_write(codec, TABLA_A_BIAS_REF_CTL, 0x1C);
900 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
901 0x80);
902 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x04,
903 0x04);
904 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x01,
905 0x01);
906 usleep_range(1000, 1000);
907 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
908 0x00);
909}
910
911static void tabla_codec_enable_bandgap(struct snd_soc_codec *codec,
912 enum tabla_bandgap_type choice)
913{
914 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
915
916 /* TODO lock resources accessed by audio streams and threaded
917 * interrupt handlers
918 */
919
920 pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
921 tabla->bandgap_type);
922
923 if (tabla->bandgap_type == choice)
924 return;
925
926 if ((tabla->bandgap_type == TABLA_BANDGAP_OFF) &&
927 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
928 tabla_codec_enable_audio_mode_bandgap(codec);
929 } else if ((tabla->bandgap_type == TABLA_BANDGAP_AUDIO_MODE) &&
930 (choice == TABLA_BANDGAP_MBHC_MODE)) {
931 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x2,
932 0x2);
933 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
934 0x80);
935 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x4,
936 0x4);
937 usleep_range(1000, 1000);
938 snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x80,
939 0x00);
940 } else if ((tabla->bandgap_type == TABLA_BANDGAP_MBHC_MODE) &&
941 (choice == TABLA_BANDGAP_AUDIO_MODE)) {
942 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
943 usleep_range(100, 100);
944 tabla_codec_enable_audio_mode_bandgap(codec);
945 } else if (choice == TABLA_BANDGAP_OFF) {
946 snd_soc_write(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x00);
947 } else {
948 pr_err("%s: Error, Invalid bandgap settings\n", __func__);
949 }
950 tabla->bandgap_type = choice;
951}
952
953static int tabla_codec_enable_config_mode(struct snd_soc_codec *codec,
954 int enable)
955{
956 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
957
958 if (enable) {
959 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
960 snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
961 usleep_range(5, 5);
962 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80,
963 0x80);
964 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80,
965 0x80);
966 usleep_range(10, 10);
967 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_TEST, 0x80, 0);
968 usleep_range(20, 20);
969 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x08);
970 } else {
971 snd_soc_update_bits(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x1,
972 0);
973 snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x80, 0);
974 }
975 tabla->config_mode_active = enable ? true : false;
976
977 return 0;
978}
979
980static int tabla_codec_enable_clock_block(struct snd_soc_codec *codec,
981 int config_mode)
982{
983 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
984
985 pr_debug("%s\n", __func__);
986
987 if (config_mode) {
988 tabla_codec_enable_config_mode(codec, 1);
989 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x00);
990 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
991 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN1, 0x0D);
992 usleep_range(1000, 1000);
993 } else
994 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x08, 0x00);
995
996 if (!config_mode && tabla->mbhc_polling_active) {
997 snd_soc_write(codec, TABLA_A_CLK_BUFF_EN2, 0x02);
998 tabla_codec_enable_config_mode(codec, 0);
999
1000 }
1001
1002 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x05);
1003 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x00);
1004 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x04);
1005 snd_soc_update_bits(codec, TABLA_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
1006 usleep_range(50, 50);
1007 tabla->clock_active = true;
1008 return 0;
1009}
1010static void tabla_codec_disable_clock_block(struct snd_soc_codec *codec)
1011{
1012 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1013 pr_debug("%s\n", __func__);
1014 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x04, 0x00);
1015 ndelay(160);
1016 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN2, 0x02, 0x02);
1017 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x00);
1018 tabla->clock_active = false;
1019}
1020
1021static int tabla_startup(struct snd_pcm_substream *substream,
1022 struct snd_soc_dai *dai)
1023{
1024 struct snd_soc_codec *codec = dai->codec;
1025 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1026 int ret = 0;
1027
1028 pr_debug("%s()\n", __func__);
1029
1030 if (!codec) {
1031 pr_err("Error, no codec found\n");
1032 return -EINVAL;
1033 }
1034 tabla->ref_cnt++;
1035
1036 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1037 /* Enable LDO */
1038 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_1_VAL, 0xFC,
1039 0xA0);
1040 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x80);
1041 usleep_range(1000, 1000);
1042 }
1043
1044 if (tabla->mbhc_polling_active && (tabla->ref_cnt == 1)) {
1045 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
1046 tabla_codec_enable_clock_block(codec, 0);
1047 }
1048
1049 return ret;
1050}
1051
1052static void tabla_shutdown(struct snd_pcm_substream *substream,
1053 struct snd_soc_dai *dai)
1054{
1055 struct snd_soc_codec *codec = dai->codec;
1056 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1057
1058 pr_debug("%s()\n", __func__);
1059
1060 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1061 /* Disable LDO */
1062 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x00);
1063 usleep_range(1000, 1000);
1064 }
1065
1066 if (!tabla->ref_cnt) {
1067 pr_err("Error, trying to shutdown codec when already down\n");
1068 return;
1069 }
1070 tabla->ref_cnt--;
1071
1072 if (tabla->mbhc_polling_active) {
1073 if (!tabla->ref_cnt) {
1074 tabla_codec_enable_bandgap(codec,
1075 TABLA_BANDGAP_MBHC_MODE);
1076 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS, 0x80,
1077 0x80);
1078 tabla_codec_enable_clock_block(codec, 1);
1079 }
1080 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01);
1081 }
1082}
1083
1084static int tabla_digital_mute(struct snd_soc_dai *codec_dai, int mute)
1085{
1086 struct snd_soc_codec *codec = codec_dai->codec;
1087
1088 pr_debug("%s %d\n", __func__, mute);
1089
1090 /* TODO mute TX */
1091 if (mute)
1092 snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL, 0x01, 0x01);
1093 else
1094 snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL, 0x01, 0x00);
1095
1096 return 0;
1097}
1098
1099static int tabla_set_dai_sysclk(struct snd_soc_dai *dai,
1100 int clk_id, unsigned int freq, int dir)
1101{
1102 pr_debug("%s\n", __func__);
1103 return 0;
1104}
1105
1106static int tabla_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1107{
1108 pr_debug("%s\n", __func__);
1109 return 0;
1110}
1111
1112static int tabla_hw_params(struct snd_pcm_substream *substream,
1113 struct snd_pcm_hw_params *params,
1114 struct snd_soc_dai *dai)
1115{
1116 pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
1117 return 0;
1118}
1119
1120static struct snd_soc_dai_ops tabla_dai_ops = {
1121 .startup = tabla_startup,
1122 .shutdown = tabla_shutdown,
1123 .hw_params = tabla_hw_params,
1124 .set_sysclk = tabla_set_dai_sysclk,
1125 .set_fmt = tabla_set_dai_fmt,
1126 .digital_mute = tabla_digital_mute,
1127};
1128
1129static struct snd_soc_dai_driver tabla_dai[] = {
1130 {
1131 .name = "tabla_rx1",
1132 .id = 1,
1133 .playback = {
1134 .stream_name = "AIF1 Playback",
1135 .rates = SNDRV_PCM_RATE_8000_48000,
1136 .formats = TABLA_FORMATS,
1137 .rate_max = 48000,
1138 .rate_min = 8000,
1139 .channels_min = 1,
1140 .channels_max = 2,
1141 },
1142 .ops = &tabla_dai_ops,
1143 },
1144 {
1145 .name = "tabla_tx1",
1146 .id = 2,
1147 .capture = {
1148 .stream_name = "AIF1 Capture",
1149 .rates = SNDRV_PCM_RATE_8000_48000,
1150 .formats = TABLA_FORMATS,
1151 .rate_max = 48000,
1152 .rate_min = 8000,
1153 .channels_min = 1,
1154 .channels_max = 2,
1155 },
1156 .ops = &tabla_dai_ops,
1157 },
1158};
1159
1160static void tabla_codec_setup_hs_polling(struct snd_soc_codec *codec)
1161{
1162 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1163 struct tabla_mbhc_calibration *calibration = tabla->calibration;
1164 int micbias_ctl_reg, micbias_cfilt_val_reg, micbias_cfilt_ctl_reg;
1165
1166 if (!calibration) {
1167 pr_err("Error, no tabla calibration\n");
1168 return;
1169 }
1170
1171 tabla->mbhc_polling_active = true;
1172
1173 if (!tabla->ref_cnt) {
1174 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_MBHC_MODE);
1175 snd_soc_update_bits(codec, TABLA_A_RX_COM_BIAS, 0x80, 0x80);
1176 tabla_codec_enable_clock_block(codec, 1);
1177 }
1178
1179 snd_soc_update_bits(codec, TABLA_A_CLK_BUFF_EN1, 0x05, 0x01);
1180
1181 /* TODO store register values in calibration */
1182 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x09);
1183 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
1184 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
1185 snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
1186
1187 snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x0F, 0x0D);
1188 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
1189
1190 /* TODO select cfilt separately from the micbias line inside the machine
1191 * driver
1192 */
1193 switch (calibration->bias) {
1194 case TABLA_MICBIAS1:
1195 micbias_ctl_reg = TABLA_A_MICB_1_CTL;
1196 micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_1_CTL;
1197 micbias_cfilt_val_reg = TABLA_A_MICB_CFILT_1_VAL;
1198 break;
1199 case TABLA_MICBIAS2:
1200 micbias_ctl_reg = TABLA_A_MICB_2_CTL;
1201 micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_2_CTL;
1202 micbias_cfilt_val_reg = TABLA_A_MICB_CFILT_2_VAL;
1203 break;
1204 case TABLA_MICBIAS3:
1205 micbias_ctl_reg = TABLA_A_MICB_3_CTL;
1206 micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_3_CTL;
1207 micbias_cfilt_val_reg = TABLA_A_MICB_CFILT_3_VAL;
1208 break;
1209 case TABLA_MICBIAS4:
1210 pr_err("%s: Error, microphone bias 4 not supported\n",
1211 __func__);
1212 return;
1213 default:
1214 pr_err("Error, invalid mic bias line\n");
1215 return;
1216 }
1217 snd_soc_write(codec, micbias_cfilt_ctl_reg, 0x40);
1218
1219 snd_soc_write(codec, micbias_ctl_reg, 0x36);
1220
1221 snd_soc_write(codec, micbias_cfilt_val_reg, 0x68);
1222
1223 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
1224 snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x4);
1225
1226 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x80);
1227 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x1F, 0x1C);
1228 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
1229
1230 snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
1231 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x80, 0x80);
1232 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x80, 0x00);
1233
1234 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL, 3);
1235 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B2_CTL, 9);
1236 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B3_CTL, 30);
1237 snd_soc_write(codec, TABLA_A_CDC_MBHC_TIMER_B6_CTL, 120);
1238 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_TIMER_B1_CTL, 0x78, 0x58);
1239 snd_soc_write(codec, TABLA_A_CDC_MBHC_B2_CTL, 11);
1240
1241 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
1242 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
1243
1244 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1245 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
1246 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1247 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
1248 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1249 /* TODO check if we need to maintain the other register bits */
1250}
1251
1252static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec,
1253 int insertion)
1254{
1255 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1256 struct tabla_mbhc_calibration *calibration = tabla->calibration;
1257 int central_bias_enabled = 0;
1258 int micbias_int_reg, micbias_ctl_reg, micbias_mbhc_reg;
1259
1260 if (!calibration) {
1261 pr_err("Error, no tabla calibration\n");
1262 return -EINVAL;
1263 }
1264
1265 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0);
1266
1267 if (insertion)
1268 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
1269 else
1270 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
1271
1272 if (snd_soc_read(codec, TABLA_A_CDC_MBHC_B1_CTL) & 0x4) {
1273 if (!(tabla->clock_active)) {
1274 tabla_codec_enable_config_mode(codec, 1);
1275 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
1276 0x04, 0);
1277 usleep_range(calibration->shutdown_plug_removal,
1278 calibration->shutdown_plug_removal);
1279 tabla_codec_enable_config_mode(codec, 0);
1280 } else
1281 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL,
1282 0x04, 0);
1283 }
1284
1285 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0xC,
1286 calibration->hph_current << 2);
1287
1288 snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x13);
1289
1290 switch (calibration->bias) {
1291 case TABLA_MICBIAS1:
1292 micbias_mbhc_reg = TABLA_A_MICB_1_MBHC;
1293 micbias_int_reg = TABLA_A_MICB_1_INT_RBIAS;
1294 micbias_ctl_reg = TABLA_A_MICB_1_CTL;
1295 break;
1296 case TABLA_MICBIAS2:
1297 micbias_mbhc_reg = TABLA_A_MICB_2_MBHC;
1298 micbias_int_reg = TABLA_A_MICB_2_INT_RBIAS;
1299 micbias_ctl_reg = TABLA_A_MICB_2_CTL;
1300 break;
1301 case TABLA_MICBIAS3:
1302 micbias_mbhc_reg = TABLA_A_MICB_3_MBHC;
1303 micbias_int_reg = TABLA_A_MICB_3_INT_RBIAS;
1304 micbias_ctl_reg = TABLA_A_MICB_3_CTL;
1305 break;
1306 case TABLA_MICBIAS4:
1307 micbias_mbhc_reg = TABLA_A_MICB_4_MBHC;
1308 micbias_int_reg = TABLA_A_MICB_4_INT_RBIAS;
1309 micbias_ctl_reg = TABLA_A_MICB_4_CTL;
1310 break;
1311 default:
1312 pr_err("Error, invalid mic bias line\n");
1313 return -EINVAL;
1314 }
1315 snd_soc_update_bits(codec, micbias_int_reg, 0x80, 0);
1316 snd_soc_update_bits(codec, micbias_ctl_reg, 0x1, 0);
1317
1318 /* If central bandgap disabled */
1319 if (!(snd_soc_read(codec, TABLA_A_PIN_CTL_OE1) & 1)) {
1320 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x3, 0x3);
1321 usleep_range(calibration->bg_fast_settle,
1322 calibration->bg_fast_settle);
1323 central_bias_enabled = 1;
1324 }
1325
1326 /* If LDO_H disabled */
1327 if (snd_soc_read(codec, TABLA_A_PIN_CTL_OE0) & 0x80) {
1328 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x10, 0);
1329 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0x80);
1330 usleep_range(calibration->tldoh, calibration->tldoh);
1331 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE0, 0x80, 0);
1332
1333 if (central_bias_enabled)
1334 snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0);
1335 }
1336 snd_soc_update_bits(codec, micbias_mbhc_reg, 0x60,
1337 calibration->mic_current << 5);
1338 snd_soc_update_bits(codec, micbias_mbhc_reg, 0x80, 0x80);
1339 usleep_range(calibration->mic_pid, calibration->mic_pid);
1340 snd_soc_update_bits(codec, micbias_mbhc_reg, 0x10, 0x10);
1341
1342 snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, calibration->bias);
1343
1344 tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
1345 snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
1346 return 0;
1347}
1348
1349int tabla_hs_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
1350 struct tabla_mbhc_calibration *calibration)
1351{
1352 struct tabla_priv *tabla;
1353 if (!codec || !calibration) {
1354 pr_err("Error: no codec or calibration\n");
1355 return -EINVAL;
1356 }
1357 tabla = snd_soc_codec_get_drvdata(codec);
1358 tabla->jack = jack;
1359 tabla->calibration = calibration;
1360
1361 return tabla_codec_enable_hs_detect(codec, 1);
1362}
1363EXPORT_SYMBOL_GPL(tabla_hs_detect);
1364
1365static irqreturn_t tabla_dummy_handler(int irq, void *data)
1366{
1367 struct tabla_priv *priv = data;
1368 struct snd_soc_codec *codec = priv->codec;
1369 snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
1370 return IRQ_HANDLED;
1371}
1372
1373static irqreturn_t tabla_hs_insert_irq(int irq, void *data)
1374{
1375 struct tabla_priv *priv = data;
1376 struct snd_soc_codec *codec = priv->codec;
1377
1378 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
1379
1380 if (priv->jack) {
1381 pr_debug("reporting insertion %d\n", SND_JACK_HEADSET);
1382 snd_soc_jack_report(priv->jack, SND_JACK_HEADSET,
1383 SND_JACK_HEADSET);
1384 }
1385 usleep_range(priv->calibration->setup_plug_removal_delay,
1386 priv->calibration->setup_plug_removal_delay);
1387
1388 tabla_codec_setup_hs_polling(codec);
1389
1390 return IRQ_HANDLED;
1391}
1392
1393static void tabla_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
1394{
1395 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1396 if (!tabla->ref_cnt) {
1397 snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0x00);
1398 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
1399 tabla_codec_enable_clock_block(codec, 0);
1400 }
1401
1402 tabla->mbhc_polling_active = false;
1403}
1404
1405static irqreturn_t tabla_hs_remove_irq(int irq, void *data)
1406{
1407 struct tabla_priv *priv = data;
1408 struct snd_soc_codec *codec = priv->codec;
1409
1410 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
1411 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1412
1413 usleep_range(priv->calibration->shutdown_plug_removal,
1414 priv->calibration->shutdown_plug_removal);
1415
1416 if (priv->jack) {
1417 pr_debug("reporting removal\n");
1418 snd_soc_jack_report(priv->jack, 0, SND_JACK_HEADSET);
1419 }
1420 tabla_codec_shutdown_hs_polling(codec);
1421
1422 tabla_codec_enable_hs_detect(codec, 1);
1423
1424 return IRQ_HANDLED;
1425}
1426
1427static unsigned long slimbus_value;
1428
1429static irqreturn_t tabla_slimbus_irq(int irq, void *data)
1430{
1431 struct tabla_priv *priv = data;
1432 struct snd_soc_codec *codec = priv->codec;
1433 int i, j;
1434 u8 val;
1435
1436 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
1437 slimbus_value = tabla_interface_reg_read(codec->control_data,
1438 TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
1439 for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
1440 val = tabla_interface_reg_read(codec->control_data,
1441 TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
1442 if (val & 0x1)
1443 pr_err_ratelimited("overflow error on port %x,"
1444 " value %x\n", i*8 + j, val);
1445 if (val & 0x2)
1446 pr_err_ratelimited("underflow error on port %x,"
1447 " value %x\n", i*8 + j, val);
1448 }
1449 tabla_interface_reg_write(codec->control_data,
1450 TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
1451 }
1452
1453 return IRQ_HANDLED;
1454}
1455
1456static int tabla_codec_probe(struct snd_soc_codec *codec)
1457{
1458 struct tabla *control;
1459 struct tabla_priv *tabla;
1460 struct snd_soc_dapm_context *dapm = &codec->dapm;
1461 int ret = 0;
1462 int i;
1463 int tx_channel;
1464
1465 codec->control_data = dev_get_drvdata(codec->dev->parent);
1466 control = codec->control_data;
1467
1468 tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL);
1469 if (!tabla) {
1470 dev_err(codec->dev, "Failed to allocate private data\n");
1471 return -ENOMEM;
1472 }
1473
1474 snd_soc_codec_set_drvdata(codec, tabla);
1475
1476 tabla->ref_cnt = 0;
1477 tabla->bandgap_type = TABLA_BANDGAP_OFF;
1478 tabla->clock_active = false;
1479 tabla->config_mode_active = false;
1480 tabla->mbhc_polling_active = false;
1481 tabla->codec = codec;
1482
1483 /* TODO only enable bandgap when necessary in order to save power */
1484 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_AUDIO_MODE);
1485 tabla_codec_enable_clock_block(codec, 0);
1486
1487 /* Initialize gain registers to use register gain */
1488 snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_GAIN, 0x10, 0x10);
1489 snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_GAIN, 0x10, 0x10);
1490 snd_soc_update_bits(codec, TABLA_A_RX_LINE_1_GAIN, 0x10, 0x10);
1491 snd_soc_update_bits(codec, TABLA_A_RX_LINE_3_GAIN, 0x10, 0x10);
1492
1493 /* Initialize mic biases to differential mode */
1494 snd_soc_update_bits(codec, TABLA_A_MICB_1_INT_RBIAS, 0x24, 0x24);
1495 snd_soc_update_bits(codec, TABLA_A_MICB_2_INT_RBIAS, 0x24, 0x24);
1496 snd_soc_update_bits(codec, TABLA_A_MICB_3_INT_RBIAS, 0x24, 0x24);
1497 snd_soc_update_bits(codec, TABLA_A_MICB_4_INT_RBIAS, 0x24, 0x24);
1498
1499 /* Set headset CFILT to fast mode */
1500 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_1_CTL, 0x00, 0x00);
1501 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_2_CTL, 0x00, 0x00);
1502 snd_soc_update_bits(codec, TABLA_A_MICB_CFILT_3_CTL, 0x00, 0x00);
1503
1504 snd_soc_update_bits(codec, TABLA_A_CDC_CONN_CLSG_CTL, 0x30, 0x10);
1505
1506 /* Use 16 bit sample size for now */
1507 for (tx_channel = 0; tx_channel < 6; tx_channel++) {
1508 snd_soc_update_bits(codec,
1509 TABLA_A_CDC_CONN_TX_SB_B1_CTL + tx_channel, 0x30, 0x20);
1510 snd_soc_update_bits(codec,
1511 TABLA_A_CDC_TX1_MUX_CTL + tx_channel, 0x8, 0x0);
1512
1513 }
1514 for (tx_channel = 6; tx_channel < 10; tx_channel++) {
1515 snd_soc_update_bits(codec,
1516 TABLA_A_CDC_CONN_TX_SB_B1_CTL + tx_channel, 0x60, 0x40);
1517 snd_soc_update_bits(codec,
1518 TABLA_A_CDC_TX1_MUX_CTL + tx_channel, 0x8, 0x0);
1519 }
1520 snd_soc_write(codec, TABLA_A_CDC_CONN_RX_SB_B1_CTL, 0xAA);
1521 snd_soc_write(codec, TABLA_A_CDC_CONN_RX_SB_B2_CTL, 0xAA);
1522
1523 snd_soc_add_controls(codec, tabla_snd_controls,
1524 ARRAY_SIZE(tabla_snd_controls));
1525 snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
1526 ARRAY_SIZE(tabla_dapm_widgets));
1527 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
1528 snd_soc_dapm_sync(dapm);
1529
1530 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
1531 tabla_hs_insert_irq, "Headset insert detect", tabla);
1532 if (ret) {
1533 pr_err("%s: Failed to request irq %d\n", __func__,
1534 TABLA_IRQ_MBHC_INSERTION);
1535 goto err_insert_irq;
1536 }
1537 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
1538
1539 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
1540 tabla_hs_remove_irq, "Headset remove detect", tabla);
1541 if (ret) {
1542 pr_err("%s: Failed to request irq %d\n", __func__,
1543 TABLA_IRQ_MBHC_REMOVAL);
1544 goto err_remove_irq;
1545 }
1546 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
1547
1548 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
1549 tabla_dummy_handler, "DC Estimation detect", tabla);
1550 if (ret) {
1551 pr_err("%s: Failed to request irq %d\n", __func__,
1552 TABLA_IRQ_MBHC_POTENTIAL);
1553 goto err_potential_irq;
1554 }
1555 tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
1556
1557 ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
1558 tabla_slimbus_irq, "SLIMBUS Slave", tabla);
1559 if (ret) {
1560 pr_err("%s: Failed to request irq %d\n", __func__,
1561 TABLA_IRQ_SLIMBUS);
1562 goto err_slimbus_irq;
1563 }
1564
1565 for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
1566 tabla_interface_reg_write(codec->control_data,
1567 TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
1568
1569 return ret;
1570
1571err_slimbus_irq:
1572 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
1573err_potential_irq:
1574 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
1575err_remove_irq:
1576 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
1577err_insert_irq:
1578 kfree(tabla);
1579 return ret;
1580}
1581static int tabla_codec_remove(struct snd_soc_codec *codec)
1582{
1583 struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
1584 tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
1585 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
1586 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
1587 tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
1588 tabla_codec_disable_clock_block(codec);
1589 tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
1590 kfree(tabla);
1591 return 0;
1592}
1593static struct snd_soc_codec_driver soc_codec_dev_tabla = {
1594 .probe = tabla_codec_probe,
1595 .remove = tabla_codec_remove,
1596 .read = tabla_read,
1597 .write = tabla_write,
1598
1599 .readable_register = tabla_readable,
1600 .volatile_register = tabla_volatile,
1601
1602 .reg_cache_size = TABLA_CACHE_SIZE,
1603 .reg_cache_default = tabla_reg_defaults,
1604 .reg_word_size = 1,
1605};
1606static int __devinit tabla_probe(struct platform_device *pdev)
1607{
1608 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
1609 tabla_dai, ARRAY_SIZE(tabla_dai));
1610}
1611static int __devexit tabla_remove(struct platform_device *pdev)
1612{
1613 snd_soc_unregister_codec(&pdev->dev);
1614 return 0;
1615}
1616static struct platform_driver tabla_codec_driver = {
1617 .probe = tabla_probe,
1618 .remove = tabla_remove,
1619 .driver = {
1620 .name = "tabla_codec",
1621 .owner = THIS_MODULE,
1622 },
1623};
1624
1625static int __init tabla_codec_init(void)
1626{
1627 return platform_driver_register(&tabla_codec_driver);
1628}
1629
1630static void __exit tabla_codec_exit(void)
1631{
1632 platform_driver_unregister(&tabla_codec_driver);
1633}
1634
1635module_init(tabla_codec_init);
1636module_exit(tabla_codec_exit);
1637
1638MODULE_DESCRIPTION("Tabla codec driver");
1639MODULE_VERSION("1.0");
1640MODULE_LICENSE("GPL v2");