blob: 6dc2ec05e35d2347abf95c6f3865f9854a4256a0 [file] [log] [blame]
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Kiran Kandic3b24402012-06-11 00:05:59 -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>
14#include <linux/firmware.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/device.h>
18#include <linux/printk.h>
19#include <linux/ratelimit.h>
20#include <linux/debugfs.h>
Joonwoo Park9bbb4d12012-11-09 19:58:11 -080021#include <linux/wait.h>
22#include <linux/bitops.h>
Kiran Kandic3b24402012-06-11 00:05:59 -070023#include <linux/mfd/wcd9xxx/core.h>
24#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
25#include <linux/mfd/wcd9xxx/wcd9320_registers.h>
26#include <linux/mfd/wcd9xxx/pdata.h>
Joonwoo Park448a8fc2013-04-10 15:25:58 -070027#include <linux/regulator/consumer.h>
Kiran Kandic3b24402012-06-11 00:05:59 -070028#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/tlv.h>
33#include <linux/bitops.h>
34#include <linux/delay.h>
35#include <linux/pm_runtime.h>
36#include <linux/kernel.h>
37#include <linux/gpio.h>
38#include "wcd9320.h"
Joonwoo Parka8890262012-10-15 12:04:27 -070039#include "wcd9xxx-resmgr.h"
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080040#include "wcd9xxx-common.h"
Kiran Kandic3b24402012-06-11 00:05:59 -070041
Joonwoo Park1d05bb92013-03-07 16:55:06 -080042#define TAIKO_MAD_SLIMBUS_TX_PORT 12
43#define TAIKO_MAD_AUDIO_FIRMWARE_PATH "wcd9320/wcd9320_mad_audio.bin"
Patrick Laiff5a5782013-05-05 00:13:00 -070044#define TAIKO_VALIDATE_RX_SBPORT_RANGE(port) ((port >= 16) && (port <= 22))
45#define TAIKO_CONVERT_RX_SBPORT_ID(port) (port - 16) /* RX1 port ID = 0 */
Joonwoo Park1d05bb92013-03-07 16:55:06 -080046
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -070047#define TAIKO_HPH_PA_SETTLE_COMP_ON 3000
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -070048#define TAIKO_HPH_PA_SETTLE_COMP_OFF 13000
49
Joonwoo Parkccccba72013-04-26 11:19:46 -070050#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
51
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -070052/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
53#define TAIKO_WG_TIME_FACTOR_US 240
54
Joonwoo Park125cd4e2012-12-11 15:16:11 -080055static atomic_t kp_taiko_priv;
56static int spkr_drv_wrnd_param_set(const char *val,
57 const struct kernel_param *kp);
58static int spkr_drv_wrnd = 1;
59
60static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
61 .set = spkr_drv_wrnd_param_set,
62 .get = param_get_int,
63};
Joonwoo Park1d05bb92013-03-07 16:55:06 -080064
65static struct afe_param_slimbus_slave_port_cfg taiko_slimbus_slave_port_cfg = {
66 .minor_version = 1,
67 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
68 .slave_dev_pgd_la = 0,
69 .slave_dev_intfdev_la = 0,
70 .bit_width = 16,
71 .data_format = 0,
72 .num_channels = 1
73};
74
Damir Didjustodcfdff82013-03-21 23:26:41 -070075static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
Joonwoo Park1d05bb92013-03-07 16:55:06 -080076 {
77 1,
78 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_MAIN_CTL_1),
79 HW_MAD_AUDIO_ENABLE, 0x1, 8, 0
80 },
81 {
82 1,
83 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_3),
84 HW_MAD_AUDIO_SLEEP_TIME, 0xF, 8, 0
85 },
86 {
87 1,
88 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_4),
89 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, 8, 0
90 },
91 {
92 1,
93 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
94 MAD_AUDIO_INT_DEST_SELECT_REG, 0x1, 8, 0
95 },
96 {
97 1,
98 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
99 MAD_AUDIO_INT_MASK_REG, 0x1, 8, 0
100 },
101 {
102 1,
103 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
104 MAD_AUDIO_INT_STATUS_REG, 0x1, 8, 0
105 },
106 {
107 1,
108 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
109 MAD_AUDIO_INT_CLEAR_REG, 0x1, 8, 0
110 },
111 {
112 1,
113 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
Damir Didjustod6aea992013-09-03 21:18:59 -0700114 SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800115 },
116 {
117 1,
118 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
Damir Didjustod6aea992013-09-03 21:18:59 -0700119 SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800120 },
121 {
122 1,
123 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
Damir Didjustod6aea992013-09-03 21:18:59 -0700124 SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800125 },
126 {
127 1,
128 (TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
Damir Didjustod6aea992013-09-03 21:18:59 -0700129 SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
Damir Didjustodcfdff82013-03-21 23:26:41 -0700130 },
131 { 1,
132 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
133 AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
134 },
135 { 1,
136 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
137 AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
138 },
139 {
140 1,
141 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_GAIN_CTL),
142 AANC_GAIN_CONTROL, 0xFF, 8, 0
143 },
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400144 {
145 1,
146 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
147 MAD_CLIP_INT_DEST_SELECT_REG, 0x8, 8, 0
148 },
149 {
150 1,
151 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
152 MAD_CLIP_INT_MASK_REG, 0x8, 8, 0
153 },
154 {
155 1,
156 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
157 MAD_CLIP_INT_STATUS_REG, 0x8, 8, 0
158 },
159 {
160 1,
161 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
162 MAD_CLIP_INT_CLEAR_REG, 0x8, 8, 0
163 },
164};
165
166static struct afe_param_cdc_reg_cfg clip_reg_cfg[] = {
167 {
168 1,
169 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400170 SPKR_CLIP_PIPE_BANK_SEL, 0x3, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400171 },
172 {
173 1,
174 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL0),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400175 SPKR_CLIPDET_VAL0, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400176 },
177 {
178 1,
179 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL1),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400180 SPKR_CLIPDET_VAL1, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400181 },
182 {
183 1,
184 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL2),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400185 SPKR_CLIPDET_VAL2, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400186 },
187 {
188 1,
189 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL3),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400190 SPKR_CLIPDET_VAL3, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400191 },
192 {
193 1,
194 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL4),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400195 SPKR_CLIPDET_VAL4, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400196 },
197 {
198 1,
199 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL5),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400200 SPKR_CLIPDET_VAL5, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400201 },
202 {
203 1,
204 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL6),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400205 SPKR_CLIPDET_VAL6, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400206 },
207 {
208 1,
209 (TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_SPKR_CLIPDET_VAL7),
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -0400210 SPKR_CLIPDET_VAL7, 0xff, 8, 0
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400211 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800212};
213
Damir Didjustodcfdff82013-03-21 23:26:41 -0700214static struct afe_param_cdc_reg_cfg_data taiko_audio_reg_cfg = {
215 .num_registers = ARRAY_SIZE(audio_reg_cfg),
216 .reg_data = audio_reg_cfg,
217};
218
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400219static struct afe_param_cdc_reg_cfg_data taiko_clip_reg_cfg = {
220 .num_registers = ARRAY_SIZE(clip_reg_cfg),
221 .reg_data = clip_reg_cfg,
222};
223
Damir Didjustodcfdff82013-03-21 23:26:41 -0700224static struct afe_param_id_cdc_aanc_version taiko_cdc_aanc_version = {
225 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
226 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800227};
228
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -0400229static struct afe_param_id_clip_bank_sel clip_bank_sel = {
230 .minor_version = AFE_API_VERSION_CLIP_BANK_SEL_CFG,
231 .num_banks = AFE_CLIP_MAX_BANKS,
232 .bank_map = {0, 1, 2, 3},
233};
234
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800235module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
236MODULE_PARM_DESC(spkr_drv_wrnd,
237 "Run software workaround to avoid leakage on the speaker drive");
238
Kiran Kandic3b24402012-06-11 00:05:59 -0700239#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
240 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
241 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
242
Kiran Kandic3b24402012-06-11 00:05:59 -0700243#define NUM_DECIMATORS 10
244#define NUM_INTERPOLATORS 7
245#define BITS_PER_REG 8
Kuirong Wang906ac472012-07-09 12:54:44 -0700246#define TAIKO_TX_PORT_NUMBER 16
Kuirong Wang80aca0d2013-05-09 14:51:09 -0700247#define TAIKO_RX_PORT_START_NUMBER 16
Kiran Kandic3b24402012-06-11 00:05:59 -0700248
Kiran Kandic3b24402012-06-11 00:05:59 -0700249#define TAIKO_I2S_MASTER_MODE_MASK 0x08
Damir Didjusto1a353ce2013-04-02 11:45:47 -0700250
Joonwoo Park9bbb4d12012-11-09 19:58:11 -0800251#define TAIKO_SLIM_CLOSE_TIMEOUT 1000
252#define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
253#define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
254#define TAIKO_SLIM_IRQ_PORT_CLOSED (1 << 2)
Venkat Sudhira50a3762012-11-26 12:12:15 -0800255#define TAIKO_MCLK_CLK_12P288MHZ 12288000
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -0700256#define TAIKO_MCLK_CLK_9P6MHZ 9600000
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800257
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -0800258#define TAIKO_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
259 SNDRV_PCM_FORMAT_S24_LE)
260
261#define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
262
Kuirong Wang906ac472012-07-09 12:54:44 -0700263enum {
264 AIF1_PB = 0,
265 AIF1_CAP,
266 AIF2_PB,
267 AIF2_CAP,
268 AIF3_PB,
269 AIF3_CAP,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -0500270 AIF4_VIFEED,
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800271 AIF4_MAD_TX,
Kuirong Wang906ac472012-07-09 12:54:44 -0700272 NUM_CODEC_DAIS,
Kiran Kandic3b24402012-06-11 00:05:59 -0700273};
274
Kuirong Wang906ac472012-07-09 12:54:44 -0700275enum {
276 RX_MIX1_INP_SEL_ZERO = 0,
277 RX_MIX1_INP_SEL_SRC1,
278 RX_MIX1_INP_SEL_SRC2,
279 RX_MIX1_INP_SEL_IIR1,
280 RX_MIX1_INP_SEL_IIR2,
281 RX_MIX1_INP_SEL_RX1,
282 RX_MIX1_INP_SEL_RX2,
283 RX_MIX1_INP_SEL_RX3,
284 RX_MIX1_INP_SEL_RX4,
285 RX_MIX1_INP_SEL_RX5,
286 RX_MIX1_INP_SEL_RX6,
287 RX_MIX1_INP_SEL_RX7,
288 RX_MIX1_INP_SEL_AUXRX,
289};
290
291#define TAIKO_COMP_DIGITAL_GAIN_OFFSET 3
292
Kiran Kandic3b24402012-06-11 00:05:59 -0700293static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
294static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
295static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
296static struct snd_soc_dai_driver taiko_dai[];
297static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
298
Kiran Kandic3b24402012-06-11 00:05:59 -0700299/* Codec supports 2 IIR filters */
300enum {
301 IIR1 = 0,
302 IIR2,
303 IIR_MAX,
304};
305/* Codec supports 5 bands */
306enum {
307 BAND1 = 0,
308 BAND2,
309 BAND3,
310 BAND4,
311 BAND5,
312 BAND_MAX,
313};
314
315enum {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700316 COMPANDER_0,
317 COMPANDER_1,
Kiran Kandic3b24402012-06-11 00:05:59 -0700318 COMPANDER_2,
319 COMPANDER_MAX,
320};
321
322enum {
323 COMPANDER_FS_8KHZ = 0,
324 COMPANDER_FS_16KHZ,
325 COMPANDER_FS_32KHZ,
326 COMPANDER_FS_48KHZ,
327 COMPANDER_FS_96KHZ,
328 COMPANDER_FS_192KHZ,
329 COMPANDER_FS_MAX,
330};
331
Kiran Kandic3b24402012-06-11 00:05:59 -0700332struct comp_sample_dependent_params {
333 u32 peak_det_timeout;
334 u32 rms_meter_div_fact;
335 u32 rms_meter_resamp_fact;
336};
337
Kiran Kandic3b24402012-06-11 00:05:59 -0700338struct hpf_work {
339 struct taiko_priv *taiko;
340 u32 decimator;
341 u8 tx_hpf_cut_of_freq;
342 struct delayed_work dwork;
343};
344
345static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
346
Kuirong Wang906ac472012-07-09 12:54:44 -0700347static const struct wcd9xxx_ch taiko_rx_chs[TAIKO_RX_MAX] = {
Kuirong Wang80aca0d2013-05-09 14:51:09 -0700348 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER, 0),
349 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 1, 1),
350 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 2, 2),
351 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 3, 3),
352 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 4, 4),
353 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 5, 5),
354 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 6, 6),
355 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 7, 7),
356 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 8, 8),
357 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 9, 9),
358 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 10, 10),
359 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 11, 11),
360 WCD9XXX_CH(TAIKO_RX_PORT_START_NUMBER + 12, 12),
Kuirong Wang906ac472012-07-09 12:54:44 -0700361};
362
363static const struct wcd9xxx_ch taiko_tx_chs[TAIKO_TX_MAX] = {
364 WCD9XXX_CH(0, 0),
365 WCD9XXX_CH(1, 1),
366 WCD9XXX_CH(2, 2),
367 WCD9XXX_CH(3, 3),
368 WCD9XXX_CH(4, 4),
369 WCD9XXX_CH(5, 5),
370 WCD9XXX_CH(6, 6),
371 WCD9XXX_CH(7, 7),
372 WCD9XXX_CH(8, 8),
373 WCD9XXX_CH(9, 9),
374 WCD9XXX_CH(10, 10),
375 WCD9XXX_CH(11, 11),
376 WCD9XXX_CH(12, 12),
377 WCD9XXX_CH(13, 13),
378 WCD9XXX_CH(14, 14),
379 WCD9XXX_CH(15, 15),
380};
381
382static const u32 vport_check_table[NUM_CODEC_DAIS] = {
383 0, /* AIF1_PB */
384 (1 << AIF2_CAP) | (1 << AIF3_CAP), /* AIF1_CAP */
385 0, /* AIF2_PB */
386 (1 << AIF1_CAP) | (1 << AIF3_CAP), /* AIF2_CAP */
387 0, /* AIF2_PB */
388 (1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
389};
390
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800391static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
392 0, /* AIF1_PB */
393 0, /* AIF1_CAP */
Venkat Sudhir994193b2012-12-17 17:30:51 -0800394 0, /* AIF2_PB */
395 0, /* AIF2_CAP */
Venkat Sudhir96dd28c2012-12-04 17:00:19 -0800396};
397
Kiran Kandic3b24402012-06-11 00:05:59 -0700398struct taiko_priv {
399 struct snd_soc_codec *codec;
Kiran Kandic3b24402012-06-11 00:05:59 -0700400 u32 adc_count;
Kiran Kandic3b24402012-06-11 00:05:59 -0700401 u32 rx_bias_count;
402 s32 dmic_1_2_clk_cnt;
403 s32 dmic_3_4_clk_cnt;
404 s32 dmic_5_6_clk_cnt;
Joonwoo Parkccccba72013-04-26 11:19:46 -0700405 s32 ldo_h_users;
406 s32 micb_2_users;
Kiran Kandic3b24402012-06-11 00:05:59 -0700407
Kiran Kandic3b24402012-06-11 00:05:59 -0700408 u32 anc_slot;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800409 bool anc_func;
Kiran Kandic3b24402012-06-11 00:05:59 -0700410
Kiran Kandic3b24402012-06-11 00:05:59 -0700411 /*track taiko interface type*/
412 u8 intf_type;
413
Kiran Kandic3b24402012-06-11 00:05:59 -0700414 /* num of slim ports required */
Kuirong Wang906ac472012-07-09 12:54:44 -0700415 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
Kiran Kandic3b24402012-06-11 00:05:59 -0700416
417 /*compander*/
418 int comp_enabled[COMPANDER_MAX];
419 u32 comp_fs[COMPANDER_MAX];
420
421 /* Maintain the status of AUX PGA */
422 int aux_pga_cnt;
423 u8 aux_l_gain;
424 u8 aux_r_gain;
425
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800426 bool spkr_pa_widget_on;
Joonwoo Park448a8fc2013-04-10 15:25:58 -0700427 struct regulator *spkdrv_reg;
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800428
Joonwoo Park88bfa842013-04-15 16:59:21 -0700429 bool mbhc_started;
430
Joonwoo Park1d05bb92013-03-07 16:55:06 -0800431 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
432
Joonwoo Parka8890262012-10-15 12:04:27 -0700433 /* resmgr module */
434 struct wcd9xxx_resmgr resmgr;
435 /* mbhc module */
436 struct wcd9xxx_mbhc mbhc;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -0800437
438 /* class h specific data */
439 struct wcd9xxx_clsh_cdc_data clsh_d;
Kiran Kandia1bed422013-05-28 18:29:12 -0700440
441 int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
442 enum wcd9xxx_codec_event);
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -0700443
444 /*
445 * list used to save/restore registers at start and
446 * end of impedance measurement
447 */
448 struct list_head reg_save_restore;
Kiran Kandic3b24402012-06-11 00:05:59 -0700449};
450
Kiran Kandic3b24402012-06-11 00:05:59 -0700451static const u32 comp_shift[] = {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700452 4, /* Compander 0's clock source is on interpolator 7 */
Kiran Kandic3b24402012-06-11 00:05:59 -0700453 0,
454 2,
455};
456
457static const int comp_rx_path[] = {
458 COMPANDER_1,
459 COMPANDER_1,
460 COMPANDER_2,
461 COMPANDER_2,
462 COMPANDER_2,
463 COMPANDER_2,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700464 COMPANDER_0,
Kiran Kandic3b24402012-06-11 00:05:59 -0700465 COMPANDER_MAX,
466};
467
468static const struct comp_sample_dependent_params comp_samp_params[] = {
469 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700470 /* 8 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700471 .peak_det_timeout = 0x06,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700472 .rms_meter_div_fact = 0x09,
473 .rms_meter_resamp_fact = 0x06,
Kiran Kandic3b24402012-06-11 00:05:59 -0700474 },
475 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700476 /* 16 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700477 .peak_det_timeout = 0x07,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700478 .rms_meter_div_fact = 0x0A,
479 .rms_meter_resamp_fact = 0x0C,
480 },
481 {
482 /* 32 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700483 .peak_det_timeout = 0x08,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700484 .rms_meter_div_fact = 0x0B,
485 .rms_meter_resamp_fact = 0x1E,
486 },
487 {
488 /* 48 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700489 .peak_det_timeout = 0x09,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700490 .rms_meter_div_fact = 0x0B,
Kiran Kandic3b24402012-06-11 00:05:59 -0700491 .rms_meter_resamp_fact = 0x28,
492 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700493 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700494 /* 96 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700495 .peak_det_timeout = 0x0A,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700496 .rms_meter_div_fact = 0x0C,
497 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700498 },
Kiran Kandic3b24402012-06-11 00:05:59 -0700499 {
Joonwoo Parkc7731432012-10-17 12:41:44 -0700500 /* 192 Khz */
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700501 .peak_det_timeout = 0x0B,
502 .rms_meter_div_fact = 0xC,
503 .rms_meter_resamp_fact = 0x50,
Kiran Kandic3b24402012-06-11 00:05:59 -0700504 },
505};
506
507static unsigned short rx_digital_gain_reg[] = {
508 TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
509 TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
510 TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
511 TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
512 TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
513 TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
514 TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
515};
516
517
518static unsigned short tx_digital_gain_reg[] = {
519 TAIKO_A_CDC_TX1_VOL_CTL_GAIN,
520 TAIKO_A_CDC_TX2_VOL_CTL_GAIN,
521 TAIKO_A_CDC_TX3_VOL_CTL_GAIN,
522 TAIKO_A_CDC_TX4_VOL_CTL_GAIN,
523 TAIKO_A_CDC_TX5_VOL_CTL_GAIN,
524 TAIKO_A_CDC_TX6_VOL_CTL_GAIN,
525 TAIKO_A_CDC_TX7_VOL_CTL_GAIN,
526 TAIKO_A_CDC_TX8_VOL_CTL_GAIN,
527 TAIKO_A_CDC_TX9_VOL_CTL_GAIN,
528 TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
529};
530
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800531static int spkr_drv_wrnd_param_set(const char *val,
532 const struct kernel_param *kp)
533{
534 struct snd_soc_codec *codec;
535 int ret, old;
536 struct taiko_priv *priv;
537
538 priv = (struct taiko_priv *)atomic_read(&kp_taiko_priv);
539 if (!priv) {
540 pr_debug("%s: codec isn't yet registered\n", __func__);
541 return 0;
542 }
543
Joonwoo Park973fd352013-06-19 11:38:53 -0700544 codec = priv->codec;
545 mutex_lock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800546 old = spkr_drv_wrnd;
547 ret = param_set_int(val, kp);
548 if (ret) {
Joonwoo Park973fd352013-06-19 11:38:53 -0700549 mutex_unlock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800550 return ret;
551 }
552
553 pr_debug("%s: spkr_drv_wrnd %d -> %d\n", __func__, old, spkr_drv_wrnd);
Joonwoo Park973fd352013-06-19 11:38:53 -0700554 if ((old == -1 || old == 0) && spkr_drv_wrnd == 1) {
Joonwoo Park533b3682013-06-13 11:41:21 -0700555 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800556 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
557 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -0700558 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800559 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
560 } else if (old == 1 && spkr_drv_wrnd == 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -0700561 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800562 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
563 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -0700564 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800565 if (!priv->spkr_pa_widget_on)
566 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
567 0x00);
568 }
Joonwoo Park973fd352013-06-19 11:38:53 -0700569 mutex_unlock(&codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800570
Joonwoo Park125cd4e2012-12-11 15:16:11 -0800571 return 0;
572}
573
Kiran Kandic3b24402012-06-11 00:05:59 -0700574static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
575 struct snd_ctl_elem_value *ucontrol)
576{
577 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
578 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
579 ucontrol->value.integer.value[0] = taiko->anc_slot;
580 return 0;
581}
582
583static int taiko_put_anc_slot(struct snd_kcontrol *kcontrol,
584 struct snd_ctl_elem_value *ucontrol)
585{
586 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
587 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
588 taiko->anc_slot = ucontrol->value.integer.value[0];
589 return 0;
590}
591
Damir Didjusto2cb06bd2013-01-30 23:14:55 -0800592static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
593 struct snd_ctl_elem_value *ucontrol)
594{
595 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
596 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
597
598 ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
599 return 0;
600}
601
602static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
603 struct snd_ctl_elem_value *ucontrol)
604{
605 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
606 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
607 struct snd_soc_dapm_context *dapm = &codec->dapm;
608
609 mutex_lock(&dapm->codec->mutex);
610 taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
611
612 dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
613
614 if (taiko->anc_func == true) {
615 snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
616 snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
617 snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
618 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
619 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
620 snd_soc_dapm_disable_pin(dapm, "HPHR");
621 snd_soc_dapm_disable_pin(dapm, "HPHL");
622 snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
623 snd_soc_dapm_disable_pin(dapm, "EAR PA");
624 snd_soc_dapm_disable_pin(dapm, "EAR");
625 } else {
626 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
627 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
628 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
629 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
630 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
631 snd_soc_dapm_enable_pin(dapm, "HPHR");
632 snd_soc_dapm_enable_pin(dapm, "HPHL");
633 snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
634 snd_soc_dapm_enable_pin(dapm, "EAR PA");
635 snd_soc_dapm_enable_pin(dapm, "EAR");
636 }
637 snd_soc_dapm_sync(dapm);
638 mutex_unlock(&dapm->codec->mutex);
639 return 0;
640}
641
Kiran Kandic3b24402012-06-11 00:05:59 -0700642static int taiko_get_iir_enable_audio_mixer(
643 struct snd_kcontrol *kcontrol,
644 struct snd_ctl_elem_value *ucontrol)
645{
646 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
647 int iir_idx = ((struct soc_multi_mixer_control *)
648 kcontrol->private_value)->reg;
649 int band_idx = ((struct soc_multi_mixer_control *)
650 kcontrol->private_value)->shift;
651
652 ucontrol->value.integer.value[0] =
Ben Romberger205e14d2013-02-06 12:31:53 -0800653 (snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
654 (1 << band_idx)) != 0;
Kiran Kandic3b24402012-06-11 00:05:59 -0700655
656 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
657 iir_idx, band_idx,
658 (uint32_t)ucontrol->value.integer.value[0]);
659 return 0;
660}
661
662static int taiko_put_iir_enable_audio_mixer(
663 struct snd_kcontrol *kcontrol,
664 struct snd_ctl_elem_value *ucontrol)
665{
666 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
667 int iir_idx = ((struct soc_multi_mixer_control *)
668 kcontrol->private_value)->reg;
669 int band_idx = ((struct soc_multi_mixer_control *)
670 kcontrol->private_value)->shift;
671 int value = ucontrol->value.integer.value[0];
672
673 /* Mask first 5 bits, 6-8 are reserved */
674 snd_soc_update_bits(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx),
675 (1 << band_idx), (value << band_idx));
676
677 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
Ben Romberger205e14d2013-02-06 12:31:53 -0800678 iir_idx, band_idx,
679 ((snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
680 (1 << band_idx)) != 0));
Kiran Kandic3b24402012-06-11 00:05:59 -0700681 return 0;
682}
683static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
684 int iir_idx, int band_idx,
685 int coeff_idx)
686{
Ben Romberger205e14d2013-02-06 12:31:53 -0800687 uint32_t value = 0;
688
Kiran Kandic3b24402012-06-11 00:05:59 -0700689 /* Address does not automatically update if reading */
690 snd_soc_write(codec,
691 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
Ben Romberger205e14d2013-02-06 12:31:53 -0800692 ((band_idx * BAND_MAX + coeff_idx)
693 * sizeof(uint32_t)) & 0x7F);
694
695 value |= snd_soc_read(codec,
696 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx));
697
698 snd_soc_write(codec,
699 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
700 ((band_idx * BAND_MAX + coeff_idx)
701 * sizeof(uint32_t) + 1) & 0x7F);
702
703 value |= (snd_soc_read(codec,
704 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 8);
705
706 snd_soc_write(codec,
707 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
708 ((band_idx * BAND_MAX + coeff_idx)
709 * sizeof(uint32_t) + 2) & 0x7F);
710
711 value |= (snd_soc_read(codec,
712 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 16);
713
714 snd_soc_write(codec,
715 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
716 ((band_idx * BAND_MAX + coeff_idx)
717 * sizeof(uint32_t) + 3) & 0x7F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700718
719 /* Mask bits top 2 bits since they are reserved */
Ben Romberger205e14d2013-02-06 12:31:53 -0800720 value |= ((snd_soc_read(codec,
721 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) & 0x3F) << 24);
722
723 return value;
Kiran Kandic3b24402012-06-11 00:05:59 -0700724}
725
726static int taiko_get_iir_band_audio_mixer(
727 struct snd_kcontrol *kcontrol,
728 struct snd_ctl_elem_value *ucontrol)
729{
730 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
731 int iir_idx = ((struct soc_multi_mixer_control *)
732 kcontrol->private_value)->reg;
733 int band_idx = ((struct soc_multi_mixer_control *)
734 kcontrol->private_value)->shift;
735
736 ucontrol->value.integer.value[0] =
737 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
738 ucontrol->value.integer.value[1] =
739 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
740 ucontrol->value.integer.value[2] =
741 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
742 ucontrol->value.integer.value[3] =
743 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
744 ucontrol->value.integer.value[4] =
745 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
746
747 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
748 "%s: IIR #%d band #%d b1 = 0x%x\n"
749 "%s: IIR #%d band #%d b2 = 0x%x\n"
750 "%s: IIR #%d band #%d a1 = 0x%x\n"
751 "%s: IIR #%d band #%d a2 = 0x%x\n",
752 __func__, iir_idx, band_idx,
753 (uint32_t)ucontrol->value.integer.value[0],
754 __func__, iir_idx, band_idx,
755 (uint32_t)ucontrol->value.integer.value[1],
756 __func__, iir_idx, band_idx,
757 (uint32_t)ucontrol->value.integer.value[2],
758 __func__, iir_idx, band_idx,
759 (uint32_t)ucontrol->value.integer.value[3],
760 __func__, iir_idx, band_idx,
761 (uint32_t)ucontrol->value.integer.value[4]);
762 return 0;
763}
764
765static void set_iir_band_coeff(struct snd_soc_codec *codec,
766 int iir_idx, int band_idx,
Ben Romberger205e14d2013-02-06 12:31:53 -0800767 uint32_t value)
Kiran Kandic3b24402012-06-11 00:05:59 -0700768{
Kiran Kandic3b24402012-06-11 00:05:59 -0700769 snd_soc_write(codec,
Ben Romberger205e14d2013-02-06 12:31:53 -0800770 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
771 (value & 0xFF));
772
773 snd_soc_write(codec,
774 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
775 (value >> 8) & 0xFF);
776
777 snd_soc_write(codec,
778 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
779 (value >> 16) & 0xFF);
Kiran Kandic3b24402012-06-11 00:05:59 -0700780
781 /* Mask top 2 bits, 7-8 are reserved */
782 snd_soc_write(codec,
783 (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
784 (value >> 24) & 0x3F);
Kiran Kandic3b24402012-06-11 00:05:59 -0700785}
786
787static int taiko_put_iir_band_audio_mixer(
788 struct snd_kcontrol *kcontrol,
789 struct snd_ctl_elem_value *ucontrol)
790{
791 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
792 int iir_idx = ((struct soc_multi_mixer_control *)
793 kcontrol->private_value)->reg;
794 int band_idx = ((struct soc_multi_mixer_control *)
795 kcontrol->private_value)->shift;
796
Ben Romberger205e14d2013-02-06 12:31:53 -0800797 /* Mask top bit it is reserved */
798 /* Updates addr automatically for each B2 write */
799 snd_soc_write(codec,
800 (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
801 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
802
803 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700804 ucontrol->value.integer.value[0]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800805 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700806 ucontrol->value.integer.value[1]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800807 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700808 ucontrol->value.integer.value[2]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800809 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700810 ucontrol->value.integer.value[3]);
Ben Romberger205e14d2013-02-06 12:31:53 -0800811 set_iir_band_coeff(codec, iir_idx, band_idx,
Kiran Kandic3b24402012-06-11 00:05:59 -0700812 ucontrol->value.integer.value[4]);
813
814 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
815 "%s: IIR #%d band #%d b1 = 0x%x\n"
816 "%s: IIR #%d band #%d b2 = 0x%x\n"
817 "%s: IIR #%d band #%d a1 = 0x%x\n"
818 "%s: IIR #%d band #%d a2 = 0x%x\n",
819 __func__, iir_idx, band_idx,
820 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
821 __func__, iir_idx, band_idx,
822 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
823 __func__, iir_idx, band_idx,
824 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
825 __func__, iir_idx, band_idx,
826 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
827 __func__, iir_idx, band_idx,
828 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
829 return 0;
830}
831
Kiran Kandic3b24402012-06-11 00:05:59 -0700832static int taiko_get_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700833 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700834{
835
836 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
837 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700838 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700839 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
840
841 ucontrol->value.integer.value[0] = taiko->comp_enabled[comp];
Kiran Kandic3b24402012-06-11 00:05:59 -0700842 return 0;
843}
844
845static int taiko_set_compander(struct snd_kcontrol *kcontrol,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700846 struct snd_ctl_elem_value *ucontrol)
Kiran Kandic3b24402012-06-11 00:05:59 -0700847{
848 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
849 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
850 int comp = ((struct soc_multi_mixer_control *)
Joonwoo Parkc7731432012-10-17 12:41:44 -0700851 kcontrol->private_value)->shift;
Kiran Kandic3b24402012-06-11 00:05:59 -0700852 int value = ucontrol->value.integer.value[0];
853
Joonwoo Parkc7731432012-10-17 12:41:44 -0700854 pr_debug("%s: Compander %d enable current %d, new %d\n",
855 __func__, comp, taiko->comp_enabled[comp], value);
Kiran Kandic3b24402012-06-11 00:05:59 -0700856 taiko->comp_enabled[comp] = value;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700857
858 if (comp == COMPANDER_1 &&
859 taiko->comp_enabled[comp] == 1) {
860 /* Wavegen to 5 msec */
861 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA);
862 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15);
863 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x2A);
864
865 /* Enable Chopper */
866 snd_soc_update_bits(codec,
867 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x80);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700868
869 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x20);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700870 pr_debug("%s: Enabled Chopper and set wavegen to 5 msec\n",
871 __func__);
872 } else if (comp == COMPANDER_1 &&
873 taiko->comp_enabled[comp] == 0) {
874 /* Wavegen to 20 msec */
875 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDB);
876 snd_soc_write(codec, TAIKO_A_RX_HPH_CNP_WG_TIME, 0x58);
877 snd_soc_write(codec, TAIKO_A_RX_HPH_BIAS_WG_OCP, 0x1A);
878
879 /* Disable CHOPPER block */
880 snd_soc_update_bits(codec,
881 TAIKO_A_RX_HPH_CHOP_CTL, 0x80, 0x00);
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -0700882
883 snd_soc_write(codec, TAIKO_A_NCP_DTEST, 0x10);
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -0700884 pr_debug("%s: Disabled Chopper and set wavegen to 20 msec\n",
885 __func__);
886 }
Kiran Kandic3b24402012-06-11 00:05:59 -0700887 return 0;
888}
889
Joonwoo Parkc7731432012-10-17 12:41:44 -0700890static int taiko_config_gain_compander(struct snd_soc_codec *codec,
891 int comp, bool enable)
892{
893 int ret = 0;
894
895 switch (comp) {
896 case COMPANDER_0:
897 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_GAIN,
898 1 << 2, !enable << 2);
899 break;
900 case COMPANDER_1:
901 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_GAIN,
902 1 << 5, !enable << 5);
903 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_GAIN,
904 1 << 5, !enable << 5);
905 break;
906 case COMPANDER_2:
907 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_1_GAIN,
908 1 << 5, !enable << 5);
909 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_3_GAIN,
910 1 << 5, !enable << 5);
911 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_2_GAIN,
912 1 << 5, !enable << 5);
913 snd_soc_update_bits(codec, TAIKO_A_RX_LINE_4_GAIN,
914 1 << 5, !enable << 5);
915 break;
916 default:
917 WARN_ON(1);
918 ret = -EINVAL;
919 }
920
921 return ret;
922}
923
924static void taiko_discharge_comp(struct snd_soc_codec *codec, int comp)
925{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700926 /* Level meter DIV Factor to 5*/
Joonwoo Parkc7731432012-10-17 12:41:44 -0700927 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700928 0x05 << 4);
929 /* RMS meter Sampling to 0x01 */
930 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8), 0x01);
931
932 /* Worst case timeout for compander CnP sleep timeout */
933 usleep_range(3000, 3000);
934}
935
936static enum wcd9xxx_buck_volt taiko_codec_get_buck_mv(
937 struct snd_soc_codec *codec)
938{
939 int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
940 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
941 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
942 int i;
943
944 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
945 if (!strncmp(pdata->regulator[i].name,
946 WCD9XXX_SUPPLY_BUCK_NAME,
947 sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
948 if ((pdata->regulator[i].min_uV ==
949 WCD9XXX_CDC_BUCK_MV_1P8) ||
950 (pdata->regulator[i].min_uV ==
951 WCD9XXX_CDC_BUCK_MV_2P15))
952 buck_volt = pdata->regulator[i].min_uV;
953 break;
954 }
955 }
956 return buck_volt;
Joonwoo Parkc7731432012-10-17 12:41:44 -0700957}
Kiran Kandic3b24402012-06-11 00:05:59 -0700958
959static int taiko_config_compander(struct snd_soc_dapm_widget *w,
Joonwoo Parkc7731432012-10-17 12:41:44 -0700960 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -0700961{
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700962 int mask, enable_mask;
Kiran Kandic3b24402012-06-11 00:05:59 -0700963 struct snd_soc_codec *codec = w->codec;
964 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parkc7731432012-10-17 12:41:44 -0700965 const int comp = w->shift;
966 const u32 rate = taiko->comp_fs[comp];
967 const struct comp_sample_dependent_params *comp_params =
968 &comp_samp_params[rate];
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700969 enum wcd9xxx_buck_volt buck_mv;
Kiran Kandic3b24402012-06-11 00:05:59 -0700970
Joonwoo Parkc7731432012-10-17 12:41:44 -0700971 pr_debug("%s: %s event %d compander %d, enabled %d", __func__,
972 w->name, event, comp, taiko->comp_enabled[comp]);
973
974 if (!taiko->comp_enabled[comp])
975 return 0;
976
977 /* Compander 0 has single channel */
978 mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700979 enable_mask = (comp == COMPANDER_0 ? 0x02 : 0x03);
980 buck_mv = taiko_codec_get_buck_mv(codec);
Kiran Kandid2b46332012-10-05 12:04:00 -0700981
Kiran Kandic3b24402012-06-11 00:05:59 -0700982 switch (event) {
983 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700984 /* Set compander Sample rate */
985 snd_soc_update_bits(codec,
986 TAIKO_A_CDC_COMP0_FS_CFG + (comp * 8),
987 0x07, rate);
988 /* Set the static gain offset */
989 if (comp == COMPANDER_1
Kuirong Wang865534c2013-06-25 14:32:51 -0700990 && buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
Bhalchandra Gajareed090e62013-03-29 16:11:49 -0700991 snd_soc_update_bits(codec,
992 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
993 0x80, 0x80);
994 } else {
995 snd_soc_update_bits(codec,
996 TAIKO_A_CDC_COMP0_B4_CTL + (comp * 8),
997 0x80, 0x00);
998 }
999 /* Enable RX interpolation path compander clocks */
Joonwoo Parkc7731432012-10-17 12:41:44 -07001000 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
1001 mask << comp_shift[comp],
1002 mask << comp_shift[comp]);
Joonwoo Parkc7731432012-10-17 12:41:44 -07001003 /* Toggle compander reset bits */
1004 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1005 mask << comp_shift[comp],
1006 mask << comp_shift[comp]);
1007 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1008 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001009
1010 /* Set gain source to compander */
1011 taiko_config_gain_compander(codec, comp, true);
1012
1013 /* Compander enable */
1014 snd_soc_update_bits(codec, TAIKO_A_CDC_COMP0_B1_CTL +
1015 (comp * 8), enable_mask, enable_mask);
1016
1017 taiko_discharge_comp(codec, comp);
1018
Joonwoo Parkc7731432012-10-17 12:41:44 -07001019 /* Set sample rate dependent paramater */
Joonwoo Parkc7731432012-10-17 12:41:44 -07001020 snd_soc_write(codec, TAIKO_A_CDC_COMP0_B3_CTL + (comp * 8),
1021 comp_params->rms_meter_resamp_fact);
1022 snd_soc_update_bits(codec,
1023 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
Joonwoo Parkc7731432012-10-17 12:41:44 -07001024 0xF0, comp_params->rms_meter_div_fact << 4);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001025 snd_soc_update_bits(codec,
1026 TAIKO_A_CDC_COMP0_B2_CTL + (comp * 8),
1027 0x0F, comp_params->peak_det_timeout);
Kiran Kandic3b24402012-06-11 00:05:59 -07001028 break;
1029 case SND_SOC_DAPM_PRE_PMD:
Joonwoo Parkc7731432012-10-17 12:41:44 -07001030 /* Disable compander */
1031 snd_soc_update_bits(codec,
1032 TAIKO_A_CDC_COMP0_B1_CTL + (comp * 8),
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001033 enable_mask, 0x00);
1034
1035 /* Toggle compander reset bits */
1036 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1037 mask << comp_shift[comp],
1038 mask << comp_shift[comp]);
1039 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
1040 mask << comp_shift[comp], 0);
1041
Joonwoo Parkc7731432012-10-17 12:41:44 -07001042 /* Turn off the clock for compander in pair */
1043 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
1044 mask << comp_shift[comp], 0);
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07001045
Joonwoo Parkc7731432012-10-17 12:41:44 -07001046 /* Set gain source to register */
1047 taiko_config_gain_compander(codec, comp, false);
Kiran Kandic3b24402012-06-11 00:05:59 -07001048 break;
1049 }
1050 return 0;
1051}
1052
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001053
Kiran Kandic3b24402012-06-11 00:05:59 -07001054
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001055static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
1056static const struct soc_enum taiko_anc_func_enum =
1057 SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
1058
1059static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
1060static const struct soc_enum tabla_ear_pa_gain_enum[] = {
1061 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
1062};
1063
Kiran Kandic3b24402012-06-11 00:05:59 -07001064/*cut of frequency for high pass filter*/
1065static const char * const cf_text[] = {
1066 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
1067};
1068
1069static const struct soc_enum cf_dec1_enum =
1070 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
1071
1072static const struct soc_enum cf_dec2_enum =
1073 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
1074
1075static const struct soc_enum cf_dec3_enum =
1076 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
1077
1078static const struct soc_enum cf_dec4_enum =
1079 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
1080
1081static const struct soc_enum cf_dec5_enum =
1082 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
1083
1084static const struct soc_enum cf_dec6_enum =
1085 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
1086
1087static const struct soc_enum cf_dec7_enum =
1088 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
1089
1090static const struct soc_enum cf_dec8_enum =
1091 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
1092
1093static const struct soc_enum cf_dec9_enum =
1094 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
1095
1096static const struct soc_enum cf_dec10_enum =
1097 SOC_ENUM_SINGLE(TAIKO_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
1098
1099static const struct soc_enum cf_rxmix1_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001100 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX1_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001101
1102static const struct soc_enum cf_rxmix2_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001103 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX2_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001104
1105static const struct soc_enum cf_rxmix3_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001106 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001107
1108static const struct soc_enum cf_rxmix4_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001109 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001110
1111static const struct soc_enum cf_rxmix5_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001112 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX5_B4_CTL, 0, 3, cf_text)
Kiran Kandic3b24402012-06-11 00:05:59 -07001113;
1114static const struct soc_enum cf_rxmix6_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001115 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001116
1117static const struct soc_enum cf_rxmix7_enum =
Joonwoo Park2000a982013-03-01 14:50:31 -08001118 SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 0, 3, cf_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001119
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001120static const char * const class_h_dsm_text[] = {
1121 "ZERO", "DSM_HPHL_RX1", "DSM_SPKR_RX7"
1122};
1123
1124static const struct soc_enum class_h_dsm_enum =
1125 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_CLSH_CTL, 4, 3, class_h_dsm_text);
1126
1127static const struct snd_kcontrol_new class_h_dsm_mux =
1128 SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
1129
Kiran Kandiddbeaa32013-10-06 14:40:11 -07001130static const char *const taiko_conn_mad_text[] = {
1131 "ADC_MB", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "NOTUSED1",
1132 "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "NOTUSED2",
1133 "NOTUSED3"};
1134
1135static const struct soc_enum taiko_conn_mad_enum =
1136 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_conn_mad_text),
1137 taiko_conn_mad_text);
1138
1139
1140static int taiko_mad_input_get(struct snd_kcontrol *kcontrol,
1141 struct snd_ctl_elem_value *ucontrol)
1142{
1143 u8 taiko_mad_input;
1144 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1145
1146 taiko_mad_input = snd_soc_read(codec, TAIKO_A_CDC_CONN_MAD);
1147
1148 taiko_mad_input = taiko_mad_input & 0x0F;
1149
1150 ucontrol->value.integer.value[0] = taiko_mad_input;
1151
1152 pr_debug("%s: taiko_mad_input = %s\n", __func__,
1153 taiko_conn_mad_text[taiko_mad_input]);
1154
1155 return 0;
1156}
1157
1158static int taiko_mad_input_put(struct snd_kcontrol *kcontrol,
1159 struct snd_ctl_elem_value *ucontrol)
1160{
1161 u8 taiko_mad_input;
1162 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1163 struct snd_soc_card *card = codec->card;
1164 char mad_amic_input_widget[6];
1165 u32 adc;
1166 const char *mad_input_widget;
1167 u32 mic_bias_found = 0;
1168 u32 i;
1169 int ret = 0;
1170
1171 taiko_mad_input = ucontrol->value.integer.value[0];
1172
1173 pr_debug("%s: taiko_mad_input = %s\n", __func__,
1174 taiko_conn_mad_text[taiko_mad_input]);
1175
1176 if (!strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED1") ||
1177 !strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED2") ||
1178 !strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED3") ||
1179 !strcmp(taiko_conn_mad_text[taiko_mad_input], "ADC_MB")) {
1180 pr_info("%s: taiko mad input is set to unsupported input = %s\n",
1181 __func__, taiko_conn_mad_text[taiko_mad_input]);
1182 return -EINVAL;
1183 }
1184
1185 if (strnstr(taiko_conn_mad_text[taiko_mad_input],
1186 "ADC", sizeof("ADC"))) {
1187 ret = kstrtouint(strpbrk(taiko_conn_mad_text[taiko_mad_input]
1188 , "123456"), 10, &adc);
1189 if ((ret < 0) || (adc > 6)) {
1190 pr_err("%s: Invalid ADC = %s\n", __func__,
1191 taiko_conn_mad_text[taiko_mad_input]);
1192 ret = -EINVAL;
1193 }
1194
1195 snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
1196
1197 mad_input_widget = mad_amic_input_widget;
1198 pr_debug("%s: taiko amic input widget = %s\n", __func__,
1199 mad_amic_input_widget);
1200 } else {
1201 /* DMIC type input widget*/
1202 mad_input_widget = taiko_conn_mad_text[taiko_mad_input];
1203 }
1204
1205 pr_debug("%s: taiko input widget = %s\n", __func__, mad_input_widget);
1206
1207 for (i = 0; i < card->num_dapm_routes; i++) {
1208
1209 if (!strncmp(card->dapm_routes[i].sink,
1210 mad_input_widget, strlen(mad_input_widget))) {
1211
1212 if (strnstr(card->dapm_routes[i].source,
1213 "MIC BIAS1", sizeof("MIC BIAS1"))) {
1214 mic_bias_found = 1;
1215 break;
1216 } else if (strnstr(card->dapm_routes[i].source,
1217 "MIC BIAS2", sizeof("MIC BIAS2"))) {
1218 mic_bias_found = 2;
1219 break;
1220 } else if (strnstr(card->dapm_routes[i].source,
1221 "MIC BIAS3", sizeof("MIC BIAS3"))) {
1222 mic_bias_found = 3;
1223 break;
1224 } else if (strnstr(card->dapm_routes[i].source,
1225 "MIC BIAS4", sizeof("MIC BIAS4"))) {
1226 mic_bias_found = 4;
1227 break;
1228 }
1229 }
1230 }
1231
1232 if (mic_bias_found) {
1233 pr_debug("%s: source mic bias = %s. sink = %s\n", __func__,
1234 card->dapm_routes[i].source,
1235 card->dapm_routes[i].sink);
1236
1237 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
1238 0x0F, taiko_mad_input);
1239 snd_soc_update_bits(codec, TAIKO_A_MAD_ANA_CTRL,
1240 0x07, mic_bias_found);
1241 return 0;
1242 } else {
1243 pr_err("%s: mic bias source not found for input = %s\n",
1244 __func__, mad_input_widget);
1245 return -EINVAL;
1246 }
1247}
1248
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08001249
Kiran Kandic3b24402012-06-11 00:05:59 -07001250static const struct snd_kcontrol_new taiko_snd_controls[] = {
1251
Kiran Kandic3b24402012-06-11 00:05:59 -07001252 SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
1253 -84, 40, digital_gain),
1254 SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
1255 -84, 40, digital_gain),
1256 SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
1257 -84, 40, digital_gain),
1258 SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
1259 -84, 40, digital_gain),
1260 SOC_SINGLE_S8_TLV("RX5 Digital Volume", TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
1261 -84, 40, digital_gain),
1262 SOC_SINGLE_S8_TLV("RX6 Digital Volume", TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
1263 -84, 40, digital_gain),
1264 SOC_SINGLE_S8_TLV("RX7 Digital Volume", TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
1265 -84, 40, digital_gain),
1266
1267 SOC_SINGLE_S8_TLV("DEC1 Volume", TAIKO_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
1268 digital_gain),
1269 SOC_SINGLE_S8_TLV("DEC2 Volume", TAIKO_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
1270 digital_gain),
1271 SOC_SINGLE_S8_TLV("DEC3 Volume", TAIKO_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
1272 digital_gain),
1273 SOC_SINGLE_S8_TLV("DEC4 Volume", TAIKO_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
1274 digital_gain),
1275 SOC_SINGLE_S8_TLV("DEC5 Volume", TAIKO_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
1276 digital_gain),
1277 SOC_SINGLE_S8_TLV("DEC6 Volume", TAIKO_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
1278 digital_gain),
1279 SOC_SINGLE_S8_TLV("DEC7 Volume", TAIKO_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
1280 digital_gain),
1281 SOC_SINGLE_S8_TLV("DEC8 Volume", TAIKO_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
1282 digital_gain),
1283 SOC_SINGLE_S8_TLV("DEC9 Volume", TAIKO_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
1284 digital_gain),
1285 SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
1286 40, digital_gain),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001287
Kiran Kandic3b24402012-06-11 00:05:59 -07001288 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
1289 40, digital_gain),
1290 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
1291 40, digital_gain),
1292 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAIKO_A_CDC_IIR1_GAIN_B3_CTL, -84,
1293 40, digital_gain),
1294 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
1295 40, digital_gain),
Fred Oh456fcb52013-02-28 19:08:15 -08001296 SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
1297 40, digital_gain),
1298 SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
1299 40, digital_gain),
1300 SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
1301 40, digital_gain),
1302 SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
1303 40, digital_gain),
Kiran Kandic3b24402012-06-11 00:05:59 -07001304
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001305 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
Kiran Kandic3b24402012-06-11 00:05:59 -07001306 taiko_put_anc_slot),
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08001307 SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
1308 taiko_put_anc_func),
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001309
Kiran Kandic3b24402012-06-11 00:05:59 -07001310 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
1311 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
1312 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
1313 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
1314 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
1315 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
1316 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
1317 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
1318 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
1319 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
1320
1321 SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
1322 SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
1323 SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
1324 SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
1325 SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
1326 SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
1327 SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
1328 SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
1329 SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
1330 SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
1331
1332 SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
1333 SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
1334 SOC_SINGLE("RX3 HPF Switch", TAIKO_A_CDC_RX3_B5_CTL, 2, 1, 0),
1335 SOC_SINGLE("RX4 HPF Switch", TAIKO_A_CDC_RX4_B5_CTL, 2, 1, 0),
1336 SOC_SINGLE("RX5 HPF Switch", TAIKO_A_CDC_RX5_B5_CTL, 2, 1, 0),
1337 SOC_SINGLE("RX6 HPF Switch", TAIKO_A_CDC_RX6_B5_CTL, 2, 1, 0),
1338 SOC_SINGLE("RX7 HPF Switch", TAIKO_A_CDC_RX7_B5_CTL, 2, 1, 0),
1339
1340 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
1341 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
1342 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
1343 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
1344 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
1345 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
1346 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
1347
1348 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
1349 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1350 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
1351 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1352 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
1353 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1354 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
1355 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1356 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
1357 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1358 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
1359 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1360 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
1361 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1362 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
1363 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1364 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
1365 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1366 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
1367 taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
1368
1369 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
1370 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1371 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
1372 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1373 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
1374 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1375 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
1376 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1377 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
1378 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1379 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
1380 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1381 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
1382 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1383 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
1384 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1385 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
1386 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1387 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
1388 taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
1389
Joonwoo Parkc7731432012-10-17 12:41:44 -07001390 SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
1391 taiko_get_compander, taiko_set_compander),
1392 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
1393 taiko_get_compander, taiko_set_compander),
1394 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
1395 taiko_get_compander, taiko_set_compander),
Kiran Kandic3b24402012-06-11 00:05:59 -07001396
Kiran Kandiddbeaa32013-10-06 14:40:11 -07001397 SOC_ENUM_EXT("MAD Input", taiko_conn_mad_enum,
1398 taiko_mad_input_get, taiko_mad_input_put),
1399
Kiran Kandic3b24402012-06-11 00:05:59 -07001400};
1401
Kiran Kandiec0db5c2013-03-08 16:03:58 -08001402static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
1403 struct snd_ctl_elem_value *ucontrol)
1404{
1405 u8 ear_pa_gain;
1406 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1407
1408 ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
1409
1410 ear_pa_gain = ear_pa_gain >> 5;
1411
1412 ucontrol->value.integer.value[0] = ear_pa_gain;
1413
1414 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
1415
1416 return 0;
1417}
1418
1419static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
1420 struct snd_ctl_elem_value *ucontrol)
1421{
1422 u8 ear_pa_gain;
1423 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1424
1425 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
1426 ucontrol->value.integer.value[0]);
1427
1428 ear_pa_gain = ucontrol->value.integer.value[0] << 5;
1429
1430 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
1431 return 0;
1432}
1433
1434static const char * const taiko_1_x_ear_pa_gain_text[] = {
1435 "POS_6_DB", "UNDEFINED_1", "UNDEFINED_2", "UNDEFINED_3", "POS_2_DB",
1436 "NEG_2P5_DB", "UNDEFINED_4", "NEG_12_DB"
1437};
1438
1439static const struct soc_enum taiko_1_x_ear_pa_gain_enum =
1440 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_1_x_ear_pa_gain_text),
1441 taiko_1_x_ear_pa_gain_text);
1442
1443static const struct snd_kcontrol_new taiko_1_x_analog_gain_controls[] = {
1444
1445 SOC_ENUM_EXT("EAR PA Gain", taiko_1_x_ear_pa_gain_enum,
1446 taiko_pa_gain_get, taiko_pa_gain_put),
1447
1448 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1449 line_gain),
1450 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1451 line_gain),
1452
1453 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1454 line_gain),
1455 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1456 line_gain),
1457 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1458 line_gain),
1459 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1460 line_gain),
1461
1462 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
1463 line_gain),
1464
1465 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
1466 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
1467 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
1468 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
1469 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
1470 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
1471};
1472
1473static const char * const taiko_2_x_ear_pa_gain_text[] = {
1474 "POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB",
1475 "POS_0_DB", "NEG_2P5_DB", "UNDEFINED", "NEG_12_DB"
1476};
1477
1478static const struct soc_enum taiko_2_x_ear_pa_gain_enum =
1479 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_2_x_ear_pa_gain_text),
1480 taiko_2_x_ear_pa_gain_text);
1481
1482static const struct snd_kcontrol_new taiko_2_x_analog_gain_controls[] = {
1483
1484 SOC_ENUM_EXT("EAR PA Gain", taiko_2_x_ear_pa_gain_enum,
1485 taiko_pa_gain_get, taiko_pa_gain_put),
1486
1487 SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
1488 line_gain),
1489 SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
1490 line_gain),
1491
1492 SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
1493 line_gain),
1494 SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
1495 line_gain),
1496 SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
1497 line_gain),
1498 SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
1499 line_gain),
1500
1501 SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 8, 1,
1502 line_gain),
1503
1504 SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_CDC_TX_1_GAIN, 2, 19, 0,
1505 analog_gain),
1506 SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_CDC_TX_2_GAIN, 2, 19, 0,
1507 analog_gain),
1508 SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_CDC_TX_3_GAIN, 2, 19, 0,
1509 analog_gain),
1510 SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_CDC_TX_4_GAIN, 2, 19, 0,
1511 analog_gain),
1512 SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_CDC_TX_5_GAIN, 2, 19, 0,
1513 analog_gain),
1514 SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_CDC_TX_6_GAIN, 2, 19, 0,
1515 analog_gain),
1516};
1517
Joonwoo Parkb755e9e2013-05-28 13:14:05 -07001518static int taiko_hph_impedance_get(struct snd_kcontrol *kcontrol,
1519 struct snd_ctl_elem_value *ucontrol)
1520{
1521 uint32_t zl, zr;
1522 bool hphr;
1523 struct soc_multi_mixer_control *mc;
1524 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1525 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
1526
1527 mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
1528
1529 hphr = mc->shift;
1530 wcd9xxx_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
1531 pr_debug("%s: zl %u, zr %u\n", __func__, zl, zr);
1532 ucontrol->value.integer.value[0] = hphr ? zr : zl;
1533
1534 return 0;
1535}
1536
1537static const struct snd_kcontrol_new impedance_detect_controls[] = {
1538 SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
1539 taiko_hph_impedance_get, NULL),
1540 SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
1541 taiko_hph_impedance_get, NULL),
1542};
1543
Kiran Kandic3b24402012-06-11 00:05:59 -07001544static const char * const rx_mix1_text[] = {
1545 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
1546 "RX5", "RX6", "RX7"
1547};
1548
1549static const char * const rx_mix2_text[] = {
1550 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
1551};
1552
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001553static const char * const rx_rdac5_text[] = {
1554 "DEM4", "DEM3_INV"
Kiran Kandic3b24402012-06-11 00:05:59 -07001555};
1556
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001557static const char * const rx_rdac7_text[] = {
1558 "DEM6", "DEM5_INV"
1559};
1560
1561
Kiran Kandic3b24402012-06-11 00:05:59 -07001562static const char * const sb_tx1_mux_text[] = {
1563 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1564 "DEC1"
1565};
1566
1567static const char * const sb_tx2_mux_text[] = {
1568 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1569 "DEC2"
1570};
1571
1572static const char * const sb_tx3_mux_text[] = {
1573 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1574 "DEC3"
1575};
1576
1577static const char * const sb_tx4_mux_text[] = {
1578 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1579 "DEC4"
1580};
1581
1582static const char * const sb_tx5_mux_text[] = {
1583 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1584 "DEC5"
1585};
1586
1587static const char * const sb_tx6_mux_text[] = {
1588 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1589 "DEC6"
1590};
1591
1592static const char * const sb_tx7_to_tx10_mux_text[] = {
1593 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
1594 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1595 "DEC9", "DEC10"
1596};
1597
1598static const char * const dec1_mux_text[] = {
1599 "ZERO", "DMIC1", "ADC6",
1600};
1601
1602static const char * const dec2_mux_text[] = {
1603 "ZERO", "DMIC2", "ADC5",
1604};
1605
1606static const char * const dec3_mux_text[] = {
1607 "ZERO", "DMIC3", "ADC4",
1608};
1609
1610static const char * const dec4_mux_text[] = {
1611 "ZERO", "DMIC4", "ADC3",
1612};
1613
1614static const char * const dec5_mux_text[] = {
1615 "ZERO", "DMIC5", "ADC2",
1616};
1617
1618static const char * const dec6_mux_text[] = {
1619 "ZERO", "DMIC6", "ADC1",
1620};
1621
1622static const char * const dec7_mux_text[] = {
1623 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
1624};
1625
1626static const char * const dec8_mux_text[] = {
1627 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
1628};
1629
1630static const char * const dec9_mux_text[] = {
1631 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
1632};
1633
1634static const char * const dec10_mux_text[] = {
1635 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
1636};
1637
1638static const char * const anc_mux_text[] = {
1639 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
1640 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
1641};
1642
1643static const char * const anc1_fb_mux_text[] = {
1644 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
1645};
1646
Fred Oh456fcb52013-02-28 19:08:15 -08001647static const char * const iir_inp1_text[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07001648 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
1649 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
1650};
1651
1652static const struct soc_enum rx_mix1_inp1_chain_enum =
1653 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
1654
1655static const struct soc_enum rx_mix1_inp2_chain_enum =
1656 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
1657
1658static const struct soc_enum rx_mix1_inp3_chain_enum =
1659 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
1660
1661static const struct soc_enum rx2_mix1_inp1_chain_enum =
1662 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
1663
1664static const struct soc_enum rx2_mix1_inp2_chain_enum =
1665 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
1666
1667static const struct soc_enum rx3_mix1_inp1_chain_enum =
1668 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
1669
1670static const struct soc_enum rx3_mix1_inp2_chain_enum =
1671 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
1672
1673static const struct soc_enum rx4_mix1_inp1_chain_enum =
1674 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
1675
1676static const struct soc_enum rx4_mix1_inp2_chain_enum =
1677 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
1678
1679static const struct soc_enum rx5_mix1_inp1_chain_enum =
1680 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
1681
1682static const struct soc_enum rx5_mix1_inp2_chain_enum =
1683 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
1684
1685static const struct soc_enum rx6_mix1_inp1_chain_enum =
1686 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
1687
1688static const struct soc_enum rx6_mix1_inp2_chain_enum =
1689 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
1690
1691static const struct soc_enum rx7_mix1_inp1_chain_enum =
1692 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
1693
1694static const struct soc_enum rx7_mix1_inp2_chain_enum =
1695 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
1696
1697static const struct soc_enum rx1_mix2_inp1_chain_enum =
1698 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
1699
1700static const struct soc_enum rx1_mix2_inp2_chain_enum =
1701 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
1702
1703static const struct soc_enum rx2_mix2_inp1_chain_enum =
1704 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
1705
1706static const struct soc_enum rx2_mix2_inp2_chain_enum =
1707 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
1708
1709static const struct soc_enum rx7_mix2_inp1_chain_enum =
1710 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
1711
1712static const struct soc_enum rx7_mix2_inp2_chain_enum =
1713 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
1714
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001715static const struct soc_enum rx_rdac5_enum =
1716 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001717
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001718static const struct soc_enum rx_rdac7_enum =
1719 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001720
1721static const struct soc_enum sb_tx1_mux_enum =
1722 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
1723
1724static const struct soc_enum sb_tx2_mux_enum =
1725 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
1726
1727static const struct soc_enum sb_tx3_mux_enum =
1728 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
1729
1730static const struct soc_enum sb_tx4_mux_enum =
1731 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
1732
1733static const struct soc_enum sb_tx5_mux_enum =
1734 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
1735
1736static const struct soc_enum sb_tx6_mux_enum =
1737 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
1738
1739static const struct soc_enum sb_tx7_mux_enum =
1740 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
1741 sb_tx7_to_tx10_mux_text);
1742
1743static const struct soc_enum sb_tx8_mux_enum =
1744 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
1745 sb_tx7_to_tx10_mux_text);
1746
1747static const struct soc_enum sb_tx9_mux_enum =
1748 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
1749 sb_tx7_to_tx10_mux_text);
1750
1751static const struct soc_enum sb_tx10_mux_enum =
1752 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
1753 sb_tx7_to_tx10_mux_text);
1754
1755static const struct soc_enum dec1_mux_enum =
1756 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
1757
1758static const struct soc_enum dec2_mux_enum =
1759 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
1760
1761static const struct soc_enum dec3_mux_enum =
1762 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
1763
1764static const struct soc_enum dec4_mux_enum =
1765 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
1766
1767static const struct soc_enum dec5_mux_enum =
1768 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
1769
1770static const struct soc_enum dec6_mux_enum =
1771 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
1772
1773static const struct soc_enum dec7_mux_enum =
1774 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
1775
1776static const struct soc_enum dec8_mux_enum =
1777 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
1778
1779static const struct soc_enum dec9_mux_enum =
1780 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
1781
1782static const struct soc_enum dec10_mux_enum =
1783 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
1784
1785static const struct soc_enum anc1_mux_enum =
1786 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
1787
1788static const struct soc_enum anc2_mux_enum =
1789 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
1790
1791static const struct soc_enum anc1_fb_mux_enum =
1792 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
1793
1794static const struct soc_enum iir1_inp1_mux_enum =
Fred Oh456fcb52013-02-28 19:08:15 -08001795 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
1796
1797static const struct soc_enum iir2_inp1_mux_enum =
1798 SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
Kiran Kandic3b24402012-06-11 00:05:59 -07001799
1800static const struct snd_kcontrol_new rx_mix1_inp1_mux =
1801 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
1802
1803static const struct snd_kcontrol_new rx_mix1_inp2_mux =
1804 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
1805
1806static const struct snd_kcontrol_new rx_mix1_inp3_mux =
1807 SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
1808
1809static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
1810 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
1811
1812static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
1813 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
1814
1815static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
1816 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
1817
1818static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
1819 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
1820
1821static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
1822 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
1823
1824static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
1825 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
1826
1827static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
1828 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
1829
1830static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
1831 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
1832
1833static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
1834 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
1835
1836static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
1837 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
1838
1839static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
1840 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
1841
1842static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
1843 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
1844
1845static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
1846 SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
1847
1848static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
1849 SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
1850
1851static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
1852 SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
1853
1854static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
1855 SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
1856
1857static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
1858 SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
1859
1860static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
1861 SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
1862
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001863static const struct snd_kcontrol_new rx_dac5_mux =
1864 SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001865
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02001866static const struct snd_kcontrol_new rx_dac7_mux =
1867 SOC_DAPM_ENUM("RDAC7 MUX Mux", rx_rdac7_enum);
Kiran Kandic3b24402012-06-11 00:05:59 -07001868
1869static const struct snd_kcontrol_new sb_tx1_mux =
1870 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
1871
1872static const struct snd_kcontrol_new sb_tx2_mux =
1873 SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
1874
1875static const struct snd_kcontrol_new sb_tx3_mux =
1876 SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
1877
1878static const struct snd_kcontrol_new sb_tx4_mux =
1879 SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
1880
1881static const struct snd_kcontrol_new sb_tx5_mux =
1882 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
1883
1884static const struct snd_kcontrol_new sb_tx6_mux =
1885 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
1886
1887static const struct snd_kcontrol_new sb_tx7_mux =
1888 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
1889
1890static const struct snd_kcontrol_new sb_tx8_mux =
1891 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
1892
1893static const struct snd_kcontrol_new sb_tx9_mux =
1894 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
1895
1896static const struct snd_kcontrol_new sb_tx10_mux =
1897 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
1898
1899
1900static int wcd9320_put_dec_enum(struct snd_kcontrol *kcontrol,
1901 struct snd_ctl_elem_value *ucontrol)
1902{
1903 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1904 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1905 struct snd_soc_codec *codec = w->codec;
1906 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1907 unsigned int dec_mux, decimator;
1908 char *dec_name = NULL;
1909 char *widget_name = NULL;
1910 char *temp;
1911 u16 tx_mux_ctl_reg;
1912 u8 adc_dmic_sel = 0x0;
1913 int ret = 0;
1914
1915 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1916 return -EINVAL;
1917
1918 dec_mux = ucontrol->value.enumerated.item[0];
1919
1920 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
1921 if (!widget_name)
1922 return -ENOMEM;
1923 temp = widget_name;
1924
1925 dec_name = strsep(&widget_name, " ");
1926 widget_name = temp;
1927 if (!dec_name) {
1928 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
1929 ret = -EINVAL;
1930 goto out;
1931 }
1932
1933 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
1934 if (ret < 0) {
1935 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
1936 ret = -EINVAL;
1937 goto out;
1938 }
1939
1940 dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
1941 , __func__, w->name, decimator, dec_mux);
1942
1943
1944 switch (decimator) {
1945 case 1:
1946 case 2:
1947 case 3:
1948 case 4:
1949 case 5:
1950 case 6:
1951 if (dec_mux == 1)
1952 adc_dmic_sel = 0x1;
1953 else
1954 adc_dmic_sel = 0x0;
1955 break;
1956 case 7:
1957 case 8:
1958 case 9:
1959 case 10:
1960 if ((dec_mux == 1) || (dec_mux == 2))
1961 adc_dmic_sel = 0x1;
1962 else
1963 adc_dmic_sel = 0x0;
1964 break;
1965 default:
1966 pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
1967 ret = -EINVAL;
1968 goto out;
1969 }
1970
1971 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
1972
1973 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
1974
1975 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1976
1977out:
1978 kfree(widget_name);
1979 return ret;
1980}
1981
1982#define WCD9320_DEC_ENUM(xname, xenum) \
1983{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1984 .info = snd_soc_info_enum_double, \
1985 .get = snd_soc_dapm_get_enum_double, \
1986 .put = wcd9320_put_dec_enum, \
1987 .private_value = (unsigned long)&xenum }
1988
1989static const struct snd_kcontrol_new dec1_mux =
1990 WCD9320_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
1991
1992static const struct snd_kcontrol_new dec2_mux =
1993 WCD9320_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
1994
1995static const struct snd_kcontrol_new dec3_mux =
1996 WCD9320_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
1997
1998static const struct snd_kcontrol_new dec4_mux =
1999 WCD9320_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
2000
2001static const struct snd_kcontrol_new dec5_mux =
2002 WCD9320_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
2003
2004static const struct snd_kcontrol_new dec6_mux =
2005 WCD9320_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
2006
2007static const struct snd_kcontrol_new dec7_mux =
2008 WCD9320_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
2009
2010static const struct snd_kcontrol_new dec8_mux =
2011 WCD9320_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
2012
2013static const struct snd_kcontrol_new dec9_mux =
2014 WCD9320_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
2015
2016static const struct snd_kcontrol_new dec10_mux =
2017 WCD9320_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
2018
2019static const struct snd_kcontrol_new iir1_inp1_mux =
2020 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
2021
Fred Oh456fcb52013-02-28 19:08:15 -08002022static const struct snd_kcontrol_new iir2_inp1_mux =
2023 SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
2024
Kiran Kandic3b24402012-06-11 00:05:59 -07002025static const struct snd_kcontrol_new anc1_mux =
2026 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
2027
2028static const struct snd_kcontrol_new anc2_mux =
2029 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
2030
2031static const struct snd_kcontrol_new anc1_fb_mux =
2032 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
2033
2034static const struct snd_kcontrol_new dac1_switch[] = {
2035 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_EAR_EN, 5, 1, 0)
2036};
2037static const struct snd_kcontrol_new hphl_switch[] = {
2038 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
2039};
2040
2041static const struct snd_kcontrol_new hphl_pa_mix[] = {
2042 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2043 7, 1, 0),
2044};
2045
2046static const struct snd_kcontrol_new hphr_pa_mix[] = {
2047 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2048 6, 1, 0),
2049};
2050
2051static const struct snd_kcontrol_new ear_pa_mix[] = {
2052 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2053 5, 1, 0),
2054};
2055static const struct snd_kcontrol_new lineout1_pa_mix[] = {
2056 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2057 4, 1, 0),
2058};
2059
2060static const struct snd_kcontrol_new lineout2_pa_mix[] = {
2061 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2062 3, 1, 0),
2063};
2064
2065static const struct snd_kcontrol_new lineout3_pa_mix[] = {
2066 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2067 2, 1, 0),
2068};
2069
2070static const struct snd_kcontrol_new lineout4_pa_mix[] = {
2071 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
2072 1, 1, 0),
2073};
2074
2075static const struct snd_kcontrol_new lineout3_ground_switch =
2076 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
2077
2078static const struct snd_kcontrol_new lineout4_ground_switch =
2079 SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
2080
Joonwoo Park9ead0e92013-03-18 11:33:33 -07002081static const struct snd_kcontrol_new aif4_mad_switch =
2082 SOC_DAPM_SINGLE("Switch", TAIKO_A_CDC_CLK_OTHR_CTL, 4, 1, 0);
2083
Kuirong Wang906ac472012-07-09 12:54:44 -07002084/* virtual port entries */
2085static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
2086 struct snd_ctl_elem_value *ucontrol)
2087{
2088 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2089 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2090
2091 ucontrol->value.integer.value[0] = widget->value;
2092 return 0;
2093}
2094
2095static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
2096 struct snd_ctl_elem_value *ucontrol)
2097{
2098 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2099 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2100 struct snd_soc_codec *codec = widget->codec;
2101 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2102 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2103 struct soc_multi_mixer_control *mixer =
2104 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2105 u32 dai_id = widget->shift;
2106 u32 port_id = mixer->shift;
2107 u32 enable = ucontrol->value.integer.value[0];
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002108 u32 vtable = vport_check_table[dai_id];
Kuirong Wang906ac472012-07-09 12:54:44 -07002109
2110
2111 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2112 widget->name, ucontrol->id.name, widget->value, widget->shift,
2113 ucontrol->value.integer.value[0]);
2114
2115 mutex_lock(&codec->mutex);
2116
2117 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
2118 if (dai_id != AIF1_CAP) {
2119 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2120 __func__);
2121 mutex_unlock(&codec->mutex);
2122 return -EINVAL;
2123 }
2124 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07002125 switch (dai_id) {
2126 case AIF1_CAP:
2127 case AIF2_CAP:
2128 case AIF3_CAP:
2129 /* only add to the list if value not set
2130 */
2131 if (enable && !(widget->value & 1 << port_id)) {
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002132
2133 if (taiko_p->intf_type ==
2134 WCD9XXX_INTERFACE_TYPE_SLIMBUS)
2135 vtable = vport_check_table[dai_id];
2136 if (taiko_p->intf_type ==
2137 WCD9XXX_INTERFACE_TYPE_I2C)
2138 vtable = vport_i2s_check_table[dai_id];
2139
Venkat Sudhira41630a2012-10-27 00:57:31 -07002140 if (wcd9xxx_tx_vport_validation(
Venkat Sudhir96dd28c2012-12-04 17:00:19 -08002141 vtable,
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002142 port_id,
2143 taiko_p->dai)) {
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002144 dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
Venkat Sudhira41630a2012-10-27 00:57:31 -07002145 __func__, port_id + 1);
2146 mutex_unlock(&codec->mutex);
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002147 return 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -07002148 }
2149 widget->value |= 1 << port_id;
2150 list_add_tail(&core->tx_chs[port_id].list,
Kuirong Wang906ac472012-07-09 12:54:44 -07002151 &taiko_p->dai[dai_id].wcd9xxx_ch_list
Venkat Sudhira41630a2012-10-27 00:57:31 -07002152 );
2153 } else if (!enable && (widget->value & 1 << port_id)) {
2154 widget->value &= ~(1 << port_id);
2155 list_del_init(&core->tx_chs[port_id].list);
2156 } else {
2157 if (enable)
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002158 dev_dbg(codec->dev, "%s: TX%u port is used by\n"
Venkat Sudhira41630a2012-10-27 00:57:31 -07002159 "this virtual port\n",
2160 __func__, port_id + 1);
2161 else
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002162 dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
Venkat Sudhira41630a2012-10-27 00:57:31 -07002163 "this virtual port\n",
2164 __func__, port_id + 1);
2165 /* avoid update power function */
2166 mutex_unlock(&codec->mutex);
2167 return 0;
2168 }
2169 break;
2170 default:
2171 pr_err("Unknown AIF %d\n", dai_id);
Kuirong Wang906ac472012-07-09 12:54:44 -07002172 mutex_unlock(&codec->mutex);
Venkat Sudhira41630a2012-10-27 00:57:31 -07002173 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07002174 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002175 pr_debug("%s: name %s sname %s updated value %u shift %d\n", __func__,
2176 widget->name, widget->sname, widget->value, widget->shift);
2177
2178 snd_soc_dapm_mixer_update_power(widget, kcontrol, enable);
2179
2180 mutex_unlock(&codec->mutex);
2181 return 0;
2182}
2183
2184static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
2185 struct snd_ctl_elem_value *ucontrol)
2186{
2187 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2188 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2189
2190 ucontrol->value.enumerated.item[0] = widget->value;
2191 return 0;
2192}
2193
2194static const char *const slim_rx_mux_text[] = {
2195 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB"
2196};
2197
2198static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
2199 struct snd_ctl_elem_value *ucontrol)
2200{
2201 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
2202 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2203 struct snd_soc_codec *codec = widget->codec;
2204 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
2205 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2206 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2207 u32 port_id = widget->shift;
2208
2209 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2210 widget->name, ucontrol->id.name, widget->value, widget->shift,
2211 ucontrol->value.integer.value[0]);
2212
2213 widget->value = ucontrol->value.enumerated.item[0];
2214
2215 mutex_lock(&codec->mutex);
2216
2217 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhir994193b2012-12-17 17:30:51 -08002218 if (widget->value > 2) {
Kuirong Wang906ac472012-07-09 12:54:44 -07002219 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2220 __func__);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002221 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002222 }
2223 }
2224 /* value need to match the Virtual port and AIF number
2225 */
2226 switch (widget->value) {
2227 case 0:
2228 list_del_init(&core->rx_chs[port_id].list);
2229 break;
2230 case 1:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002231 if (wcd9xxx_rx_vport_validation(port_id +
2232 TAIKO_RX_PORT_START_NUMBER,
2233 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
2234 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2235 __func__, port_id + 1);
2236 goto rtn;
2237 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002238 list_add_tail(&core->rx_chs[port_id].list,
2239 &taiko_p->dai[AIF1_PB].wcd9xxx_ch_list);
2240 break;
2241 case 2:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002242 if (wcd9xxx_rx_vport_validation(port_id +
2243 TAIKO_RX_PORT_START_NUMBER,
2244 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
2245 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2246 __func__, port_id + 1);
2247 goto rtn;
2248 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002249 list_add_tail(&core->rx_chs[port_id].list,
2250 &taiko_p->dai[AIF2_PB].wcd9xxx_ch_list);
2251 break;
2252 case 3:
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002253 if (wcd9xxx_rx_vport_validation(port_id +
2254 TAIKO_RX_PORT_START_NUMBER,
2255 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
2256 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2257 __func__, port_id + 1);
2258 goto rtn;
2259 }
Kuirong Wang906ac472012-07-09 12:54:44 -07002260 list_add_tail(&core->rx_chs[port_id].list,
2261 &taiko_p->dai[AIF3_PB].wcd9xxx_ch_list);
2262 break;
2263 default:
2264 pr_err("Unknown AIF %d\n", widget->value);
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002265 goto err;
Kuirong Wang906ac472012-07-09 12:54:44 -07002266 }
Kuirong Wang80aca0d2013-05-09 14:51:09 -07002267rtn:
Kuirong Wang906ac472012-07-09 12:54:44 -07002268 snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
2269
2270 mutex_unlock(&codec->mutex);
2271 return 0;
Kuirong Wangdcc392e2012-10-19 00:33:38 -07002272err:
2273 mutex_unlock(&codec->mutex);
2274 return -EINVAL;
Kuirong Wang906ac472012-07-09 12:54:44 -07002275}
2276
2277static const struct soc_enum slim_rx_mux_enum =
2278 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
2279
2280static const struct snd_kcontrol_new slim_rx_mux[TAIKO_RX_MAX] = {
2281 SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
2282 slim_rx_mux_get, slim_rx_mux_put),
2283 SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
2284 slim_rx_mux_get, slim_rx_mux_put),
2285 SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
2286 slim_rx_mux_get, slim_rx_mux_put),
2287 SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
2288 slim_rx_mux_get, slim_rx_mux_put),
2289 SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
2290 slim_rx_mux_get, slim_rx_mux_put),
2291 SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
2292 slim_rx_mux_get, slim_rx_mux_put),
2293 SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
2294 slim_rx_mux_get, slim_rx_mux_put),
2295};
2296
2297static const struct snd_kcontrol_new aif_cap_mixer[] = {
2298 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TAIKO_TX1, 1, 0,
2299 slim_tx_mixer_get, slim_tx_mixer_put),
2300 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TAIKO_TX2, 1, 0,
2301 slim_tx_mixer_get, slim_tx_mixer_put),
2302 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TAIKO_TX3, 1, 0,
2303 slim_tx_mixer_get, slim_tx_mixer_put),
2304 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TAIKO_TX4, 1, 0,
2305 slim_tx_mixer_get, slim_tx_mixer_put),
2306 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TAIKO_TX5, 1, 0,
2307 slim_tx_mixer_get, slim_tx_mixer_put),
2308 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TAIKO_TX6, 1, 0,
2309 slim_tx_mixer_get, slim_tx_mixer_put),
2310 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TAIKO_TX7, 1, 0,
2311 slim_tx_mixer_get, slim_tx_mixer_put),
2312 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TAIKO_TX8, 1, 0,
2313 slim_tx_mixer_get, slim_tx_mixer_put),
2314 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TAIKO_TX9, 1, 0,
2315 slim_tx_mixer_get, slim_tx_mixer_put),
2316 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TAIKO_TX10, 1, 0,
2317 slim_tx_mixer_get, slim_tx_mixer_put),
2318};
2319
Kiran Kandic3b24402012-06-11 00:05:59 -07002320static void taiko_codec_enable_adc_block(struct snd_soc_codec *codec,
2321 int enable)
2322{
2323 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2324
2325 pr_debug("%s %d\n", __func__, enable);
2326
2327 if (enable) {
2328 taiko->adc_count++;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002329 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
2330 0x2, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07002331 } else {
2332 taiko->adc_count--;
2333 if (!taiko->adc_count)
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002334 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
Kiran Kandic3b24402012-06-11 00:05:59 -07002335 0x2, 0x0);
2336 }
2337}
2338
2339static int taiko_codec_enable_adc(struct snd_soc_dapm_widget *w,
2340 struct snd_kcontrol *kcontrol, int event)
2341{
2342 struct snd_soc_codec *codec = w->codec;
2343 u16 adc_reg;
2344 u8 init_bit_shift;
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002345 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07002346
2347 pr_debug("%s %d\n", __func__, event);
2348
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002349 if (TAIKO_IS_1_0(core->version)) {
2350 if (w->reg == TAIKO_A_TX_1_2_EN) {
2351 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2352 } else if (w->reg == TAIKO_A_TX_3_4_EN) {
2353 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2354 } else if (w->reg == TAIKO_A_TX_5_6_EN) {
2355 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2356 } else {
2357 pr_err("%s: Error, invalid adc register\n", __func__);
2358 return -EINVAL;
2359 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002360
Joonwoo Park2a9170a2013-03-04 17:05:57 -08002361 if (w->shift == 3) {
2362 init_bit_shift = 6;
2363 } else if (w->shift == 7) {
2364 init_bit_shift = 7;
2365 } else {
2366 pr_err("%s: Error, invalid init bit postion adc register\n",
2367 __func__);
2368 return -EINVAL;
2369 }
2370 } else {
2371 switch (w->reg) {
2372 case TAIKO_A_CDC_TX_1_GAIN:
2373 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2374 init_bit_shift = 7;
2375 break;
2376 case TAIKO_A_CDC_TX_2_GAIN:
2377 adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
2378 init_bit_shift = 6;
2379 break;
2380 case TAIKO_A_CDC_TX_3_GAIN:
2381 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2382 init_bit_shift = 7;
2383 break;
2384 case TAIKO_A_CDC_TX_4_GAIN:
2385 adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
2386 init_bit_shift = 6;
2387 break;
2388 case TAIKO_A_CDC_TX_5_GAIN:
2389 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2390 init_bit_shift = 7;
2391 break;
2392 case TAIKO_A_CDC_TX_6_GAIN:
2393 adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
2394 init_bit_shift = 6;
2395 break;
2396 default:
2397 pr_err("%s: Error, invalid adc register\n", __func__);
2398 return -EINVAL;
2399 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002400 }
2401
2402 switch (event) {
2403 case SND_SOC_DAPM_PRE_PMU:
2404 taiko_codec_enable_adc_block(codec, 1);
2405 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
2406 1 << init_bit_shift);
2407 break;
2408 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002409 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07002410 break;
2411 case SND_SOC_DAPM_POST_PMD:
2412 taiko_codec_enable_adc_block(codec, 0);
2413 break;
2414 }
2415 return 0;
2416}
2417
Kiran Kandic3b24402012-06-11 00:05:59 -07002418static int taiko_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
2419 struct snd_kcontrol *kcontrol, int event)
2420{
2421 struct snd_soc_codec *codec = w->codec;
2422 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2423
2424 pr_debug("%s: %d\n", __func__, event);
2425
2426 switch (event) {
2427 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park533b3682013-06-13 11:41:21 -07002428 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07002429 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
2430 WCD9XXX_BANDGAP_AUDIO_MODE);
2431 /* AUX PGA requires RCO or MCLK */
2432 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
2433 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
Joonwoo Park533b3682013-06-13 11:41:21 -07002434 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002435 break;
2436
2437 case SND_SOC_DAPM_POST_PMD:
Joonwoo Park533b3682013-06-13 11:41:21 -07002438 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07002439 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
2440 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
2441 WCD9XXX_BANDGAP_AUDIO_MODE);
2442 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_RCO);
Joonwoo Park533b3682013-06-13 11:41:21 -07002443 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07002444 break;
2445 }
2446 return 0;
2447}
2448
2449static int taiko_codec_enable_lineout(struct snd_soc_dapm_widget *w,
2450 struct snd_kcontrol *kcontrol, int event)
2451{
2452 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002453 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07002454 u16 lineout_gain_reg;
2455
2456 pr_debug("%s %d %s\n", __func__, event, w->name);
2457
2458 switch (w->shift) {
2459 case 0:
2460 lineout_gain_reg = TAIKO_A_RX_LINE_1_GAIN;
2461 break;
2462 case 1:
2463 lineout_gain_reg = TAIKO_A_RX_LINE_2_GAIN;
2464 break;
2465 case 2:
2466 lineout_gain_reg = TAIKO_A_RX_LINE_3_GAIN;
2467 break;
2468 case 3:
2469 lineout_gain_reg = TAIKO_A_RX_LINE_4_GAIN;
2470 break;
2471 default:
2472 pr_err("%s: Error, incorrect lineout register value\n",
2473 __func__);
2474 return -EINVAL;
2475 }
2476
2477 switch (event) {
2478 case SND_SOC_DAPM_PRE_PMU:
2479 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
2480 break;
2481 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002482 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2483 WCD9XXX_CLSH_STATE_LO,
2484 WCD9XXX_CLSH_REQ_ENABLE,
2485 WCD9XXX_CLSH_EVENT_POST_PA);
2486 pr_debug("%s: sleeping 3 ms after %s PA turn on\n",
Kiran Kandic3b24402012-06-11 00:05:59 -07002487 __func__, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002488 usleep_range(3000, 3000);
Kiran Kandic3b24402012-06-11 00:05:59 -07002489 break;
2490 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08002491 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
2492 WCD9XXX_CLSH_STATE_LO,
2493 WCD9XXX_CLSH_REQ_DISABLE,
2494 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandic3b24402012-06-11 00:05:59 -07002495 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
2496 break;
2497 }
2498 return 0;
2499}
2500
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002501static int taiko_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
2502 struct snd_kcontrol *kcontrol, int event)
2503{
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002504 struct snd_soc_codec *codec = w->codec;
2505 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2506
2507 pr_debug("%s: %d %s\n", __func__, event, w->name);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002508 switch (event) {
2509 case SND_SOC_DAPM_PRE_PMU:
2510 taiko->spkr_pa_widget_on = true;
2511 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
2512 break;
2513 case SND_SOC_DAPM_POST_PMD:
2514 taiko->spkr_pa_widget_on = false;
2515 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x00);
2516 break;
2517 }
Joonwoo Park7680b9f2012-07-13 11:36:48 -07002518 return 0;
2519}
Kiran Kandic3b24402012-06-11 00:05:59 -07002520
2521static int taiko_codec_enable_dmic(struct snd_soc_dapm_widget *w,
2522 struct snd_kcontrol *kcontrol, int event)
2523{
2524 struct snd_soc_codec *codec = w->codec;
2525 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
2526 u8 dmic_clk_en;
2527 u16 dmic_clk_reg;
2528 s32 *dmic_clk_cnt;
2529 unsigned int dmic;
2530 int ret;
2531
2532 ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
2533 if (ret < 0) {
2534 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
2535 return -EINVAL;
2536 }
2537
2538 switch (dmic) {
2539 case 1:
2540 case 2:
2541 dmic_clk_en = 0x01;
2542 dmic_clk_cnt = &(taiko->dmic_1_2_clk_cnt);
2543 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2544 pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
2545 __func__, event, dmic, *dmic_clk_cnt);
2546
2547 break;
2548
2549 case 3:
2550 case 4:
2551 dmic_clk_en = 0x10;
2552 dmic_clk_cnt = &(taiko->dmic_3_4_clk_cnt);
2553 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
2554
2555 pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
2556 __func__, event, dmic, *dmic_clk_cnt);
2557 break;
2558
2559 case 5:
2560 case 6:
2561 dmic_clk_en = 0x01;
2562 dmic_clk_cnt = &(taiko->dmic_5_6_clk_cnt);
2563 dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B2_CTL;
2564
2565 pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
2566 __func__, event, dmic, *dmic_clk_cnt);
2567
2568 break;
2569
2570 default:
2571 pr_err("%s: Invalid DMIC Selection\n", __func__);
2572 return -EINVAL;
2573 }
2574
2575 switch (event) {
2576 case SND_SOC_DAPM_PRE_PMU:
2577
2578 (*dmic_clk_cnt)++;
2579 if (*dmic_clk_cnt == 1)
2580 snd_soc_update_bits(codec, dmic_clk_reg,
2581 dmic_clk_en, dmic_clk_en);
2582
2583 break;
2584 case SND_SOC_DAPM_POST_PMD:
2585
2586 (*dmic_clk_cnt)--;
2587 if (*dmic_clk_cnt == 0)
2588 snd_soc_update_bits(codec, dmic_clk_reg,
2589 dmic_clk_en, 0);
2590 break;
2591 }
2592 return 0;
2593}
2594
Joonwoo Park1d05bb92013-03-07 16:55:06 -08002595static int taiko_codec_config_mad(struct snd_soc_codec *codec)
2596{
2597 int ret;
2598 const struct firmware *fw;
2599 struct mad_audio_cal *mad_cal;
2600 const char *filename = TAIKO_MAD_AUDIO_FIRMWARE_PATH;
2601
2602 pr_debug("%s: enter\n", __func__);
2603 ret = request_firmware(&fw, filename, codec->dev);
2604 if (ret != 0) {
2605 pr_err("Failed to acquire MAD firwmare data %s: %d\n", filename,
2606 ret);
2607 return -ENODEV;
2608 }
2609
2610 if (fw->size < sizeof(struct mad_audio_cal)) {
2611 pr_err("%s: incorrect firmware size %u\n", __func__, fw->size);
2612 release_firmware(fw);
2613 return -ENOMEM;
2614 }
2615
2616 mad_cal = (struct mad_audio_cal *)(fw->data);
2617 if (!mad_cal) {
2618 pr_err("%s: Invalid calibration data\n", __func__);
2619 release_firmware(fw);
2620 return -EINVAL;
2621 }
2622
Joonwoo Park1d05bb92013-03-07 16:55:06 -08002623 snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
2624 mad_cal->microphone_info.cycle_time);
2625 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
2626 ((uint16_t)mad_cal->microphone_info.settle_time)
2627 << 3);
2628
2629 /* Audio */
2630 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_8,
2631 mad_cal->audio_info.rms_omit_samples);
2632 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_1,
2633 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2634 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03 << 2,
2635 mad_cal->audio_info.detection_mechanism << 2);
2636 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_7,
2637 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2638 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_5,
2639 mad_cal->audio_info.rms_threshold_lsb);
2640 snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_6,
2641 mad_cal->audio_info.rms_threshold_msb);
2642
2643
2644 /* Beacon */
2645 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_8,
2646 mad_cal->beacon_info.rms_omit_samples);
2647 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2648 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2649 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_2, 0x03 << 2,
2650 mad_cal->beacon_info.detection_mechanism << 2);
2651 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_7,
2652 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2653 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_5,
2654 mad_cal->beacon_info.rms_threshold_lsb);
2655 snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_6,
2656 mad_cal->beacon_info.rms_threshold_msb);
2657
2658 /* Ultrasound */
2659 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
2660 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
2661 snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_ULTR_CTL_2, 0x03 << 2,
2662 mad_cal->ultrasound_info.detection_mechanism);
2663 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_7,
2664 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2665 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_5,
2666 mad_cal->ultrasound_info.rms_threshold_lsb);
2667 snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_6,
2668 mad_cal->ultrasound_info.rms_threshold_msb);
2669
2670 release_firmware(fw);
2671 pr_debug("%s: leave ret %d\n", __func__, ret);
2672
2673 return ret;
2674}
2675
2676static int taiko_codec_enable_mad(struct snd_soc_dapm_widget *w,
2677 struct snd_kcontrol *kcontrol, int event)
2678{
2679 struct snd_soc_codec *codec = w->codec;
2680 int ret = 0;
2681
2682 pr_debug("%s %d\n", __func__, event);
2683 switch (event) {
2684 case SND_SOC_DAPM_PRE_PMU:
2685 ret = taiko_codec_config_mad(codec);
2686 if (ret) {
2687 pr_err("%s: Failed to config MAD\n", __func__);
2688 break;
2689 }
2690 break;
2691 }
2692 return ret;
2693}
2694
Kiran Kandic3b24402012-06-11 00:05:59 -07002695static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
2696 struct snd_kcontrol *kcontrol, int event)
2697{
2698 struct snd_soc_codec *codec = w->codec;
2699 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002700 u16 micb_int_reg = 0, micb_ctl_reg = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07002701 u8 cfilt_sel_val = 0;
2702 char *internal1_text = "Internal1";
2703 char *internal2_text = "Internal2";
2704 char *internal3_text = "Internal3";
Joonwoo Parka8890262012-10-15 12:04:27 -07002705 enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
Kiran Kandic3b24402012-06-11 00:05:59 -07002706
Joonwoo Park3699ca32013-02-08 12:06:15 -08002707 pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
2708 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
2709 micb_ctl_reg = TAIKO_A_MICB_1_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002710 micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002711 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias1_cfilt_sel;
2712 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
2713 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
2714 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002715 } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
2716 micb_ctl_reg = TAIKO_A_MICB_2_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002717 micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002718 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias2_cfilt_sel;
2719 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
2720 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
2721 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002722 } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002723 micb_ctl_reg = TAIKO_A_MICB_3_CTL;
Kiran Kandic3b24402012-06-11 00:05:59 -07002724 micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
Joonwoo Parka8890262012-10-15 12:04:27 -07002725 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias3_cfilt_sel;
2726 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
2727 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
2728 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002729 } else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4"))) {
Damir Didjusto6e4f9d22013-03-07 10:10:57 -08002730 micb_ctl_reg = TAIKO_A_MICB_4_CTL;
Joonwoo Parka8890262012-10-15 12:04:27 -07002731 micb_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias;
2732 cfilt_sel_val = taiko->resmgr.pdata->micbias.bias4_cfilt_sel;
2733 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_4_ON;
2734 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_4_ON;
2735 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_4_OFF;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002736 } else {
2737 pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
Kiran Kandic3b24402012-06-11 00:05:59 -07002738 return -EINVAL;
2739 }
2740
2741 switch (event) {
2742 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07002743 /* Let MBHC module know so micbias switch to be off */
2744 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002745
Joonwoo Parka8890262012-10-15 12:04:27 -07002746 /* Get cfilt */
2747 wcd9xxx_resmgr_cfilt_get(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002748
2749 if (strnstr(w->name, internal1_text, 30))
2750 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
2751 else if (strnstr(w->name, internal2_text, 30))
2752 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
2753 else if (strnstr(w->name, internal3_text, 30))
2754 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
2755
Joonwoo Parkccccba72013-04-26 11:19:46 -07002756 if (taiko->mbhc_started && micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
2757 if (++taiko->micb_2_users == 1) {
2758 if (taiko->resmgr.pdata->
2759 micbias.bias2_is_headset_only)
2760 wcd9xxx_resmgr_add_cond_update_bits(
2761 &taiko->resmgr,
2762 WCD9XXX_COND_HPH_MIC,
2763 micb_ctl_reg, w->shift,
2764 false);
2765 else
2766 snd_soc_update_bits(codec, micb_ctl_reg,
2767 1 << w->shift,
2768 1 << w->shift);
2769 }
2770 pr_debug("%s: micb_2_users %d\n", __func__,
2771 taiko->micb_2_users);
2772 } else {
Joonwoo Park3699ca32013-02-08 12:06:15 -08002773 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2774 1 << w->shift);
Joonwoo Parkccccba72013-04-26 11:19:46 -07002775 }
Kiran Kandic3b24402012-06-11 00:05:59 -07002776 break;
2777 case SND_SOC_DAPM_POST_PMU:
Kiran Kandic3b24402012-06-11 00:05:59 -07002778 usleep_range(20000, 20000);
Joonwoo Parka8890262012-10-15 12:04:27 -07002779 /* Let MBHC module know so micbias is on */
2780 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07002781 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07002782 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkccccba72013-04-26 11:19:46 -07002783 if (taiko->mbhc_started && micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
2784 if (--taiko->micb_2_users == 0) {
2785 if (taiko->resmgr.pdata->
2786 micbias.bias2_is_headset_only)
2787 wcd9xxx_resmgr_rm_cond_update_bits(
2788 &taiko->resmgr,
2789 WCD9XXX_COND_HPH_MIC,
2790 micb_ctl_reg, 7, false);
2791 else
2792 snd_soc_update_bits(codec, micb_ctl_reg,
2793 1 << w->shift, 0);
2794 }
2795 pr_debug("%s: micb_2_users %d\n", __func__,
2796 taiko->micb_2_users);
2797 WARN(taiko->micb_2_users < 0,
2798 "Unexpected micbias users %d\n",
2799 taiko->micb_2_users);
2800 } else {
Joonwoo Park3699ca32013-02-08 12:06:15 -08002801 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
2802 0);
Joonwoo Parkccccba72013-04-26 11:19:46 -07002803 }
Joonwoo Park3699ca32013-02-08 12:06:15 -08002804
Joonwoo Parka8890262012-10-15 12:04:27 -07002805 /* Let MBHC module know so micbias switch to be off */
2806 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
Kiran Kandic3b24402012-06-11 00:05:59 -07002807
2808 if (strnstr(w->name, internal1_text, 30))
2809 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
2810 else if (strnstr(w->name, internal2_text, 30))
2811 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
2812 else if (strnstr(w->name, internal3_text, 30))
2813 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
2814
Joonwoo Parka8890262012-10-15 12:04:27 -07002815 /* Put cfilt */
2816 wcd9xxx_resmgr_cfilt_put(&taiko->resmgr, cfilt_sel_val);
Kiran Kandic3b24402012-06-11 00:05:59 -07002817 break;
2818 }
2819
2820 return 0;
2821}
2822
Joonwoo Parkccccba72013-04-26 11:19:46 -07002823/* called under codec_resource_lock acquisition */
2824static int taiko_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable)
2825{
2826 int rc;
2827
2828 if (enable)
2829 rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
2830 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
2831 else
2832 rc = snd_soc_dapm_disable_pin(&codec->dapm,
2833 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
2834 if (!rc)
2835 snd_soc_dapm_sync(&codec->dapm);
2836 pr_debug("%s: leave ret %d\n", __func__, rc);
2837 return rc;
2838}
Kiran Kandic3b24402012-06-11 00:05:59 -07002839
2840static void tx_hpf_corner_freq_callback(struct work_struct *work)
2841{
2842 struct delayed_work *hpf_delayed_work;
2843 struct hpf_work *hpf_work;
2844 struct taiko_priv *taiko;
2845 struct snd_soc_codec *codec;
2846 u16 tx_mux_ctl_reg;
2847 u8 hpf_cut_of_freq;
2848
2849 hpf_delayed_work = to_delayed_work(work);
2850 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
2851 taiko = hpf_work->taiko;
2852 codec = hpf_work->taiko->codec;
2853 hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
2854
2855 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL +
2856 (hpf_work->decimator - 1) * 8;
2857
2858 pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
2859 hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
2860
2861 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
2862}
2863
2864#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
2865#define CF_MIN_3DB_4HZ 0x0
2866#define CF_MIN_3DB_75HZ 0x1
2867#define CF_MIN_3DB_150HZ 0x2
2868
2869static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
2870 struct snd_kcontrol *kcontrol, int event)
2871{
2872 struct snd_soc_codec *codec = w->codec;
2873 unsigned int decimator;
2874 char *dec_name = NULL;
2875 char *widget_name = NULL;
2876 char *temp;
2877 int ret = 0;
2878 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
2879 u8 dec_hpf_cut_of_freq;
2880 int offset;
2881
2882
2883 pr_debug("%s %d\n", __func__, event);
2884
2885 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
2886 if (!widget_name)
2887 return -ENOMEM;
2888 temp = widget_name;
2889
2890 dec_name = strsep(&widget_name, " ");
2891 widget_name = temp;
2892 if (!dec_name) {
2893 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
2894 ret = -EINVAL;
2895 goto out;
2896 }
2897
2898 ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
2899 if (ret < 0) {
2900 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
2901 ret = -EINVAL;
2902 goto out;
2903 }
2904
2905 pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
2906 w->name, dec_name, decimator);
2907
2908 if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
2909 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B1_CTL;
2910 offset = 0;
2911 } else if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
2912 dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B2_CTL;
2913 offset = 8;
2914 } else {
2915 pr_err("%s: Error, incorrect dec\n", __func__);
2916 return -EINVAL;
2917 }
2918
2919 tx_vol_ctl_reg = TAIKO_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
2920 tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
2921
2922 switch (event) {
2923 case SND_SOC_DAPM_PRE_PMU:
2924
2925 /* Enableable TX digital mute */
2926 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2927
2928 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
2929 1 << w->shift);
2930 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
2931
2932 dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
2933
2934 dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
2935
2936 tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
2937 dec_hpf_cut_of_freq;
2938
2939 if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
2940
2941 /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
2942 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2943 CF_MIN_3DB_150HZ << 4);
2944 }
2945
2946 /* enable HPF */
2947 snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
2948
2949 break;
2950
2951 case SND_SOC_DAPM_POST_PMU:
2952
2953 /* Disable TX digital mute */
2954 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
2955
2956 if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
2957 CF_MIN_3DB_150HZ) {
2958
2959 schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
2960 msecs_to_jiffies(300));
2961 }
2962 /* apply the digital gain after the decimator is enabled*/
Damir Didjustoed406e22012-11-16 15:44:57 -08002963 if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
Kiran Kandic3b24402012-06-11 00:05:59 -07002964 snd_soc_write(codec,
2965 tx_digital_gain_reg[w->shift + offset],
2966 snd_soc_read(codec,
2967 tx_digital_gain_reg[w->shift + offset])
2968 );
2969
2970 break;
2971
2972 case SND_SOC_DAPM_PRE_PMD:
2973
2974 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
2975 cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
2976 break;
2977
2978 case SND_SOC_DAPM_POST_PMD:
2979
2980 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
2981 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
2982 (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
2983
2984 break;
2985 }
2986out:
2987 kfree(widget_name);
2988 return ret;
2989}
2990
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002991static int taiko_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
2992 struct snd_kcontrol *kcontrol, int event)
2993{
2994 int ret = 0;
2995 struct snd_soc_codec *codec = w->codec;
2996 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07002997 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08002998
2999 pr_debug("%s: %d %s\n", __func__, event, w->name);
Joonwoo Park448a8fc2013-04-10 15:25:58 -07003000
3001 WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
3002 WCD9XXX_VDD_SPKDRV_NAME);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003003 switch (event) {
3004 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park448a8fc2013-04-10 15:25:58 -07003005 if (priv->spkdrv_reg) {
3006 ret = regulator_enable(priv->spkdrv_reg);
3007 if (ret)
3008 pr_err("%s: Failed to enable spkdrv_reg %s\n",
3009 __func__, WCD9XXX_VDD_SPKDRV_NAME);
3010 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003011 if (spkr_drv_wrnd > 0) {
3012 WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
3013 0x80));
3014 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
3015 0x00);
3016 }
3017 if (TAIKO_IS_1_0(core->version))
3018 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
3019 0x24, 0x00);
3020 break;
3021 case SND_SOC_DAPM_POST_PMD:
3022 if (TAIKO_IS_1_0(core->version))
3023 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
3024 0x24, 0x24);
3025 if (spkr_drv_wrnd > 0) {
3026 WARN_ON(!!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
3027 0x80));
3028 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
3029 0x80);
3030 }
Joonwoo Park448a8fc2013-04-10 15:25:58 -07003031 if (priv->spkdrv_reg) {
3032 ret = regulator_disable(priv->spkdrv_reg);
3033 if (ret)
3034 pr_err("%s: Failed to disable spkdrv_reg %s\n",
3035 __func__, WCD9XXX_VDD_SPKDRV_NAME);
3036 }
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003037 break;
3038 }
3039
3040 return ret;
3041}
3042
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07003043static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07003044 struct snd_kcontrol *kcontrol, int event)
3045{
3046 struct snd_soc_codec *codec = w->codec;
3047
3048 pr_debug("%s %d %s\n", __func__, event, w->name);
3049
3050 switch (event) {
3051 case SND_SOC_DAPM_PRE_PMU:
3052 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
3053 1 << w->shift, 1 << w->shift);
3054 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
3055 1 << w->shift, 0x0);
3056 break;
3057 case SND_SOC_DAPM_POST_PMU:
3058 /* apply the digital gain after the interpolator is enabled*/
3059 if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
3060 snd_soc_write(codec,
3061 rx_digital_gain_reg[w->shift],
3062 snd_soc_read(codec,
3063 rx_digital_gain_reg[w->shift])
3064 );
3065 break;
3066 }
3067 return 0;
3068}
3069
Joonwoo Parkccccba72013-04-26 11:19:46 -07003070/* called under codec_resource_lock acquisition */
3071static int __taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
3072 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07003073{
Joonwoo Parkccccba72013-04-26 11:19:46 -07003074 struct snd_soc_codec *codec = w->codec;
3075 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
3076
3077 pr_debug("%s: enter\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07003078 switch (event) {
Joonwoo Parkccccba72013-04-26 11:19:46 -07003079 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Park533b3682013-06-13 11:41:21 -07003080 /*
3081 * ldo_h_users is protected by codec->mutex, don't need
3082 * additional mutex
3083 */
Joonwoo Parkccccba72013-04-26 11:19:46 -07003084 if (++priv->ldo_h_users == 1) {
Joonwoo Park533b3682013-06-13 11:41:21 -07003085 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003086 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
3087 WCD9XXX_BANDGAP_AUDIO_MODE);
3088 wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
3089 WCD9XXX_CLK_RCO);
3090 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 1 << 7,
3091 1 << 7);
3092 wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
3093 WCD9XXX_CLK_RCO);
Joonwoo Park533b3682013-06-13 11:41:21 -07003094 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003095 pr_debug("%s: ldo_h_users %d\n", __func__,
3096 priv->ldo_h_users);
3097 /* LDO enable requires 1ms to settle down */
3098 usleep_range(1000, 1000);
3099 }
3100 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07003101 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parkccccba72013-04-26 11:19:46 -07003102 if (--priv->ldo_h_users == 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -07003103 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003104 wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
3105 WCD9XXX_CLK_RCO);
3106 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 1 << 7,
3107 0);
3108 wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
3109 WCD9XXX_CLK_RCO);
3110 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
3111 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07003112 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003113 pr_debug("%s: ldo_h_users %d\n", __func__,
3114 priv->ldo_h_users);
3115 }
3116 WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n",
3117 priv->ldo_h_users);
Kiran Kandic3b24402012-06-11 00:05:59 -07003118 break;
3119 }
Joonwoo Parkccccba72013-04-26 11:19:46 -07003120 pr_debug("%s: leave\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07003121 return 0;
3122}
3123
Joonwoo Parkccccba72013-04-26 11:19:46 -07003124static int taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
3125 struct snd_kcontrol *kcontrol, int event)
3126{
3127 int rc;
Joonwoo Parkccccba72013-04-26 11:19:46 -07003128 rc = __taiko_codec_enable_ldo_h(w, kcontrol, event);
Joonwoo Parkccccba72013-04-26 11:19:46 -07003129 return rc;
3130}
3131
Kiran Kandic3b24402012-06-11 00:05:59 -07003132static int taiko_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
3133 struct snd_kcontrol *kcontrol, int event)
3134{
3135 struct snd_soc_codec *codec = w->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07003136 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07003137
3138 pr_debug("%s %d\n", __func__, event);
3139
3140 switch (event) {
3141 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07003142 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 1);
Kiran Kandic3b24402012-06-11 00:05:59 -07003143 break;
3144 case SND_SOC_DAPM_POST_PMD:
Joonwoo Parka8890262012-10-15 12:04:27 -07003145 wcd9xxx_resmgr_enable_rx_bias(&taiko->resmgr, 0);
Kiran Kandic3b24402012-06-11 00:05:59 -07003146 break;
3147 }
3148 return 0;
3149}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003150
3151static int taiko_hphl_dac_event(struct snd_soc_dapm_widget *w,
Kiran Kandic3b24402012-06-11 00:05:59 -07003152 struct snd_kcontrol *kcontrol, int event)
3153{
3154 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003155 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Santosh Mardi93a69192013-07-03 23:37:29 +05303156 uint32_t impedl, impedr;
3157 int ret = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07003158
3159 pr_debug("%s %s %d\n", __func__, w->name, event);
3160
3161 switch (event) {
3162 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003163 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3164 0x02, 0x02);
3165 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
3166 WCD9XXX_CLSH_STATE_HPHL,
3167 WCD9XXX_CLSH_REQ_ENABLE,
3168 WCD9XXX_CLSH_EVENT_PRE_DAC);
Santosh Mardi93a69192013-07-03 23:37:29 +05303169 ret = wcd9xxx_mbhc_get_impedance(&taiko_p->mbhc,
3170 &impedl, &impedr);
3171 if (!ret)
3172 wcd9xxx_clsh_imped_config(codec, impedl);
3173 else
3174 dev_err(codec->dev, "Failed to get mbhc impedance %d\n",
3175 ret);
Kiran Kandic3b24402012-06-11 00:05:59 -07003176 break;
3177 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003178 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3179 0x02, 0x00);
3180 }
3181 return 0;
3182}
3183
3184static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
3185 struct snd_kcontrol *kcontrol, int event)
3186{
3187 struct snd_soc_codec *codec = w->codec;
3188 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
3189
3190 pr_debug("%s %s %d\n", __func__, w->name, event);
3191
3192 switch (event) {
3193 case SND_SOC_DAPM_PRE_PMU:
3194 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3195 0x04, 0x04);
3196 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
3197 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
3198 WCD9XXX_CLSH_STATE_HPHR,
3199 WCD9XXX_CLSH_REQ_ENABLE,
3200 WCD9XXX_CLSH_EVENT_PRE_DAC);
3201 break;
3202 case SND_SOC_DAPM_POST_PMD:
3203 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
3204 0x04, 0x00);
Kiran Kandic3b24402012-06-11 00:05:59 -07003205 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
3206 break;
3207 }
3208 return 0;
3209}
3210
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003211static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
3212 struct snd_kcontrol *kcontrol, int event)
3213{
3214 struct snd_soc_codec *codec = w->codec;
3215 const char *filename;
3216 const struct firmware *fw;
3217 int i;
3218 int ret;
3219 int num_anc_slots;
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303220 struct wcd9xxx_anc_header *anc_head;
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003221 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
3222 u32 anc_writes_size = 0;
3223 int anc_size_remaining;
3224 u32 *anc_ptr;
3225 u16 reg;
3226 u8 mask, val, old_val;
3227
3228
3229 if (taiko->anc_func == 0)
3230 return 0;
3231
3232 switch (event) {
3233 case SND_SOC_DAPM_PRE_PMU:
3234 filename = "wcd9320/wcd9320_anc.bin";
3235
3236 ret = request_firmware(&fw, filename, codec->dev);
3237 if (ret != 0) {
3238 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
3239 ret);
3240 return -ENODEV;
3241 }
3242
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303243 if (fw->size < sizeof(struct wcd9xxx_anc_header)) {
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003244 dev_err(codec->dev, "Not enough data\n");
3245 release_firmware(fw);
3246 return -ENOMEM;
3247 }
3248
3249 /* First number is the number of register writes */
Simmi Pateriyadf675e92013-04-05 01:15:54 +05303250 anc_head = (struct wcd9xxx_anc_header *)(fw->data);
3251 anc_ptr = (u32 *)((u32)fw->data +
3252 sizeof(struct wcd9xxx_anc_header));
3253 anc_size_remaining = fw->size -
3254 sizeof(struct wcd9xxx_anc_header);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003255 num_anc_slots = anc_head->num_anc_slots;
3256
3257 if (taiko->anc_slot >= num_anc_slots) {
3258 dev_err(codec->dev, "Invalid ANC slot selected\n");
3259 release_firmware(fw);
3260 return -EINVAL;
3261 }
3262 for (i = 0; i < num_anc_slots; i++) {
3263 if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
3264 dev_err(codec->dev, "Invalid register format\n");
3265 release_firmware(fw);
3266 return -EINVAL;
3267 }
3268 anc_writes_size = (u32)(*anc_ptr);
3269 anc_size_remaining -= sizeof(u32);
3270 anc_ptr += 1;
3271
3272 if (anc_writes_size * TAIKO_PACKED_REG_SIZE
3273 > anc_size_remaining) {
3274 dev_err(codec->dev, "Invalid register format\n");
3275 release_firmware(fw);
3276 return -ENOMEM;
3277 }
3278
3279 if (taiko->anc_slot == i)
3280 break;
3281
3282 anc_size_remaining -= (anc_writes_size *
3283 TAIKO_PACKED_REG_SIZE);
3284 anc_ptr += anc_writes_size;
3285 }
3286 if (i == num_anc_slots) {
3287 dev_err(codec->dev, "Selected ANC slot not present\n");
3288 release_firmware(fw);
3289 return -ENOMEM;
3290 }
3291 for (i = 0; i < anc_writes_size; i++) {
3292 TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
3293 mask, val);
3294 old_val = snd_soc_read(codec, reg);
3295 snd_soc_write(codec, reg, (old_val & ~mask) |
3296 (val & mask));
3297 }
3298 release_firmware(fw);
3299 break;
Damir Didjustoaf0085c2013-05-02 17:47:45 -07003300 case SND_SOC_DAPM_PRE_PMD:
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003301 msleep(40);
3302 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
3303 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
3304 msleep(20);
3305 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
3306 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
3307 snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
3308 break;
3309 }
3310 return 0;
3311}
3312
Kiran Kandic3b24402012-06-11 00:05:59 -07003313static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
Joonwoo Parka8890262012-10-15 12:04:27 -07003314 struct snd_kcontrol *kcontrol, int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07003315{
3316 struct snd_soc_codec *codec = w->codec;
3317 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07003318 enum wcd9xxx_notify_event e_pre_on, e_post_off;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003319 u8 req_clsh_state;
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003320 u32 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_OFF;
Joonwoo Parka8890262012-10-15 12:04:27 -07003321
Kiran Kandi4c56c592012-07-25 11:04:55 -07003322 pr_debug("%s: %s event = %d\n", __func__, w->name, event);
Joonwoo Parka8890262012-10-15 12:04:27 -07003323 if (w->shift == 5) {
Joonwoo Parka8890262012-10-15 12:04:27 -07003324 e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
3325 e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
Patrick Lai453cd742013-03-02 16:51:27 -08003326 req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
3327 } else if (w->shift == 4) {
3328 e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
3329 e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003330 req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
Joonwoo Parka8890262012-10-15 12:04:27 -07003331 } else {
3332 pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
3333 return -EINVAL;
3334 }
Kiran Kandic3b24402012-06-11 00:05:59 -07003335
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003336 if (taiko->comp_enabled[COMPANDER_1])
3337 pa_settle_time = TAIKO_HPH_PA_SETTLE_COMP_ON;
3338
Kiran Kandic3b24402012-06-11 00:05:59 -07003339 switch (event) {
3340 case SND_SOC_DAPM_PRE_PMU:
Joonwoo Parka8890262012-10-15 12:04:27 -07003341 /* Let MBHC module know PA is turning on */
3342 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_pre_on);
Kiran Kandic3b24402012-06-11 00:05:59 -07003343 break;
3344
Kiran Kandi4c56c592012-07-25 11:04:55 -07003345 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003346 usleep_range(pa_settle_time, pa_settle_time + 1000);
3347 pr_debug("%s: sleep %d us after %s PA enable\n", __func__,
3348 pa_settle_time, w->name);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003349 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3350 req_clsh_state,
3351 WCD9XXX_CLSH_REQ_ENABLE,
3352 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07003353
Kiran Kandi4c56c592012-07-25 11:04:55 -07003354 break;
3355
Kiran Kandic3b24402012-06-11 00:05:59 -07003356 case SND_SOC_DAPM_POST_PMD:
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07003357 usleep_range(pa_settle_time, pa_settle_time + 1000);
3358 pr_debug("%s: sleep %d us after %s PA disable\n", __func__,
3359 pa_settle_time, w->name);
3360
Joonwoo Parka8890262012-10-15 12:04:27 -07003361 /* Let MBHC module know PA turned off */
3362 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
3363
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003364 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3365 req_clsh_state,
3366 WCD9XXX_CLSH_REQ_DISABLE,
3367 WCD9XXX_CLSH_EVENT_POST_PA);
3368
Kiran Kandic3b24402012-06-11 00:05:59 -07003369 break;
3370 }
3371 return 0;
3372}
3373
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003374static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
3375 struct snd_kcontrol *kcontrol, int event)
3376{
3377 struct snd_soc_codec *codec = w->codec;
3378 int ret = 0;
3379
3380 switch (event) {
3381 case SND_SOC_DAPM_PRE_PMU:
3382 ret = taiko_hph_pa_event(w, kcontrol, event);
3383 if (w->shift == 4) {
3384 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3385 msleep(50);
3386 }
3387 break;
3388 case SND_SOC_DAPM_POST_PMU:
3389 if (w->shift == 4) {
3390 snd_soc_update_bits(codec,
3391 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
3392 msleep(30);
3393 }
3394 ret = taiko_hph_pa_event(w, kcontrol, event);
3395 break;
3396 case SND_SOC_DAPM_PRE_PMD:
3397 if (w->shift == 5) {
3398 snd_soc_update_bits(codec,
3399 TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
3400 msleep(40);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003401 snd_soc_update_bits(codec,
3402 TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
3403 ret |= taiko_codec_enable_anc(w, kcontrol, event);
3404 }
3405 case SND_SOC_DAPM_POST_PMD:
3406 ret = taiko_hph_pa_event(w, kcontrol, event);
3407 break;
3408 }
3409 return ret;
3410}
3411
Kiran Kandic3b24402012-06-11 00:05:59 -07003412static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
3413 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
3414 4, 0, NULL, 0),
3415 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TAIKO_A_CDC_CLK_TX_I2S_CTL, 4,
3416 0, NULL, 0),
3417};
3418
3419static int taiko_lineout_dac_event(struct snd_soc_dapm_widget *w,
3420 struct snd_kcontrol *kcontrol, int event)
3421{
3422 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003423 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07003424
3425 pr_debug("%s %s %d\n", __func__, w->name, event);
3426
3427 switch (event) {
3428 case SND_SOC_DAPM_PRE_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003429 wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
3430 WCD9XXX_CLSH_STATE_LO,
3431 WCD9XXX_CLSH_REQ_ENABLE,
3432 WCD9XXX_CLSH_EVENT_PRE_DAC);
Kiran Kandic3b24402012-06-11 00:05:59 -07003433 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
3434 break;
3435
3436 case SND_SOC_DAPM_POST_PMD:
3437 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
3438 break;
3439 }
3440 return 0;
3441}
3442
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003443static int taiko_spk_dac_event(struct snd_soc_dapm_widget *w,
3444 struct snd_kcontrol *kcontrol, int event)
3445{
3446 pr_debug("%s %s %d\n", __func__, w->name, event);
3447 return 0;
3448}
3449
Kiran Kandic3b24402012-06-11 00:05:59 -07003450static const struct snd_soc_dapm_route audio_i2s_map[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07003451 {"SLIM RX1", NULL, "RX_I2S_CLK"},
3452 {"SLIM RX2", NULL, "RX_I2S_CLK"},
3453 {"SLIM RX3", NULL, "RX_I2S_CLK"},
3454 {"SLIM RX4", NULL, "RX_I2S_CLK"},
3455
Venkat Sudhira41630a2012-10-27 00:57:31 -07003456 {"SLIM TX7 MUX", NULL, "TX_I2S_CLK"},
3457 {"SLIM TX8 MUX", NULL, "TX_I2S_CLK"},
3458 {"SLIM TX9 MUX", NULL, "TX_I2S_CLK"},
3459 {"SLIM TX10 MUX", NULL, "TX_I2S_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003460};
3461
Joonwoo Park559a5bf2013-02-15 14:46:36 -08003462static const struct snd_soc_dapm_route audio_i2s_map_1_0[] = {
3463 {"RX_I2S_CLK", NULL, "CDC_CONN"},
3464};
3465
3466static const struct snd_soc_dapm_route audio_i2s_map_2_0[] = {
3467 {"RX_I2S_CLK", NULL, "CDC_I2S_RX_CONN"},
3468};
3469
Kiran Kandic3b24402012-06-11 00:05:59 -07003470static const struct snd_soc_dapm_route audio_map[] = {
3471 /* SLIMBUS Connections */
Kuirong Wang906ac472012-07-09 12:54:44 -07003472 {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
3473 {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
3474 {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05003475 {"AIF4 VI", NULL, "SPK_OUT"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003476
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003477 /* MAD */
3478 {"AIF4 MAD", NULL, "CDC_CONN"},
Joonwoo Park9ead0e92013-03-18 11:33:33 -07003479 {"MADONOFF", "Switch", "MADINPUT"},
3480 {"AIF4 MAD", NULL, "MADONOFF"},
Joonwoo Park1d05bb92013-03-07 16:55:06 -08003481
Kuirong Wang906ac472012-07-09 12:54:44 -07003482 /* SLIM_MIXER("AIF1_CAP Mixer"),*/
3483 {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3484 {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3485 {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3486 {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3487 {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3488 {"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3489 {"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3490 {"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3491 {"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3492 {"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3493 /* SLIM_MIXER("AIF2_CAP Mixer"),*/
3494 {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3495 {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3496 {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3497 {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3498 {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3499 {"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3500 {"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3501 {"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3502 {"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3503 {"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3504 /* SLIM_MIXER("AIF3_CAP Mixer"),*/
3505 {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
3506 {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
3507 {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
3508 {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
3509 {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
3510 {"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
3511 {"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
3512 {"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
3513 {"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
3514 {"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
3515
Kiran Kandic3b24402012-06-11 00:05:59 -07003516 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
3517
Kiran Kandic3b24402012-06-11 00:05:59 -07003518 {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
3519
Kiran Kandic3b24402012-06-11 00:05:59 -07003520 {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
3521 {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
3522 {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
3523 {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
3524 {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
3525 {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
3526 {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
3527 {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
3528
Kiran Kandic3b24402012-06-11 00:05:59 -07003529 {"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
3530
Kiran Kandic3b24402012-06-11 00:05:59 -07003531 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
3532 {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
3533 {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
3534 {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
3535 {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
3536 {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
3537 {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
3538 {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
3539
Kiran Kandic3b24402012-06-11 00:05:59 -07003540 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
3541
Kiran Kandic3b24402012-06-11 00:05:59 -07003542 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
3543 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
3544 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
3545 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
3546 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
3547 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
3548 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
3549 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
3550 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
3551 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
3552 {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
3553 {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
3554 {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
3555 {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
3556 {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
3557 {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
3558 {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
3559
Kiran Kandic3b24402012-06-11 00:05:59 -07003560 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
3561 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
3562 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
3563 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
3564 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
3565 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
3566 {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
3567 {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
3568 {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
3569 {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
3570
Kiran Kandic3b24402012-06-11 00:05:59 -07003571 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
3572 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
3573 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
3574 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
3575 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
3576 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
3577 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
3578 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
3579 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
3580 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
3581
Kiran Kandic3b24402012-06-11 00:05:59 -07003582 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
3583 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
3584 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
3585 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
3586 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
3587 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
3588 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
3589 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
3590 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
3591 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
3592
3593 /* Earpiece (RX MIX1) */
3594 {"EAR", NULL, "EAR PA"},
3595 {"EAR PA", NULL, "EAR_PA_MIXER"},
3596 {"EAR_PA_MIXER", NULL, "DAC1"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003597 {"DAC1", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003598
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003599 {"ANC EAR", NULL, "ANC EAR PA"},
3600 {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003601 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
3602 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003603
3604 /* Headset (RX MIX1 and RX MIX2) */
3605 {"HEADPHONE", NULL, "HPHL"},
3606 {"HEADPHONE", NULL, "HPHR"},
3607
3608 {"HPHL", NULL, "HPHL_PA_MIXER"},
3609 {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003610 {"HPHL DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003611
3612 {"HPHR", NULL, "HPHR_PA_MIXER"},
3613 {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003614 {"HPHR DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003615
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003616 {"ANC HEADPHONE", NULL, "ANC HPHL"},
3617 {"ANC HEADPHONE", NULL, "ANC HPHR"},
3618
3619 {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
3620 {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
3621
Kiran Kandic3b24402012-06-11 00:05:59 -07003622 {"ANC1 MUX", "ADC1", "ADC1"},
3623 {"ANC1 MUX", "ADC2", "ADC2"},
3624 {"ANC1 MUX", "ADC3", "ADC3"},
3625 {"ANC1 MUX", "ADC4", "ADC4"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003626 {"ANC1 MUX", "DMIC1", "DMIC1"},
3627 {"ANC1 MUX", "DMIC2", "DMIC2"},
3628 {"ANC1 MUX", "DMIC3", "DMIC3"},
3629 {"ANC1 MUX", "DMIC4", "DMIC4"},
3630 {"ANC1 MUX", "DMIC5", "DMIC5"},
3631 {"ANC1 MUX", "DMIC6", "DMIC6"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003632 {"ANC2 MUX", "ADC1", "ADC1"},
3633 {"ANC2 MUX", "ADC2", "ADC2"},
3634 {"ANC2 MUX", "ADC3", "ADC3"},
3635 {"ANC2 MUX", "ADC4", "ADC4"},
3636
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003637 {"ANC HPHR", NULL, "CDC_CONN"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003638
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003639 {"DAC1", "Switch", "CLASS_H_DSM MUX"},
3640 {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003641 {"HPHR DAC", NULL, "RX2 CHAIN"},
3642
3643 {"LINEOUT1", NULL, "LINEOUT1 PA"},
3644 {"LINEOUT2", NULL, "LINEOUT2 PA"},
3645 {"LINEOUT3", NULL, "LINEOUT3 PA"},
3646 {"LINEOUT4", NULL, "LINEOUT4 PA"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003647 {"SPK_OUT", NULL, "SPK PA"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003648
3649 {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
3650 {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003651
Kiran Kandic3b24402012-06-11 00:05:59 -07003652 {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
3653 {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003654
Kiran Kandic3b24402012-06-11 00:05:59 -07003655 {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
3656 {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
Tanya Finkelfe634462012-10-23 22:12:07 +02003657
Kiran Kandic3b24402012-06-11 00:05:59 -07003658 {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
3659 {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
3660
3661 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
3662
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003663 {"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
3664 {"RDAC5 MUX", "DEM4", "RX4 MIX1"},
3665
3666 {"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003667
3668 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
3669
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02003670 {"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
3671 {"RDAC7 MUX", "DEM6", "RX6 MIX1"},
3672
3673 {"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003674
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003675 {"SPK PA", NULL, "SPK DAC"},
Kiran Kandid2b46332012-10-05 12:04:00 -07003676 {"SPK DAC", NULL, "RX7 MIX2"},
Joonwoo Park125cd4e2012-12-11 15:16:11 -08003677 {"SPK DAC", NULL, "VDD_SPKDRV"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003678
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08003679 {"CLASS_H_DSM MUX", "DSM_HPHL_RX1", "RX1 CHAIN"},
3680
Kiran Kandic3b24402012-06-11 00:05:59 -07003681 {"RX1 CHAIN", NULL, "RX1 MIX2"},
3682 {"RX2 CHAIN", NULL, "RX2 MIX2"},
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08003683 {"RX1 MIX2", NULL, "ANC1 MUX"},
3684 {"RX2 MIX2", NULL, "ANC2 MUX"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003685
Kiran Kandic3b24402012-06-11 00:05:59 -07003686 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
3687 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
3688 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
3689 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
Joonwoo Park7680b9f2012-07-13 11:36:48 -07003690 {"SPK DAC", NULL, "RX_BIAS"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003691
Joonwoo Parkc7731432012-10-17 12:41:44 -07003692 {"RX7 MIX1", NULL, "COMP0_CLK"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003693 {"RX1 MIX1", NULL, "COMP1_CLK"},
3694 {"RX2 MIX1", NULL, "COMP1_CLK"},
3695 {"RX3 MIX1", NULL, "COMP2_CLK"},
3696 {"RX5 MIX1", NULL, "COMP2_CLK"},
3697
Kiran Kandic3b24402012-06-11 00:05:59 -07003698 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
3699 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
3700 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
3701 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
3702 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
3703 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
3704 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
3705 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
3706 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
3707 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
3708 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
3709 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
3710 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
3711 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
3712 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
3713 {"RX1 MIX2", NULL, "RX1 MIX1"},
3714 {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
3715 {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
3716 {"RX2 MIX2", NULL, "RX2 MIX1"},
3717 {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
3718 {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
3719 {"RX7 MIX2", NULL, "RX7 MIX1"},
3720 {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
3721 {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
3722
Kuirong Wang906ac472012-07-09 12:54:44 -07003723 /* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
3724 {"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
3725 {"SLIM RX2 MUX", "AIF1_PB", "AIF1 PB"},
3726 {"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
3727 {"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
3728 {"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
3729 {"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
3730 {"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
3731 /* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
3732 {"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
3733 {"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
3734 {"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
3735 {"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
3736 {"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
3737 {"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
3738 {"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
3739 /* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
3740 {"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
3741 {"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
3742 {"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
3743 {"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
3744 {"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
3745 {"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
3746 {"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
3747
3748 {"SLIM RX1", NULL, "SLIM RX1 MUX"},
3749 {"SLIM RX2", NULL, "SLIM RX2 MUX"},
3750 {"SLIM RX3", NULL, "SLIM RX3 MUX"},
3751 {"SLIM RX4", NULL, "SLIM RX4 MUX"},
3752 {"SLIM RX5", NULL, "SLIM RX5 MUX"},
3753 {"SLIM RX6", NULL, "SLIM RX6 MUX"},
3754 {"SLIM RX7", NULL, "SLIM RX7 MUX"},
3755
Kiran Kandic3b24402012-06-11 00:05:59 -07003756 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
3757 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
3758 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
3759 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
3760 {"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
3761 {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
3762 {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
3763 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003764 {"RX1 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003765 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
3766 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
3767 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
3768 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
3769 {"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
3770 {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
3771 {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
3772 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003773 {"RX1 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003774 {"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
3775 {"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
3776 {"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
3777 {"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
3778 {"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
3779 {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
3780 {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
3781 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
3782 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
3783 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
3784 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
3785 {"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
3786 {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
3787 {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
3788 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003789 {"RX2 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003790 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
3791 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
3792 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
3793 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
3794 {"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
3795 {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
3796 {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
3797 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003798 {"RX2 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003799 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
3800 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
3801 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
3802 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
3803 {"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
3804 {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
3805 {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
3806 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003807 {"RX3 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003808 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
3809 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
3810 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
3811 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
3812 {"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
3813 {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
3814 {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
3815 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003816 {"RX3 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003817 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
3818 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
3819 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
3820 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
3821 {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
3822 {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
3823 {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
3824 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003825 {"RX4 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003826 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
3827 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
3828 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
3829 {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
3830 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
3831 {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
3832 {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
3833 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003834 {"RX4 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003835 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
3836 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
3837 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
3838 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
3839 {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
3840 {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
3841 {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
3842 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003843 {"RX5 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003844 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
3845 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
3846 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
3847 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
3848 {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
3849 {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
3850 {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
3851 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003852 {"RX5 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003853 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
3854 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
3855 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
3856 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
3857 {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
3858 {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
3859 {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
3860 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003861 {"RX6 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003862 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
3863 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
3864 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
3865 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
3866 {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
3867 {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
3868 {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
3869 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003870 {"RX6 MIX1 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003871 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
3872 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
3873 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
3874 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
3875 {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
3876 {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
3877 {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
3878 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003879 {"RX7 MIX1 INP1", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003880 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
3881 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
3882 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
3883 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
3884 {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
3885 {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
3886 {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
3887 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003888 {"RX7 MIX1 INP2", "IIR2", "IIR2"},
3889
3890 /* IIR1, IIR2 inputs to Second RX Mixer on RX1, RX2 and RX7 chains. */
Kiran Kandic3b24402012-06-11 00:05:59 -07003891 {"RX1 MIX2 INP1", "IIR1", "IIR1"},
3892 {"RX1 MIX2 INP2", "IIR1", "IIR1"},
3893 {"RX2 MIX2 INP1", "IIR1", "IIR1"},
3894 {"RX2 MIX2 INP2", "IIR1", "IIR1"},
3895 {"RX7 MIX2 INP1", "IIR1", "IIR1"},
3896 {"RX7 MIX2 INP2", "IIR1", "IIR1"},
Fred Oh456fcb52013-02-28 19:08:15 -08003897 {"RX1 MIX2 INP1", "IIR2", "IIR2"},
3898 {"RX1 MIX2 INP2", "IIR2", "IIR2"},
3899 {"RX2 MIX2 INP1", "IIR2", "IIR2"},
3900 {"RX2 MIX2 INP2", "IIR2", "IIR2"},
3901 {"RX7 MIX2 INP1", "IIR2", "IIR2"},
3902 {"RX7 MIX2 INP2", "IIR2", "IIR2"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003903
3904 /* Decimator Inputs */
3905 {"DEC1 MUX", "DMIC1", "DMIC1"},
3906 {"DEC1 MUX", "ADC6", "ADC6"},
3907 {"DEC1 MUX", NULL, "CDC_CONN"},
3908 {"DEC2 MUX", "DMIC2", "DMIC2"},
3909 {"DEC2 MUX", "ADC5", "ADC5"},
3910 {"DEC2 MUX", NULL, "CDC_CONN"},
3911 {"DEC3 MUX", "DMIC3", "DMIC3"},
3912 {"DEC3 MUX", "ADC4", "ADC4"},
3913 {"DEC3 MUX", NULL, "CDC_CONN"},
3914 {"DEC4 MUX", "DMIC4", "DMIC4"},
3915 {"DEC4 MUX", "ADC3", "ADC3"},
3916 {"DEC4 MUX", NULL, "CDC_CONN"},
3917 {"DEC5 MUX", "DMIC5", "DMIC5"},
3918 {"DEC5 MUX", "ADC2", "ADC2"},
3919 {"DEC5 MUX", NULL, "CDC_CONN"},
3920 {"DEC6 MUX", "DMIC6", "DMIC6"},
3921 {"DEC6 MUX", "ADC1", "ADC1"},
3922 {"DEC6 MUX", NULL, "CDC_CONN"},
3923 {"DEC7 MUX", "DMIC1", "DMIC1"},
3924 {"DEC7 MUX", "DMIC6", "DMIC6"},
3925 {"DEC7 MUX", "ADC1", "ADC1"},
3926 {"DEC7 MUX", "ADC6", "ADC6"},
3927 {"DEC7 MUX", NULL, "CDC_CONN"},
3928 {"DEC8 MUX", "DMIC2", "DMIC2"},
3929 {"DEC8 MUX", "DMIC5", "DMIC5"},
3930 {"DEC8 MUX", "ADC2", "ADC2"},
3931 {"DEC8 MUX", "ADC5", "ADC5"},
3932 {"DEC8 MUX", NULL, "CDC_CONN"},
3933 {"DEC9 MUX", "DMIC4", "DMIC4"},
3934 {"DEC9 MUX", "DMIC5", "DMIC5"},
3935 {"DEC9 MUX", "ADC2", "ADC2"},
3936 {"DEC9 MUX", "ADC3", "ADC3"},
3937 {"DEC9 MUX", NULL, "CDC_CONN"},
3938 {"DEC10 MUX", "DMIC3", "DMIC3"},
3939 {"DEC10 MUX", "DMIC6", "DMIC6"},
3940 {"DEC10 MUX", "ADC1", "ADC1"},
3941 {"DEC10 MUX", "ADC4", "ADC4"},
3942 {"DEC10 MUX", NULL, "CDC_CONN"},
3943
3944 /* ADC Connections */
3945 {"ADC1", NULL, "AMIC1"},
3946 {"ADC2", NULL, "AMIC2"},
3947 {"ADC3", NULL, "AMIC3"},
3948 {"ADC4", NULL, "AMIC4"},
3949 {"ADC5", NULL, "AMIC5"},
3950 {"ADC6", NULL, "AMIC6"},
3951
3952 /* AUX PGA Connections */
Kiran Kandic3b24402012-06-11 00:05:59 -07003953 {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
Kiran Kandi4c56c592012-07-25 11:04:55 -07003954 {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3955 {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3956 {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3957 {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
3958 {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
3959 {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003960 {"AUX_PGA_Left", NULL, "AMIC5"},
3961 {"AUX_PGA_Right", NULL, "AMIC6"},
3962
Kiran Kandic3b24402012-06-11 00:05:59 -07003963 {"IIR1", NULL, "IIR1 INP1 MUX"},
3964 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
3965 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
3966 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
3967 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
3968 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
3969 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
3970 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
3971 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
3972 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
3973 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003974 {"IIR1 INP1 MUX", "RX1", "SLIM RX1"},
3975 {"IIR1 INP1 MUX", "RX2", "SLIM RX2"},
3976 {"IIR1 INP1 MUX", "RX3", "SLIM RX3"},
3977 {"IIR1 INP1 MUX", "RX4", "SLIM RX4"},
3978 {"IIR1 INP1 MUX", "RX5", "SLIM RX5"},
3979 {"IIR1 INP1 MUX", "RX6", "SLIM RX6"},
3980 {"IIR1 INP1 MUX", "RX7", "SLIM RX7"},
Kiran Kandic3b24402012-06-11 00:05:59 -07003981
Fred Oh456fcb52013-02-28 19:08:15 -08003982 {"IIR2", NULL, "IIR2 INP1 MUX"},
3983 {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
3984 {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
3985 {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
3986 {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
3987 {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
3988 {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
3989 {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
3990 {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
3991 {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
3992 {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
Kiran Kandibd85d772013-05-19 19:03:43 -07003993 {"IIR2 INP1 MUX", "RX1", "SLIM RX1"},
3994 {"IIR2 INP1 MUX", "RX2", "SLIM RX2"},
3995 {"IIR2 INP1 MUX", "RX3", "SLIM RX3"},
3996 {"IIR2 INP1 MUX", "RX4", "SLIM RX4"},
3997 {"IIR2 INP1 MUX", "RX5", "SLIM RX5"},
3998 {"IIR2 INP1 MUX", "RX6", "SLIM RX6"},
3999 {"IIR2 INP1 MUX", "RX7", "SLIM RX7"},
Fred Oh456fcb52013-02-28 19:08:15 -08004000
Kiran Kandic3b24402012-06-11 00:05:59 -07004001 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
4002 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
4003 {"MIC BIAS1 External", NULL, "LDO_H"},
4004 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
4005 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
4006 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
4007 {"MIC BIAS2 External", NULL, "LDO_H"},
4008 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
4009 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
4010 {"MIC BIAS3 External", NULL, "LDO_H"},
4011 {"MIC BIAS4 External", NULL, "LDO_H"},
Joonwoo Parkccccba72013-04-26 11:19:46 -07004012 {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"},
Kiran Kandic3b24402012-06-11 00:05:59 -07004013};
4014
4015static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
4016{
4017 return taiko_reg_readable[reg];
4018}
4019
4020static bool taiko_is_digital_gain_register(unsigned int reg)
4021{
4022 bool rtn = false;
4023 switch (reg) {
4024 case TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL:
4025 case TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL:
4026 case TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL:
4027 case TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL:
4028 case TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL:
4029 case TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL:
4030 case TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL:
4031 case TAIKO_A_CDC_TX1_VOL_CTL_GAIN:
4032 case TAIKO_A_CDC_TX2_VOL_CTL_GAIN:
4033 case TAIKO_A_CDC_TX3_VOL_CTL_GAIN:
4034 case TAIKO_A_CDC_TX4_VOL_CTL_GAIN:
4035 case TAIKO_A_CDC_TX5_VOL_CTL_GAIN:
4036 case TAIKO_A_CDC_TX6_VOL_CTL_GAIN:
4037 case TAIKO_A_CDC_TX7_VOL_CTL_GAIN:
4038 case TAIKO_A_CDC_TX8_VOL_CTL_GAIN:
4039 case TAIKO_A_CDC_TX9_VOL_CTL_GAIN:
4040 case TAIKO_A_CDC_TX10_VOL_CTL_GAIN:
4041 rtn = true;
4042 break;
4043 default:
4044 break;
4045 }
4046 return rtn;
4047}
4048
4049static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
4050{
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004051 int i;
4052
Kiran Kandic3b24402012-06-11 00:05:59 -07004053 /* Registers lower than 0x100 are top level registers which can be
4054 * written by the Taiko core driver.
4055 */
4056
4057 if ((reg >= TAIKO_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
4058 return 1;
4059
4060 /* IIR Coeff registers are not cacheable */
4061 if ((reg >= TAIKO_A_CDC_IIR1_COEF_B1_CTL) &&
4062 (reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
4063 return 1;
4064
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08004065 /* ANC filter registers are not cacheable */
4066 if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
4067 (reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
4068 return 1;
4069 if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
4070 (reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
4071 return 1;
4072
Kiran Kandic3b24402012-06-11 00:05:59 -07004073 /* Digital gain register is not cacheable so we have to write
4074 * the setting even it is the same
4075 */
4076 if (taiko_is_digital_gain_register(reg))
4077 return 1;
4078
4079 /* HPH status registers */
4080 if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
4081 return 1;
4082
Joonwoo Parka8890262012-10-15 12:04:27 -07004083 if (reg == TAIKO_A_MBHC_INSERT_DET_STATUS)
4084 return 1;
4085
Joonwoo Park559a5bf2013-02-15 14:46:36 -08004086 switch (reg) {
4087 case TAIKO_A_CDC_SPKR_CLIPDET_VAL0:
4088 case TAIKO_A_CDC_SPKR_CLIPDET_VAL1:
4089 case TAIKO_A_CDC_SPKR_CLIPDET_VAL2:
4090 case TAIKO_A_CDC_SPKR_CLIPDET_VAL3:
4091 case TAIKO_A_CDC_SPKR_CLIPDET_VAL4:
4092 case TAIKO_A_CDC_SPKR_CLIPDET_VAL5:
4093 case TAIKO_A_CDC_SPKR_CLIPDET_VAL6:
4094 case TAIKO_A_CDC_SPKR_CLIPDET_VAL7:
4095 case TAIKO_A_CDC_VBAT_GAIN_MON_VAL:
4096 return 1;
4097 }
4098
Damir Didjustodcfdff82013-03-21 23:26:41 -07004099 for (i = 0; i < ARRAY_SIZE(audio_reg_cfg); i++)
4100 if (audio_reg_cfg[i].reg_logical_addr -
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004101 TAIKO_REGISTER_START_OFFSET == reg)
4102 return 1;
4103
Kiran Kandic3b24402012-06-11 00:05:59 -07004104 return 0;
4105}
4106
Kiran Kandic3b24402012-06-11 00:05:59 -07004107static int taiko_write(struct snd_soc_codec *codec, unsigned int reg,
4108 unsigned int value)
4109{
4110 int ret;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07004111 struct wcd9xxx *wcd9xxx = codec->control_data;
Kuirong Wang906ac472012-07-09 12:54:44 -07004112
4113 if (reg == SND_SOC_NOPM)
4114 return 0;
4115
Kiran Kandic3b24402012-06-11 00:05:59 -07004116 BUG_ON(reg > TAIKO_MAX_REGISTER);
4117
4118 if (!taiko_volatile(codec, reg)) {
4119 ret = snd_soc_cache_write(codec, reg, value);
4120 if (ret != 0)
4121 dev_err(codec->dev, "Cache write to %x failed: %d\n",
4122 reg, ret);
4123 }
4124
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07004125 return wcd9xxx_reg_write(&wcd9xxx->core_res, reg, value);
Kiran Kandic3b24402012-06-11 00:05:59 -07004126}
4127static unsigned int taiko_read(struct snd_soc_codec *codec,
4128 unsigned int reg)
4129{
4130 unsigned int val;
4131 int ret;
4132
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07004133 struct wcd9xxx *wcd9xxx = codec->control_data;
4134
Kuirong Wang906ac472012-07-09 12:54:44 -07004135 if (reg == SND_SOC_NOPM)
4136 return 0;
4137
Kiran Kandic3b24402012-06-11 00:05:59 -07004138 BUG_ON(reg > TAIKO_MAX_REGISTER);
4139
4140 if (!taiko_volatile(codec, reg) && taiko_readable(codec, reg) &&
4141 reg < codec->driver->reg_cache_size) {
4142 ret = snd_soc_cache_read(codec, reg, &val);
4143 if (ret >= 0) {
4144 return val;
4145 } else
4146 dev_err(codec->dev, "Cache read from %x failed: %d\n",
4147 reg, ret);
4148 }
4149
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07004150 val = wcd9xxx_reg_read(&wcd9xxx->core_res, reg);
Kiran Kandic3b24402012-06-11 00:05:59 -07004151 return val;
4152}
4153
Kiran Kandic3b24402012-06-11 00:05:59 -07004154static int taiko_startup(struct snd_pcm_substream *substream,
4155 struct snd_soc_dai *dai)
4156{
4157 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
4158 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
4159 substream->name, substream->stream);
4160 if ((taiko_core != NULL) &&
4161 (taiko_core->dev != NULL) &&
4162 (taiko_core->dev->parent != NULL))
4163 pm_runtime_get_sync(taiko_core->dev->parent);
4164
4165 return 0;
4166}
4167
4168static void taiko_shutdown(struct snd_pcm_substream *substream,
4169 struct snd_soc_dai *dai)
4170{
4171 struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
4172 pr_debug("%s(): substream = %s stream = %d\n" , __func__,
4173 substream->name, substream->stream);
4174 if ((taiko_core != NULL) &&
4175 (taiko_core->dev != NULL) &&
4176 (taiko_core->dev->parent != NULL)) {
4177 pm_runtime_mark_last_busy(taiko_core->dev->parent);
4178 pm_runtime_put(taiko_core->dev->parent);
4179 }
4180}
4181
4182int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
4183{
4184 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4185
4186 pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
4187 dapm);
Joonwoo Parka8890262012-10-15 12:04:27 -07004188
Joonwoo Park533b3682013-06-13 11:41:21 -07004189 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Kiran Kandic3b24402012-06-11 00:05:59 -07004190 if (mclk_enable) {
Joonwoo Parka8890262012-10-15 12:04:27 -07004191 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
4192 WCD9XXX_BANDGAP_AUDIO_MODE);
4193 wcd9xxx_resmgr_get_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
Kiran Kandic3b24402012-06-11 00:05:59 -07004194 } else {
Joonwoo Parka8890262012-10-15 12:04:27 -07004195 /* Put clock and BG */
4196 wcd9xxx_resmgr_put_clk_block(&taiko->resmgr, WCD9XXX_CLK_MCLK);
4197 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
4198 WCD9XXX_BANDGAP_AUDIO_MODE);
Kiran Kandic3b24402012-06-11 00:05:59 -07004199 }
Joonwoo Park533b3682013-06-13 11:41:21 -07004200 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Parka8890262012-10-15 12:04:27 -07004201
Kiran Kandic3b24402012-06-11 00:05:59 -07004202 return 0;
4203}
4204
4205static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
4206 int clk_id, unsigned int freq, int dir)
4207{
Venkat Sudhira50a3762012-11-26 12:12:15 -08004208 pr_debug("%s\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07004209 return 0;
4210}
4211
4212static int taiko_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
4213{
4214 u8 val = 0;
4215 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
4216
4217 pr_debug("%s\n", __func__);
4218 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
4219 case SND_SOC_DAIFMT_CBS_CFS:
4220 /* CPU is master */
4221 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4222 if (dai->id == AIF1_CAP)
4223 snd_soc_update_bits(dai->codec,
4224 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4225 TAIKO_I2S_MASTER_MODE_MASK, 0);
4226 else if (dai->id == AIF1_PB)
4227 snd_soc_update_bits(dai->codec,
4228 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4229 TAIKO_I2S_MASTER_MODE_MASK, 0);
4230 }
4231 break;
4232 case SND_SOC_DAIFMT_CBM_CFM:
4233 /* CPU is slave */
4234 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4235 val = TAIKO_I2S_MASTER_MODE_MASK;
4236 if (dai->id == AIF1_CAP)
4237 snd_soc_update_bits(dai->codec,
4238 TAIKO_A_CDC_CLK_TX_I2S_CTL, val, val);
4239 else if (dai->id == AIF1_PB)
4240 snd_soc_update_bits(dai->codec,
4241 TAIKO_A_CDC_CLK_RX_I2S_CTL, val, val);
4242 }
4243 break;
4244 default:
4245 return -EINVAL;
4246 }
4247 return 0;
4248}
4249
4250static int taiko_set_channel_map(struct snd_soc_dai *dai,
4251 unsigned int tx_num, unsigned int *tx_slot,
4252 unsigned int rx_num, unsigned int *rx_slot)
4253
4254{
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004255 struct wcd9xxx_codec_dai_data *dai_data = NULL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004256 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07004257 struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07004258 if (!tx_slot && !rx_slot) {
4259 pr_err("%s: Invalid\n", __func__);
4260 return -EINVAL;
4261 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004262 pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n"
4263 "taiko->intf_type %d\n",
4264 __func__, dai->name, dai->id, tx_num, rx_num,
4265 taiko->intf_type);
Kiran Kandic3b24402012-06-11 00:05:59 -07004266
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004267 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Kuirong Wang906ac472012-07-09 12:54:44 -07004268 wcd9xxx_init_slimslave(core, core->slim->laddr,
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004269 tx_num, tx_slot, rx_num, rx_slot);
4270 /*Reserve tx11 and tx12 for VI feedback path*/
4271 dai_data = &taiko->dai[AIF4_VIFEED];
4272 if (dai_data) {
4273 list_add_tail(&core->tx_chs[TAIKO_TX11].list,
4274 &dai_data->wcd9xxx_ch_list);
4275 list_add_tail(&core->tx_chs[TAIKO_TX12].list,
4276 &dai_data->wcd9xxx_ch_list);
4277 }
4278 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004279 return 0;
4280}
4281
4282static int taiko_get_channel_map(struct snd_soc_dai *dai,
4283 unsigned int *tx_num, unsigned int *tx_slot,
4284 unsigned int *rx_num, unsigned int *rx_slot)
4285
4286{
4287 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(dai->codec);
4288 u32 i = 0;
4289 struct wcd9xxx_ch *ch;
4290
4291 switch (dai->id) {
4292 case AIF1_PB:
4293 case AIF2_PB:
4294 case AIF3_PB:
4295 if (!rx_slot || !rx_num) {
4296 pr_err("%s: Invalid rx_slot %d or rx_num %d\n",
4297 __func__, (u32) rx_slot, (u32) rx_num);
4298 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004299 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004300 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
4301 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05004302 pr_debug("%s: slot_num %u ch->ch_num %d\n",
4303 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07004304 rx_slot[i++] = ch->ch_num;
4305 }
4306 pr_debug("%s: rx_num %d\n", __func__, i);
4307 *rx_num = i;
4308 break;
4309 case AIF1_CAP:
4310 case AIF2_CAP:
4311 case AIF3_CAP:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004312 case AIF4_VIFEED:
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004313 case AIF4_MAD_TX:
Kuirong Wang906ac472012-07-09 12:54:44 -07004314 if (!tx_slot || !tx_num) {
4315 pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
4316 __func__, (u32) tx_slot, (u32) tx_num);
4317 return -EINVAL;
4318 }
4319 list_for_each_entry(ch, &taiko_p->dai[dai->id].wcd9xxx_ch_list,
4320 list) {
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05004321 pr_debug("%s: slot_num %u ch->ch_num %d\n",
4322 __func__, i, ch->ch_num);
Kuirong Wang906ac472012-07-09 12:54:44 -07004323 tx_slot[i++] = ch->ch_num;
4324 }
4325 pr_debug("%s: tx_num %d\n", __func__, i);
4326 *tx_num = i;
4327 break;
4328
4329 default:
4330 pr_err("%s: Invalid DAI ID %x\n", __func__, dai->id);
4331 break;
4332 }
4333
4334 return 0;
4335}
4336
4337static int taiko_set_interpolator_rate(struct snd_soc_dai *dai,
4338 u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
4339{
4340 u32 j;
4341 u8 rx_mix1_inp;
4342 u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
4343 u16 rx_fs_reg;
4344 u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
4345 struct snd_soc_codec *codec = dai->codec;
4346 struct wcd9xxx_ch *ch;
4347 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4348
4349 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
4350 /* for RX port starting from 16 instead of 10 like tabla */
4351 rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
4352 TAIKO_TX_PORT_NUMBER;
4353 if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
4354 (rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
4355 pr_err("%s: Invalid TAIKO_RX%u port. Dai ID is %d\n",
4356 __func__, rx_mix1_inp - 5 , dai->id);
4357 return -EINVAL;
4358 }
4359
4360 rx_mix_1_reg_1 = TAIKO_A_CDC_CONN_RX1_B1_CTL;
4361
4362 for (j = 0; j < NUM_INTERPOLATORS; j++) {
4363 rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
4364
4365 rx_mix_1_reg_1_val = snd_soc_read(codec,
4366 rx_mix_1_reg_1);
4367 rx_mix_1_reg_2_val = snd_soc_read(codec,
4368 rx_mix_1_reg_2);
4369
4370 if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
4371 (((rx_mix_1_reg_1_val >> 4) & 0x0F)
4372 == rx_mix1_inp) ||
4373 ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
4374
4375 rx_fs_reg = TAIKO_A_CDC_RX1_B5_CTL + 8 * j;
4376
4377 pr_debug("%s: AIF_PB DAI(%d) connected to RX%u\n",
4378 __func__, dai->id, j + 1);
4379
4380 pr_debug("%s: set RX%u sample rate to %u\n",
4381 __func__, j + 1, sample_rate);
4382
4383 snd_soc_update_bits(codec, rx_fs_reg,
4384 0xE0, rx_fs_rate_reg_val);
4385
4386 if (comp_rx_path[j] < COMPANDER_MAX)
4387 taiko->comp_fs[comp_rx_path[j]]
4388 = compander_fs;
4389 }
Kuirong Wang94761952013-03-07 16:19:35 -08004390 if (j < 2)
Kuirong Wang906ac472012-07-09 12:54:44 -07004391 rx_mix_1_reg_1 += 3;
4392 else
4393 rx_mix_1_reg_1 += 2;
Kiran Kandic3b24402012-06-11 00:05:59 -07004394 }
4395 }
4396 return 0;
4397}
4398
Kuirong Wang906ac472012-07-09 12:54:44 -07004399static int taiko_set_decimator_rate(struct snd_soc_dai *dai,
4400 u8 tx_fs_rate_reg_val, u32 sample_rate)
Kiran Kandic3b24402012-06-11 00:05:59 -07004401{
Kuirong Wang906ac472012-07-09 12:54:44 -07004402 struct snd_soc_codec *codec = dai->codec;
4403 struct wcd9xxx_ch *ch;
4404 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
4405 u32 tx_port;
4406 u16 tx_port_reg, tx_fs_reg;
4407 u8 tx_port_reg_val;
4408 s8 decimator;
Kiran Kandic3b24402012-06-11 00:05:59 -07004409
Kuirong Wang906ac472012-07-09 12:54:44 -07004410 list_for_each_entry(ch, &taiko->dai[dai->id].wcd9xxx_ch_list, list) {
Kiran Kandic3b24402012-06-11 00:05:59 -07004411
Kuirong Wang906ac472012-07-09 12:54:44 -07004412 tx_port = ch->port + 1;
4413 pr_debug("%s: dai->id = %d, tx_port = %d",
4414 __func__, dai->id, tx_port);
4415
4416 if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
4417 pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
4418 __func__, tx_port, dai->id);
4419 return -EINVAL;
4420 }
4421
4422 tx_port_reg = TAIKO_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
4423 tx_port_reg_val = snd_soc_read(codec, tx_port_reg);
4424
4425 decimator = 0;
4426
4427 if ((tx_port >= 1) && (tx_port <= 6)) {
4428
4429 tx_port_reg_val = tx_port_reg_val & 0x0F;
4430 if (tx_port_reg_val == 0x8)
4431 decimator = tx_port;
4432
4433 } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
4434
4435 tx_port_reg_val = tx_port_reg_val & 0x1F;
4436
4437 if ((tx_port_reg_val >= 0x8) &&
4438 (tx_port_reg_val <= 0x11)) {
4439
4440 decimator = (tx_port_reg_val - 0x8) + 1;
4441 }
4442 }
4443
4444 if (decimator) { /* SLIM_TX port has a DEC as input */
4445
4446 tx_fs_reg = TAIKO_A_CDC_TX1_CLK_FS_CTL +
4447 8 * (decimator - 1);
4448
4449 pr_debug("%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
4450 __func__, decimator, tx_port, sample_rate);
4451
4452 snd_soc_update_bits(codec, tx_fs_reg, 0x07,
4453 tx_fs_rate_reg_val);
4454
4455 } else {
4456 if ((tx_port_reg_val >= 0x1) &&
4457 (tx_port_reg_val <= 0x7)) {
4458
4459 pr_debug("%s: RMIX%u going to SLIM TX%u\n",
4460 __func__, tx_port_reg_val, tx_port);
4461
4462 } else if ((tx_port_reg_val >= 0x8) &&
4463 (tx_port_reg_val <= 0x11)) {
4464
4465 pr_err("%s: ERROR: Should not be here\n",
4466 __func__);
4467 pr_err("%s: ERROR: DEC connected to SLIM TX%u\n",
4468 __func__, tx_port);
4469 return -EINVAL;
4470
4471 } else if (tx_port_reg_val == 0) {
4472 pr_debug("%s: no signal to SLIM TX%u\n",
4473 __func__, tx_port);
4474 } else {
4475 pr_err("%s: ERROR: wrong signal to SLIM TX%u\n",
4476 __func__, tx_port);
4477 pr_err("%s: ERROR: wrong signal = %u\n",
4478 __func__, tx_port_reg_val);
4479 return -EINVAL;
4480 }
4481 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004482 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004483 return 0;
4484}
4485
Patrick Laiff5a5782013-05-05 00:13:00 -07004486static void taiko_set_rxsb_port_format(struct snd_pcm_hw_params *params,
4487 struct snd_soc_dai *dai)
4488{
4489 struct snd_soc_codec *codec = dai->codec;
4490 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
4491 struct wcd9xxx_codec_dai_data *cdc_dai;
4492 struct wcd9xxx_ch *ch;
4493 int port;
4494 u8 bit_sel;
4495 u16 sb_ctl_reg, field_shift;
4496
4497 switch (params_format(params)) {
4498 case SNDRV_PCM_FORMAT_S16_LE:
4499 bit_sel = 0x2;
4500 taiko_p->dai[dai->id].bit_width = 16;
4501 break;
4502 case SNDRV_PCM_FORMAT_S24_LE:
4503 bit_sel = 0x0;
4504 taiko_p->dai[dai->id].bit_width = 24;
4505 break;
4506 default:
4507 dev_err(codec->dev, "Invalid format\n");
4508 return;
4509 }
4510
4511 cdc_dai = &taiko_p->dai[dai->id];
4512
4513 list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
4514 port = wcd9xxx_get_slave_port(ch->ch_num);
4515
4516 if (IS_ERR_VALUE(port) ||
4517 !TAIKO_VALIDATE_RX_SBPORT_RANGE(port)) {
4518 dev_warn(codec->dev,
4519 "%s: invalid port ID %d returned for RX DAI\n",
4520 __func__, port);
4521 return;
4522 }
4523
4524 port = TAIKO_CONVERT_RX_SBPORT_ID(port);
4525
4526 if (port <= 3) {
4527 sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B1_CTL;
4528 field_shift = port << 1;
4529 } else if (port <= 6) {
4530 sb_ctl_reg = TAIKO_A_CDC_CONN_RX_SB_B2_CTL;
4531 field_shift = (port - 4) << 1;
4532 } else { /* should not happen */
4533 dev_warn(codec->dev,
4534 "%s: bad port ID %d\n", __func__, port);
4535 return;
4536 }
4537
4538 dev_dbg(codec->dev, "%s: sb_ctl_reg %x field_shift %x\n",
4539 __func__, sb_ctl_reg, field_shift);
4540 snd_soc_update_bits(codec, sb_ctl_reg, 0x3 << field_shift,
4541 bit_sel << field_shift);
4542 }
4543}
4544
Kiran Kandic3b24402012-06-11 00:05:59 -07004545static int taiko_hw_params(struct snd_pcm_substream *substream,
4546 struct snd_pcm_hw_params *params,
4547 struct snd_soc_dai *dai)
4548{
4549 struct snd_soc_codec *codec = dai->codec;
4550 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
Kuirong Wang906ac472012-07-09 12:54:44 -07004551 u8 tx_fs_rate, rx_fs_rate;
Kiran Kandic3b24402012-06-11 00:05:59 -07004552 u32 compander_fs;
Kuirong Wang906ac472012-07-09 12:54:44 -07004553 int ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004554
4555 pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
4556 dai->name, dai->id, params_rate(params),
4557 params_channels(params));
4558
4559 switch (params_rate(params)) {
4560 case 8000:
4561 tx_fs_rate = 0x00;
4562 rx_fs_rate = 0x00;
4563 compander_fs = COMPANDER_FS_8KHZ;
4564 break;
4565 case 16000:
4566 tx_fs_rate = 0x01;
4567 rx_fs_rate = 0x20;
4568 compander_fs = COMPANDER_FS_16KHZ;
4569 break;
4570 case 32000:
4571 tx_fs_rate = 0x02;
4572 rx_fs_rate = 0x40;
4573 compander_fs = COMPANDER_FS_32KHZ;
4574 break;
4575 case 48000:
4576 tx_fs_rate = 0x03;
4577 rx_fs_rate = 0x60;
4578 compander_fs = COMPANDER_FS_48KHZ;
4579 break;
4580 case 96000:
4581 tx_fs_rate = 0x04;
4582 rx_fs_rate = 0x80;
4583 compander_fs = COMPANDER_FS_96KHZ;
4584 break;
4585 case 192000:
4586 tx_fs_rate = 0x05;
4587 rx_fs_rate = 0xA0;
4588 compander_fs = COMPANDER_FS_192KHZ;
4589 break;
4590 default:
4591 pr_err("%s: Invalid sampling rate %d\n", __func__,
Kuirong Wang906ac472012-07-09 12:54:44 -07004592 params_rate(params));
Kiran Kandic3b24402012-06-11 00:05:59 -07004593 return -EINVAL;
4594 }
4595
Kuirong Wang906ac472012-07-09 12:54:44 -07004596 switch (substream->stream) {
4597 case SNDRV_PCM_STREAM_CAPTURE:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004598 if (dai->id != AIF4_VIFEED) {
4599 ret = taiko_set_decimator_rate(dai, tx_fs_rate,
4600 params_rate(params));
4601 if (ret < 0) {
4602 pr_err("%s: set decimator rate failed %d\n",
4603 __func__, ret);
4604 return ret;
4605 }
Kiran Kandic3b24402012-06-11 00:05:59 -07004606 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004607
Kiran Kandic3b24402012-06-11 00:05:59 -07004608 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4609 switch (params_format(params)) {
4610 case SNDRV_PCM_FORMAT_S16_LE:
4611 snd_soc_update_bits(codec,
4612 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4613 0x20, 0x20);
4614 break;
4615 case SNDRV_PCM_FORMAT_S32_LE:
4616 snd_soc_update_bits(codec,
4617 TAIKO_A_CDC_CLK_TX_I2S_CTL,
4618 0x20, 0x00);
4619 break;
4620 default:
4621 pr_err("invalid format\n");
4622 break;
4623 }
4624 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004625 0x07, tx_fs_rate);
Kiran Kandic3b24402012-06-11 00:05:59 -07004626 } else {
Kuirong Wang906ac472012-07-09 12:54:44 -07004627 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004628 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004629 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004630
Kuirong Wang906ac472012-07-09 12:54:44 -07004631 case SNDRV_PCM_STREAM_PLAYBACK:
4632 ret = taiko_set_interpolator_rate(dai, rx_fs_rate,
4633 compander_fs,
4634 params_rate(params));
4635 if (ret < 0) {
4636 pr_err("%s: set decimator rate failed %d\n", __func__,
4637 ret);
4638 return ret;
Kiran Kandic3b24402012-06-11 00:05:59 -07004639 }
4640 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
4641 switch (params_format(params)) {
4642 case SNDRV_PCM_FORMAT_S16_LE:
4643 snd_soc_update_bits(codec,
4644 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4645 0x20, 0x20);
4646 break;
4647 case SNDRV_PCM_FORMAT_S32_LE:
4648 snd_soc_update_bits(codec,
4649 TAIKO_A_CDC_CLK_RX_I2S_CTL,
4650 0x20, 0x00);
4651 break;
4652 default:
4653 pr_err("invalid format\n");
4654 break;
4655 }
4656 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
Kuirong Wang906ac472012-07-09 12:54:44 -07004657 0x03, (rx_fs_rate >> 0x05));
Kiran Kandic3b24402012-06-11 00:05:59 -07004658 } else {
Patrick Laiff5a5782013-05-05 00:13:00 -07004659 taiko_set_rxsb_port_format(params, dai);
Kuirong Wang906ac472012-07-09 12:54:44 -07004660 taiko->dai[dai->id].rate = params_rate(params);
Kiran Kandic3b24402012-06-11 00:05:59 -07004661 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004662 break;
4663 default:
4664 pr_err("%s: Invalid stream type %d\n", __func__,
4665 substream->stream);
4666 return -EINVAL;
Kiran Kandic3b24402012-06-11 00:05:59 -07004667 }
4668
4669 return 0;
4670}
4671
4672static struct snd_soc_dai_ops taiko_dai_ops = {
4673 .startup = taiko_startup,
4674 .shutdown = taiko_shutdown,
4675 .hw_params = taiko_hw_params,
4676 .set_sysclk = taiko_set_dai_sysclk,
4677 .set_fmt = taiko_set_dai_fmt,
4678 .set_channel_map = taiko_set_channel_map,
4679 .get_channel_map = taiko_get_channel_map,
4680};
4681
4682static struct snd_soc_dai_driver taiko_dai[] = {
4683 {
4684 .name = "taiko_rx1",
4685 .id = AIF1_PB,
4686 .playback = {
4687 .stream_name = "AIF1 Playback",
4688 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004689 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004690 .rate_max = 192000,
4691 .rate_min = 8000,
4692 .channels_min = 1,
4693 .channels_max = 2,
4694 },
4695 .ops = &taiko_dai_ops,
4696 },
4697 {
4698 .name = "taiko_tx1",
4699 .id = AIF1_CAP,
4700 .capture = {
4701 .stream_name = "AIF1 Capture",
4702 .rates = WCD9320_RATES,
4703 .formats = TAIKO_FORMATS,
4704 .rate_max = 192000,
4705 .rate_min = 8000,
4706 .channels_min = 1,
4707 .channels_max = 4,
4708 },
4709 .ops = &taiko_dai_ops,
4710 },
4711 {
4712 .name = "taiko_rx2",
4713 .id = AIF2_PB,
4714 .playback = {
4715 .stream_name = "AIF2 Playback",
4716 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004717 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004718 .rate_min = 8000,
4719 .rate_max = 192000,
4720 .channels_min = 1,
4721 .channels_max = 2,
4722 },
4723 .ops = &taiko_dai_ops,
4724 },
4725 {
4726 .name = "taiko_tx2",
4727 .id = AIF2_CAP,
4728 .capture = {
4729 .stream_name = "AIF2 Capture",
4730 .rates = WCD9320_RATES,
4731 .formats = TAIKO_FORMATS,
4732 .rate_max = 192000,
4733 .rate_min = 8000,
4734 .channels_min = 1,
Ravit Dennis895a5572013-06-05 16:34:42 +03004735 .channels_max = 8,
Kiran Kandic3b24402012-06-11 00:05:59 -07004736 },
4737 .ops = &taiko_dai_ops,
4738 },
4739 {
4740 .name = "taiko_tx3",
4741 .id = AIF3_CAP,
4742 .capture = {
4743 .stream_name = "AIF3 Capture",
4744 .rates = WCD9320_RATES,
4745 .formats = TAIKO_FORMATS,
4746 .rate_max = 48000,
4747 .rate_min = 8000,
4748 .channels_min = 1,
4749 .channels_max = 2,
4750 },
4751 .ops = &taiko_dai_ops,
4752 },
4753 {
4754 .name = "taiko_rx3",
4755 .id = AIF3_PB,
4756 .playback = {
4757 .stream_name = "AIF3 Playback",
4758 .rates = WCD9320_RATES,
Bhalchandra Gajare5b40c532013-02-19 13:36:47 -08004759 .formats = TAIKO_FORMATS_S16_S24_LE,
Kiran Kandic3b24402012-06-11 00:05:59 -07004760 .rate_min = 8000,
4761 .rate_max = 192000,
4762 .channels_min = 1,
4763 .channels_max = 2,
4764 },
4765 .ops = &taiko_dai_ops,
4766 },
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004767 {
4768 .name = "taiko_vifeedback",
4769 .id = AIF4_VIFEED,
4770 .capture = {
4771 .stream_name = "VIfeed",
4772 .rates = SNDRV_PCM_RATE_48000,
4773 .formats = TAIKO_FORMATS,
4774 .rate_max = 48000,
4775 .rate_min = 48000,
4776 .channels_min = 2,
4777 .channels_max = 2,
4778 },
4779 .ops = &taiko_dai_ops,
4780 },
Joonwoo Park1d05bb92013-03-07 16:55:06 -08004781 {
4782 .name = "taiko_mad1",
4783 .id = AIF4_MAD_TX,
4784 .capture = {
4785 .stream_name = "AIF4 MAD TX",
4786 .rates = SNDRV_PCM_RATE_16000,
4787 .formats = TAIKO_FORMATS,
4788 .rate_min = 16000,
4789 .rate_max = 16000,
4790 .channels_min = 1,
4791 .channels_max = 1,
4792 },
4793 .ops = &taiko_dai_ops,
4794 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004795};
4796
4797static struct snd_soc_dai_driver taiko_i2s_dai[] = {
4798 {
4799 .name = "taiko_i2s_rx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004800 .id = AIF1_PB,
Kiran Kandic3b24402012-06-11 00:05:59 -07004801 .playback = {
4802 .stream_name = "AIF1 Playback",
4803 .rates = WCD9320_RATES,
4804 .formats = TAIKO_FORMATS,
4805 .rate_max = 192000,
4806 .rate_min = 8000,
4807 .channels_min = 1,
4808 .channels_max = 4,
4809 },
4810 .ops = &taiko_dai_ops,
4811 },
4812 {
4813 .name = "taiko_i2s_tx1",
Kuirong Wang906ac472012-07-09 12:54:44 -07004814 .id = AIF1_CAP,
Kiran Kandic3b24402012-06-11 00:05:59 -07004815 .capture = {
4816 .stream_name = "AIF1 Capture",
4817 .rates = WCD9320_RATES,
4818 .formats = TAIKO_FORMATS,
4819 .rate_max = 192000,
4820 .rate_min = 8000,
4821 .channels_min = 1,
4822 .channels_max = 4,
4823 },
4824 .ops = &taiko_dai_ops,
4825 },
Venkat Sudhir994193b2012-12-17 17:30:51 -08004826 {
4827 .name = "taiko_i2s_rx2",
4828 .id = AIF1_PB,
4829 .playback = {
4830 .stream_name = "AIF2 Playback",
4831 .rates = WCD9320_RATES,
4832 .formats = TAIKO_FORMATS,
4833 .rate_max = 192000,
4834 .rate_min = 8000,
4835 .channels_min = 1,
4836 .channels_max = 4,
4837 },
4838 .ops = &taiko_dai_ops,
4839 },
4840 {
4841 .name = "taiko_i2s_tx2",
4842 .id = AIF1_CAP,
4843 .capture = {
4844 .stream_name = "AIF2 Capture",
4845 .rates = WCD9320_RATES,
4846 .formats = TAIKO_FORMATS,
4847 .rate_max = 192000,
4848 .rate_min = 8000,
4849 .channels_min = 1,
4850 .channels_max = 4,
4851 },
4852 .ops = &taiko_dai_ops,
4853 },
Kiran Kandic3b24402012-06-11 00:05:59 -07004854};
4855
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004856static int taiko_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
4857 bool up)
4858{
4859 int ret = 0;
4860 struct wcd9xxx_ch *ch;
4861
4862 if (up) {
4863 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
4864 ret = wcd9xxx_get_slave_port(ch->ch_num);
4865 if (ret < 0) {
4866 pr_err("%s: Invalid slave port ID: %d\n",
4867 __func__, ret);
4868 ret = -EINVAL;
4869 } else {
4870 set_bit(ret, &dai->ch_mask);
4871 }
4872 }
4873 } else {
4874 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
4875 msecs_to_jiffies(
4876 TAIKO_SLIM_CLOSE_TIMEOUT));
4877 if (!ret) {
4878 pr_err("%s: Slim close tx/rx wait timeout\n", __func__);
4879 ret = -ETIMEDOUT;
4880 } else {
4881 ret = 0;
4882 }
4883 }
4884 return ret;
4885}
4886
Kiran Kandic3b24402012-06-11 00:05:59 -07004887static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07004888 struct snd_kcontrol *kcontrol,
4889 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07004890{
Kuirong Wang906ac472012-07-09 12:54:44 -07004891 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07004892 struct snd_soc_codec *codec = w->codec;
4893 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004894 int ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07004895 struct wcd9xxx_codec_dai_data *dai;
4896
4897 core = dev_get_drvdata(codec->dev->parent);
4898
4899 pr_debug("%s: event called! codec name %s num_dai %d\n"
4900 "stream name %s event %d\n",
4901 __func__, w->codec->name, w->codec->num_dai, w->sname, event);
4902
Kiran Kandic3b24402012-06-11 00:05:59 -07004903 /* Execute the callback only if interface type is slimbus */
4904 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
4905 return 0;
4906
Kuirong Wang906ac472012-07-09 12:54:44 -07004907 dai = &taiko_p->dai[w->shift];
4908 pr_debug("%s: w->name %s w->shift %d event %d\n",
4909 __func__, w->name, w->shift, event);
Kiran Kandic3b24402012-06-11 00:05:59 -07004910
4911 switch (event) {
4912 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004913 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07004914 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4915 dai->rate, dai->bit_width,
4916 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07004917 break;
4918 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07004919 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
4920 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08004921 ret = taiko_codec_enable_slim_chmask(dai, false);
4922 if (ret < 0) {
4923 ret = wcd9xxx_disconnect_port(core,
4924 &dai->wcd9xxx_ch_list,
4925 dai->grph);
4926 pr_debug("%s: Disconnect RX port, ret = %d\n",
4927 __func__, ret);
4928 }
Kuirong Wang906ac472012-07-09 12:54:44 -07004929 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07004930 }
4931 return ret;
4932}
4933
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004934static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
4935 struct snd_kcontrol *kcontrol,
4936 int event)
4937{
4938 struct wcd9xxx *core = NULL;
4939 struct snd_soc_codec *codec = NULL;
4940 struct taiko_priv *taiko_p = NULL;
4941 u32 ret = 0;
4942 struct wcd9xxx_codec_dai_data *dai = NULL;
4943
4944 if (!w || !w->codec) {
4945 pr_err("%s invalid params\n", __func__);
4946 return -EINVAL;
4947 }
4948 codec = w->codec;
4949 taiko_p = snd_soc_codec_get_drvdata(codec);
4950 core = dev_get_drvdata(codec->dev->parent);
4951
4952 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
4953 __func__, w->codec->name, w->codec->num_dai, w->sname);
4954
4955 /* Execute the callback only if interface type is slimbus */
4956 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
4957 pr_err("%s Interface is not correct", __func__);
4958 return 0;
4959 }
4960
4961 pr_debug("%s(): w->name %s event %d w->shift %d\n",
4962 __func__, w->name, event, w->shift);
4963 if (w->shift != AIF4_VIFEED) {
4964 pr_err("%s Error in enabling the tx path\n", __func__);
4965 ret = -EINVAL;
4966 goto out_vi;
4967 }
4968 dai = &taiko_p->dai[w->shift];
4969 switch (event) {
4970 case SND_SOC_DAPM_POST_PMU:
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004971 /*Enable V&I sensing*/
4972 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4973 0x88, 0x88);
4974 /*Enable spkr VI clocks*/
4975 snd_soc_update_bits(codec,
4976 TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
Gopikrishnaiah Anandand3b89c02013-04-16 11:22:15 -04004977 (void) taiko_codec_enable_slim_chmask(dai, true);
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004978 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4979 dai->rate, dai->bit_width,
4980 &dai->grph);
4981 break;
4982 case SND_SOC_DAPM_POST_PMD:
4983 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
4984 dai->grph);
4985 if (ret)
4986 pr_err("%s error in close_slim_sch_tx %d\n",
4987 __func__, ret);
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004988 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
4989 0xC, 0x0);
4990 /*Disable V&I sensing*/
4991 snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
4992 0x88, 0x00);
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05004993 break;
4994 }
4995out_vi:
4996 return ret;
4997}
4998
Kiran Kandic3b24402012-06-11 00:05:59 -07004999static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
Kuirong Wang906ac472012-07-09 12:54:44 -07005000 struct snd_kcontrol *kcontrol,
5001 int event)
Kiran Kandic3b24402012-06-11 00:05:59 -07005002{
Kuirong Wang906ac472012-07-09 12:54:44 -07005003 struct wcd9xxx *core;
Kiran Kandic3b24402012-06-11 00:05:59 -07005004 struct snd_soc_codec *codec = w->codec;
5005 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07005006 u32 ret = 0;
Kuirong Wang906ac472012-07-09 12:54:44 -07005007 struct wcd9xxx_codec_dai_data *dai;
Kiran Kandic3b24402012-06-11 00:05:59 -07005008
Kuirong Wang906ac472012-07-09 12:54:44 -07005009 core = dev_get_drvdata(codec->dev->parent);
5010
5011 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
5012 __func__, w->codec->name, w->codec->num_dai, w->sname);
Kiran Kandic3b24402012-06-11 00:05:59 -07005013
5014 /* Execute the callback only if interface type is slimbus */
5015 if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
5016 return 0;
5017
Kuirong Wang906ac472012-07-09 12:54:44 -07005018 pr_debug("%s(): w->name %s event %d w->shift %d\n",
5019 __func__, w->name, event, w->shift);
Kiran Kandic3b24402012-06-11 00:05:59 -07005020
Kuirong Wang906ac472012-07-09 12:54:44 -07005021 dai = &taiko_p->dai[w->shift];
Kiran Kandic3b24402012-06-11 00:05:59 -07005022 switch (event) {
5023 case SND_SOC_DAPM_POST_PMU:
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005024 (void) taiko_codec_enable_slim_chmask(dai, true);
Kuirong Wang906ac472012-07-09 12:54:44 -07005025 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
5026 dai->rate, dai->bit_width,
5027 &dai->grph);
Kiran Kandic3b24402012-06-11 00:05:59 -07005028 break;
5029 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang906ac472012-07-09 12:54:44 -07005030 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
5031 dai->grph);
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005032 ret = taiko_codec_enable_slim_chmask(dai, false);
5033 if (ret < 0) {
5034 ret = wcd9xxx_disconnect_port(core,
5035 &dai->wcd9xxx_ch_list,
5036 dai->grph);
5037 pr_debug("%s: Disconnect RX port, ret = %d\n",
5038 __func__, ret);
5039 }
Kuirong Wang906ac472012-07-09 12:54:44 -07005040 break;
Kiran Kandic3b24402012-06-11 00:05:59 -07005041 }
5042 return ret;
5043}
5044
Kiran Kandi4c56c592012-07-25 11:04:55 -07005045static int taiko_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
5046 struct snd_kcontrol *kcontrol, int event)
5047{
5048 struct snd_soc_codec *codec = w->codec;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005049 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
Kiran Kandi4c56c592012-07-25 11:04:55 -07005050
5051 pr_debug("%s %s %d\n", __func__, w->name, event);
5052
5053 switch (event) {
Kiran Kandi4c56c592012-07-25 11:04:55 -07005054 case SND_SOC_DAPM_POST_PMU:
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005055 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5056 WCD9XXX_CLSH_STATE_EAR,
5057 WCD9XXX_CLSH_REQ_ENABLE,
5058 WCD9XXX_CLSH_EVENT_POST_PA);
Kiran Kandi4c56c592012-07-25 11:04:55 -07005059
5060 usleep_range(5000, 5000);
5061 break;
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005062 case SND_SOC_DAPM_POST_PMD:
5063 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5064 WCD9XXX_CLSH_STATE_EAR,
5065 WCD9XXX_CLSH_REQ_DISABLE,
5066 WCD9XXX_CLSH_EVENT_POST_PA);
5067 usleep_range(5000, 5000);
5068 }
5069 return 0;
5070}
5071
5072static int taiko_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
5073 struct snd_kcontrol *kcontrol, int event)
5074{
5075 struct snd_soc_codec *codec = w->codec;
5076 struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
5077
5078 pr_debug("%s %s %d\n", __func__, w->name, event);
5079
5080 switch (event) {
5081 case SND_SOC_DAPM_PRE_PMU:
5082 wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
5083 WCD9XXX_CLSH_STATE_EAR,
5084 WCD9XXX_CLSH_REQ_ENABLE,
5085 WCD9XXX_CLSH_EVENT_PRE_DAC);
5086 break;
5087 }
5088
5089 return 0;
5090}
5091
5092static int taiko_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
5093 struct snd_kcontrol *kcontrol, int event)
5094{
5095 struct snd_soc_codec *codec = w->codec;
5096 u8 reg_val, zoh_mux_val = 0x00;
5097
5098 pr_debug("%s: event = %d\n", __func__, event);
5099
5100 switch (event) {
5101 case SND_SOC_DAPM_POST_PMU:
5102 reg_val = snd_soc_read(codec, TAIKO_A_CDC_CONN_CLSH_CTL);
5103
5104 if ((reg_val & 0x30) == 0x10)
5105 zoh_mux_val = 0x04;
5106 else if ((reg_val & 0x30) == 0x20)
5107 zoh_mux_val = 0x08;
5108
5109 if (zoh_mux_val != 0x00)
5110 snd_soc_update_bits(codec,
5111 TAIKO_A_CDC_CONN_CLSH_CTL,
5112 0x0C, zoh_mux_val);
5113 break;
5114
5115 case SND_SOC_DAPM_POST_PMD:
5116 snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_CLSH_CTL,
5117 0x0C, 0x00);
5118 break;
Kiran Kandi4c56c592012-07-25 11:04:55 -07005119 }
5120 return 0;
5121}
5122
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08005123static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
5124 struct snd_kcontrol *kcontrol, int event)
5125{
5126 struct snd_soc_codec *codec = w->codec;
5127 int ret = 0;
5128
5129 switch (event) {
5130 case SND_SOC_DAPM_PRE_PMU:
5131 ret = taiko_codec_enable_anc(w, kcontrol, event);
5132 msleep(50);
5133 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
5134 break;
5135 case SND_SOC_DAPM_POST_PMU:
5136 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
5137 break;
5138 case SND_SOC_DAPM_PRE_PMD:
5139 snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
5140 msleep(40);
5141 ret |= taiko_codec_enable_anc(w, kcontrol, event);
5142 break;
5143 case SND_SOC_DAPM_POST_PMD:
5144 ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
5145 break;
5146 }
5147 return ret;
5148}
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005149
Kiran Kandic3b24402012-06-11 00:05:59 -07005150/* Todo: Have seperate dapm widgets for I2S and Slimbus.
5151 * Might Need to have callbacks registered only for slimbus
5152 */
5153static const struct snd_soc_dapm_widget taiko_dapm_widgets[] = {
5154 /*RX stuff */
5155 SND_SOC_DAPM_OUTPUT("EAR"),
5156
Kiran Kandi4c56c592012-07-25 11:04:55 -07005157 SND_SOC_DAPM_PGA_E("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0,
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005158 taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
5159 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005160
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005161 SND_SOC_DAPM_MIXER_E("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
5162 ARRAY_SIZE(dac1_switch), taiko_codec_ear_dac_event,
5163 SND_SOC_DAPM_PRE_PMU),
Kiran Kandic3b24402012-06-11 00:05:59 -07005164
Kuirong Wang906ac472012-07-09 12:54:44 -07005165 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
5166 AIF1_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005167 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07005168 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
5169 AIF2_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005170 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kuirong Wang906ac472012-07-09 12:54:44 -07005171 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
5172 AIF3_PB, 0, taiko_codec_enable_slimrx,
Kiran Kandic3b24402012-06-11 00:05:59 -07005173 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5174
Kuirong Wang906ac472012-07-09 12:54:44 -07005175 SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, TAIKO_RX1, 0,
5176 &slim_rx_mux[TAIKO_RX1]),
5177 SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, TAIKO_RX2, 0,
5178 &slim_rx_mux[TAIKO_RX2]),
5179 SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, TAIKO_RX3, 0,
5180 &slim_rx_mux[TAIKO_RX3]),
5181 SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, TAIKO_RX4, 0,
5182 &slim_rx_mux[TAIKO_RX4]),
5183 SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, TAIKO_RX5, 0,
5184 &slim_rx_mux[TAIKO_RX5]),
5185 SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, TAIKO_RX6, 0,
5186 &slim_rx_mux[TAIKO_RX6]),
5187 SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, TAIKO_RX7, 0,
5188 &slim_rx_mux[TAIKO_RX7]),
Kiran Kandic3b24402012-06-11 00:05:59 -07005189
Kuirong Wang906ac472012-07-09 12:54:44 -07005190 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5191 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
5192 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
5193 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
5194 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
5195 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
5196 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
Kiran Kandic3b24402012-06-11 00:05:59 -07005197
5198 /* Headphone */
5199 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
5200 SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
5201 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07005202 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005203 SND_SOC_DAPM_MIXER_E("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
5204 hphl_switch, ARRAY_SIZE(hphl_switch), taiko_hphl_dac_event,
5205 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005206
5207 SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
5208 taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
Kiran Kandi4c56c592012-07-25 11:04:55 -07005209 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005210
5211 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
5212 taiko_hphr_dac_event,
5213 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5214
5215 /* Speaker */
5216 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
5217 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
5218 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
5219 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005220 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005221
5222 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAIKO_A_RX_LINE_CNP_EN, 0, 0, NULL,
5223 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5224 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5225 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAIKO_A_RX_LINE_CNP_EN, 1, 0, NULL,
5226 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5227 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5228 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TAIKO_A_RX_LINE_CNP_EN, 2, 0, NULL,
5229 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5230 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5231 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
5232 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
5233 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005234 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
5235 0, taiko_codec_enable_spk_pa,
5236 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005237
5238 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
5239 , taiko_lineout_dac_event,
5240 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5241 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAIKO_A_RX_LINE_2_DAC_CTL, 7, 0
5242 , taiko_lineout_dac_event,
5243 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5244 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TAIKO_A_RX_LINE_3_DAC_CTL, 7, 0
5245 , taiko_lineout_dac_event,
5246 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5247 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
5248 &lineout3_ground_switch),
5249 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TAIKO_A_RX_LINE_4_DAC_CTL, 7, 0
5250 , taiko_lineout_dac_event,
5251 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5252 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
5253 &lineout4_ground_switch),
5254
Joonwoo Park7680b9f2012-07-13 11:36:48 -07005255 SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
5256 taiko_spk_dac_event,
5257 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5258
Joonwoo Park125cd4e2012-12-11 15:16:11 -08005259 SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
5260 taiko_codec_enable_vdd_spkr,
5261 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5262
Kiran Kandid2b46332012-10-05 12:04:00 -07005263 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5264 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5265 SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
5266
Kiran Kandic3b24402012-06-11 00:05:59 -07005267 SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005268 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005269 SND_SOC_DAPM_POST_PMU),
5270 SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005271 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005272 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07005273 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005274 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005275 SND_SOC_DAPM_POST_PMU),
5276 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005277 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005278 SND_SOC_DAPM_POST_PMU),
5279 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005280 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005281 SND_SOC_DAPM_POST_PMU),
5282 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005283 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005284 SND_SOC_DAPM_POST_PMU),
Kiran Kandid2b46332012-10-05 12:04:00 -07005285 SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005286 0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
Kiran Kandic3b24402012-06-11 00:05:59 -07005287 SND_SOC_DAPM_POST_PMU),
5288
Kiran Kandic3b24402012-06-11 00:05:59 -07005289
5290 SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
5291 SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
5292
5293 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5294 &rx_mix1_inp1_mux),
5295 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5296 &rx_mix1_inp2_mux),
5297 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
5298 &rx_mix1_inp3_mux),
5299 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5300 &rx2_mix1_inp1_mux),
5301 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5302 &rx2_mix1_inp2_mux),
5303 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5304 &rx3_mix1_inp1_mux),
5305 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5306 &rx3_mix1_inp2_mux),
5307 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5308 &rx4_mix1_inp1_mux),
5309 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5310 &rx4_mix1_inp2_mux),
5311 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5312 &rx5_mix1_inp1_mux),
5313 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5314 &rx5_mix1_inp2_mux),
5315 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5316 &rx6_mix1_inp1_mux),
5317 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5318 &rx6_mix1_inp2_mux),
5319 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
5320 &rx7_mix1_inp1_mux),
5321 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
5322 &rx7_mix1_inp2_mux),
5323 SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5324 &rx1_mix2_inp1_mux),
5325 SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5326 &rx1_mix2_inp2_mux),
5327 SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5328 &rx2_mix2_inp1_mux),
5329 SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5330 &rx2_mix2_inp2_mux),
5331 SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
5332 &rx7_mix2_inp1_mux),
5333 SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
5334 &rx7_mix2_inp2_mux),
5335
Tanya Finkeldaaa6d12012-10-25 11:22:48 +02005336 SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
5337 &rx_dac5_mux),
5338 SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
5339 &rx_dac7_mux),
5340
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005341 SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
5342 &class_h_dsm_mux, taiko_codec_dsm_mux_event,
5343 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005344
Kiran Kandic3b24402012-06-11 00:05:59 -07005345 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
5346 taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
5347 SND_SOC_DAPM_POST_PMD),
5348
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005349 SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 5, 0,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005350 NULL, 0),
5351
Kiran Kandic3b24402012-06-11 00:05:59 -07005352 /* TX */
5353
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005354 SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
Kiran Kandic3b24402012-06-11 00:05:59 -07005355 0),
5356
Joonwoo Parkccccba72013-04-26 11:19:46 -07005357 SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0,
5358 taiko_codec_enable_ldo_h,
5359 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
5360 /*
5361 * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after
5362 * acquring codec_resource lock.
5363 * So call __taiko_codec_enable_ldo_h instead and avoid deadlock.
5364 */
5365 SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0,
5366 __taiko_codec_enable_ldo_h,
5367 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005368
Joonwoo Parkc7731432012-10-17 12:41:44 -07005369 SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005370 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005371 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005372 SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
5373 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005374 SND_SOC_DAPM_PRE_PMD),
Joonwoo Parkc7731432012-10-17 12:41:44 -07005375 SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
Kiran Kandic3b24402012-06-11 00:05:59 -07005376 taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
Bhalchandra Gajareed090e62013-03-29 16:11:49 -07005377 SND_SOC_DAPM_PRE_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005378
5379
5380 SND_SOC_DAPM_INPUT("AMIC1"),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005381 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
5382 taiko_codec_enable_micbias,
5383 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5384 SND_SOC_DAPM_POST_PMD),
5385 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
5386 taiko_codec_enable_micbias,
5387 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5388 SND_SOC_DAPM_POST_PMD),
5389 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
5390 taiko_codec_enable_micbias,
5391 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5392 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005393
5394 SND_SOC_DAPM_INPUT("AMIC3"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005395
5396 SND_SOC_DAPM_INPUT("AMIC4"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005397
5398 SND_SOC_DAPM_INPUT("AMIC5"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005399
5400 SND_SOC_DAPM_INPUT("AMIC6"),
Kiran Kandic3b24402012-06-11 00:05:59 -07005401
5402 SND_SOC_DAPM_MUX_E("DEC1 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
5403 &dec1_mux, taiko_codec_enable_dec,
5404 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5405 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5406
5407 SND_SOC_DAPM_MUX_E("DEC2 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
5408 &dec2_mux, taiko_codec_enable_dec,
5409 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5410 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5411
5412 SND_SOC_DAPM_MUX_E("DEC3 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
5413 &dec3_mux, taiko_codec_enable_dec,
5414 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5415 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5416
5417 SND_SOC_DAPM_MUX_E("DEC4 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
5418 &dec4_mux, taiko_codec_enable_dec,
5419 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5420 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5421
5422 SND_SOC_DAPM_MUX_E("DEC5 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
5423 &dec5_mux, taiko_codec_enable_dec,
5424 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5425 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5426
5427 SND_SOC_DAPM_MUX_E("DEC6 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
5428 &dec6_mux, taiko_codec_enable_dec,
5429 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5430 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5431
5432 SND_SOC_DAPM_MUX_E("DEC7 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
5433 &dec7_mux, taiko_codec_enable_dec,
5434 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5435 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5436
5437 SND_SOC_DAPM_MUX_E("DEC8 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
5438 &dec8_mux, taiko_codec_enable_dec,
5439 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5440 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5441
5442 SND_SOC_DAPM_MUX_E("DEC9 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
5443 &dec9_mux, taiko_codec_enable_dec,
5444 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5445 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5446
5447 SND_SOC_DAPM_MUX_E("DEC10 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
5448 &dec10_mux, taiko_codec_enable_dec,
5449 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5450 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
5451
5452 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
5453 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
5454
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08005455 SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
5456 SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
5457 taiko_codec_enable_anc_hph,
5458 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5459 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
5460 SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
5461 taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
5462 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
5463 SND_SOC_DAPM_POST_PMU),
5464 SND_SOC_DAPM_OUTPUT("ANC EAR"),
5465 SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
5466 taiko_codec_enable_anc_ear,
5467 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
5468 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005469 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
5470
5471 SND_SOC_DAPM_INPUT("AMIC2"),
Joonwoo Parkccccba72013-04-26 11:19:46 -07005472 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM,
5473 7, 0, taiko_codec_enable_micbias,
5474 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5475 SND_SOC_DAPM_POST_PMD),
Joonwoo Park3699ca32013-02-08 12:06:15 -08005476 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
5477 taiko_codec_enable_micbias,
5478 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5479 SND_SOC_DAPM_POST_PMD),
5480 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
5481 taiko_codec_enable_micbias,
5482 SND_SOC_DAPM_PRE_PMU |
5483 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5484 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
5485 taiko_codec_enable_micbias,
5486 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5487 SND_SOC_DAPM_POST_PMD),
5488 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
5489 taiko_codec_enable_micbias,
5490 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5491 SND_SOC_DAPM_POST_PMD),
5492 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
5493 taiko_codec_enable_micbias,
5494 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5495 SND_SOC_DAPM_POST_PMD),
5496 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
5497 taiko_codec_enable_micbias,
5498 SND_SOC_DAPM_PRE_PMU |
5499 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5500 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
5501 taiko_codec_enable_micbias,
5502 SND_SOC_DAPM_PRE_PMU |
5503 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
5504 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", SND_SOC_NOPM, 7,
5505 0, taiko_codec_enable_micbias,
5506 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
5507 SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005508
Kuirong Wang906ac472012-07-09 12:54:44 -07005509 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
5510 AIF1_CAP, 0, taiko_codec_enable_slimtx,
5511 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005512
Kuirong Wang906ac472012-07-09 12:54:44 -07005513 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
5514 AIF2_CAP, 0, taiko_codec_enable_slimtx,
5515 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005516
Kuirong Wang906ac472012-07-09 12:54:44 -07005517 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
5518 AIF3_CAP, 0, taiko_codec_enable_slimtx,
5519 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Kiran Kandic3b24402012-06-11 00:05:59 -07005520
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005521 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
5522 AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
5523 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005524 SND_SOC_DAPM_AIF_OUT_E("AIF4 MAD", "AIF4 MAD TX", 0,
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005525 SND_SOC_NOPM, 0, 0,
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005526 taiko_codec_enable_mad, SND_SOC_DAPM_PRE_PMU),
Joonwoo Park9ead0e92013-03-18 11:33:33 -07005527 SND_SOC_DAPM_SWITCH("MADONOFF", SND_SOC_NOPM, 0, 0,
5528 &aif4_mad_switch),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005529 SND_SOC_DAPM_INPUT("MADINPUT"),
Gopikrishnaiah Anandana2627572013-02-26 13:30:50 -05005530
Kuirong Wang906ac472012-07-09 12:54:44 -07005531 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
5532 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005533
Kuirong Wang906ac472012-07-09 12:54:44 -07005534 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
5535 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005536
Kuirong Wang906ac472012-07-09 12:54:44 -07005537 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
5538 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005539
Kuirong Wang906ac472012-07-09 12:54:44 -07005540 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAIKO_TX1, 0,
5541 &sb_tx1_mux),
5542 SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAIKO_TX2, 0,
5543 &sb_tx2_mux),
5544 SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAIKO_TX3, 0,
5545 &sb_tx3_mux),
5546 SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAIKO_TX4, 0,
5547 &sb_tx4_mux),
5548 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TAIKO_TX5, 0,
5549 &sb_tx5_mux),
5550 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, TAIKO_TX6, 0,
5551 &sb_tx6_mux),
5552 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, TAIKO_TX7, 0,
5553 &sb_tx7_mux),
5554 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, TAIKO_TX8, 0,
5555 &sb_tx8_mux),
5556 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, TAIKO_TX9, 0,
5557 &sb_tx9_mux),
5558 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, TAIKO_TX10, 0,
5559 &sb_tx10_mux),
Kiran Kandic3b24402012-06-11 00:05:59 -07005560
5561 /* Digital Mic Inputs */
5562 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
5563 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5564 SND_SOC_DAPM_POST_PMD),
5565
5566 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
5567 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5568 SND_SOC_DAPM_POST_PMD),
5569
5570 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
5571 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5572 SND_SOC_DAPM_POST_PMD),
5573
5574 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
5575 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5576 SND_SOC_DAPM_POST_PMD),
5577
5578 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
5579 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5580 SND_SOC_DAPM_POST_PMD),
5581 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
5582 taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
5583 SND_SOC_DAPM_POST_PMD),
5584
5585 /* Sidetone */
5586 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
Kiran Kandibd85d772013-05-19 19:03:43 -07005587 SND_SOC_DAPM_MIXER("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
Kiran Kandic3b24402012-06-11 00:05:59 -07005588
Fred Oh456fcb52013-02-28 19:08:15 -08005589 SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
Kiran Kandibd85d772013-05-19 19:03:43 -07005590 SND_SOC_DAPM_MIXER("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
Fred Oh456fcb52013-02-28 19:08:15 -08005591
Kiran Kandic3b24402012-06-11 00:05:59 -07005592 /* AUX PGA */
5593 SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
5594 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5595 SND_SOC_DAPM_POST_PMD),
5596
5597 SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAIKO_A_RX_AUX_SW_CTL, 6, 0,
5598 taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
5599 SND_SOC_DAPM_POST_PMD),
5600
5601 /* Lineout, ear and HPH PA Mixers */
5602
5603 SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5604 ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
5605
5606 SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
5607 hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
5608
5609 SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
5610 hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
5611
5612 SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
5613 lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
5614
5615 SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
5616 lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
5617
5618 SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
5619 lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
5620
5621 SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
5622 lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
Kiran Kandic3b24402012-06-11 00:05:59 -07005623};
5624
Kiran Kandic3b24402012-06-11 00:05:59 -07005625static irqreturn_t taiko_slimbus_irq(int irq, void *data)
5626{
5627 struct taiko_priv *priv = data;
5628 struct snd_soc_codec *codec = priv->codec;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005629 unsigned long status = 0;
5630 int i, j, port_id, k;
5631 u32 bit;
Kiran Kandic3b24402012-06-11 00:05:59 -07005632 u8 val;
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005633 bool tx, cleared;
Kiran Kandic3b24402012-06-11 00:05:59 -07005634
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005635 for (i = TAIKO_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
5636 i <= TAIKO_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
5637 val = wcd9xxx_interface_reg_read(codec->control_data, i);
5638 status |= ((u32)val << (8 * j));
5639 }
5640
5641 for_each_set_bit(j, &status, 32) {
5642 tx = (j >= 16 ? true : false);
5643 port_id = (tx ? j - 16 : j);
5644 val = wcd9xxx_interface_reg_read(codec->control_data,
5645 TAIKO_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
5646 if (val & TAIKO_SLIM_IRQ_OVERFLOW)
5647 pr_err_ratelimited(
5648 "%s: overflow error on %s port %d, value %x\n",
5649 __func__, (tx ? "TX" : "RX"), port_id, val);
5650 if (val & TAIKO_SLIM_IRQ_UNDERFLOW)
5651 pr_err_ratelimited(
5652 "%s: underflow error on %s port %d, value %x\n",
5653 __func__, (tx ? "TX" : "RX"), port_id, val);
5654 if (val & TAIKO_SLIM_IRQ_PORT_CLOSED) {
5655 /*
5656 * INT SOURCE register starts from RX to TX
5657 * but port number in the ch_mask is in opposite way
5658 */
5659 bit = (tx ? j - 16 : j + 16);
5660 pr_debug("%s: %s port %d closed value %x, bit %u\n",
5661 __func__, (tx ? "TX" : "RX"), port_id, val,
5662 bit);
5663 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
5664 pr_debug("%s: priv->dai[%d].ch_mask = 0x%lx\n",
5665 __func__, k, priv->dai[k].ch_mask);
5666 if (test_and_clear_bit(bit,
5667 &priv->dai[k].ch_mask)) {
5668 cleared = true;
5669 if (!priv->dai[k].ch_mask)
5670 wake_up(&priv->dai[k].dai_wait);
5671 /*
5672 * There are cases when multiple DAIs
5673 * might be using the same slimbus
5674 * channel. Hence don't break here.
5675 */
5676 }
5677 }
5678 WARN(!cleared,
5679 "Couldn't find slimbus %s port %d for closing\n",
5680 (tx ? "TX" : "RX"), port_id);
Kiran Kandic3b24402012-06-11 00:05:59 -07005681 }
5682 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005683 TAIKO_SLIM_PGD_PORT_INT_CLR_RX_0 +
5684 (j / 8),
5685 1 << (j % 8));
Joonwoo Parka8890262012-10-15 12:04:27 -07005686 }
Joonwoo Park9bbb4d12012-11-09 19:58:11 -08005687
Kiran Kandic3b24402012-06-11 00:05:59 -07005688 return IRQ_HANDLED;
5689}
5690
5691static int taiko_handle_pdata(struct taiko_priv *taiko)
5692{
5693 struct snd_soc_codec *codec = taiko->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07005694 struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
Kiran Kandic3b24402012-06-11 00:05:59 -07005695 int k1, k2, k3, rc = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07005696 u8 leg_mode, txfe_bypass, txfe_buff, flag;
Kiran Kandic3b24402012-06-11 00:05:59 -07005697 u8 i = 0, j = 0;
5698 u8 val_txfe = 0, value = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005699 u8 dmic_sample_rate_value = 0;
5700 u8 dmic_b1_ctl_value = 0, dmic_b2_ctl_value = 0;
5701 u8 anc_ctl_value = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07005702
5703 if (!pdata) {
Kiran Kandi725f8492012-08-06 13:45:16 -07005704 pr_err("%s: NULL pdata\n", __func__);
Kiran Kandic3b24402012-06-11 00:05:59 -07005705 rc = -ENODEV;
5706 goto done;
5707 }
5708
Kiran Kandi725f8492012-08-06 13:45:16 -07005709 leg_mode = pdata->amic_settings.legacy_mode;
5710 txfe_bypass = pdata->amic_settings.txfe_enable;
5711 txfe_buff = pdata->amic_settings.txfe_buff;
5712 flag = pdata->amic_settings.use_pdata;
5713
Kiran Kandic3b24402012-06-11 00:05:59 -07005714 /* Make sure settings are correct */
Joonwoo Parka8890262012-10-15 12:04:27 -07005715 if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
5716 (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5717 (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5718 (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
5719 (pdata->micbias.bias4_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005720 rc = -EINVAL;
5721 goto done;
5722 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005723 /* figure out k value */
Joonwoo Parka8890262012-10-15 12:04:27 -07005724 k1 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt1_mv);
5725 k2 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt2_mv);
5726 k3 = wcd9xxx_resmgr_get_k_val(&taiko->resmgr, pdata->micbias.cfilt3_mv);
Kiran Kandic3b24402012-06-11 00:05:59 -07005727
5728 if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
5729 rc = -EINVAL;
5730 goto done;
5731 }
Kiran Kandic3b24402012-06-11 00:05:59 -07005732 /* Set voltage level and always use LDO */
5733 snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x0C,
Joonwoo Parka8890262012-10-15 12:04:27 -07005734 (pdata->micbias.ldoh_v << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005735
Joonwoo Parka8890262012-10-15 12:04:27 -07005736 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_1_VAL, 0xFC, (k1 << 2));
5737 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
5738 snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
Kiran Kandic3b24402012-06-11 00:05:59 -07005739
5740 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005741 (pdata->micbias.bias1_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005742 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005743 (pdata->micbias.bias2_cfilt_sel << 5));
Kiran Kandic3b24402012-06-11 00:05:59 -07005744 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x60,
Joonwoo Parka8890262012-10-15 12:04:27 -07005745 (pdata->micbias.bias3_cfilt_sel << 5));
5746 snd_soc_update_bits(codec, taiko->resmgr.reg_addr->micb_4_ctl, 0x60,
Kiran Kandic3b24402012-06-11 00:05:59 -07005747 (pdata->micbias.bias4_cfilt_sel << 5));
5748
5749 for (i = 0; i < 6; j++, i += 2) {
5750 if (flag & (0x01 << i)) {
5751 value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
5752 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
5753 val_txfe = val_txfe |
5754 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
5755 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5756 0x10, value);
5757 snd_soc_update_bits(codec,
5758 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5759 0x30, val_txfe);
5760 }
5761 if (flag & (0x01 << (i + 1))) {
5762 value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
5763 val_txfe = (txfe_bypass &
5764 (0x01 << (i + 1))) ? 0x02 : 0x00;
5765 val_txfe |= (txfe_buff &
5766 (0x01 << (i + 1))) ? 0x01 : 0x00;
5767 snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
5768 0x01, value);
5769 snd_soc_update_bits(codec,
5770 TAIKO_A_TX_1_2_TEST_EN + j * 10,
5771 0x03, val_txfe);
5772 }
5773 }
5774 if (flag & 0x40) {
5775 value = (leg_mode & 0x40) ? 0x10 : 0x00;
5776 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
5777 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
5778 snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN,
5779 0x13, value);
5780 }
5781
5782 if (pdata->ocp.use_pdata) {
5783 /* not defined in CODEC specification */
5784 if (pdata->ocp.hph_ocp_limit == 1 ||
5785 pdata->ocp.hph_ocp_limit == 5) {
5786 rc = -EINVAL;
5787 goto done;
5788 }
5789 snd_soc_update_bits(codec, TAIKO_A_RX_COM_OCP_CTL,
5790 0x0F, pdata->ocp.num_attempts);
5791 snd_soc_write(codec, TAIKO_A_RX_COM_OCP_COUNT,
5792 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
5793 snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL,
5794 0xE0, (pdata->ocp.hph_ocp_limit << 5));
5795 }
5796
5797 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
Joonwoo Park448a8fc2013-04-10 15:25:58 -07005798 if (pdata->regulator[i].name &&
5799 !strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
Kiran Kandic3b24402012-06-11 00:05:59 -07005800 if (pdata->regulator[i].min_uV == 1800000 &&
5801 pdata->regulator[i].max_uV == 1800000) {
5802 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5803 0x1C);
5804 } else if (pdata->regulator[i].min_uV == 2200000 &&
5805 pdata->regulator[i].max_uV == 2200000) {
5806 snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
5807 0x1E);
5808 } else {
5809 pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
5810 "min %d, max %d\n", __func__,
5811 pdata->regulator[i].min_uV,
5812 pdata->regulator[i].max_uV);
5813 rc = -EINVAL;
5814 }
5815 break;
5816 }
5817 }
Kiran Kandi4c56c592012-07-25 11:04:55 -07005818
Joonwoo Park1848c762012-10-18 13:16:01 -07005819 /* Set micbias capless mode with tail current */
5820 value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
5821 0x00 : 0x16);
5822 snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x1E, value);
5823 value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
5824 0x00 : 0x16);
5825 snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x1E, value);
5826 value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
5827 0x00 : 0x16);
5828 snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x1E, value);
5829 value = (pdata->micbias.bias4_cap_mode == MICBIAS_EXT_BYP_CAP ?
5830 0x00 : 0x16);
5831 snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
5832
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005833 /* Set the DMIC sample rate */
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07005834 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ) {
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005835 switch (pdata->dmic_sample_rate) {
Damir Didjusto5f553e92013-10-02 14:54:31 -07005836 case WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ:
5837 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
5838 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
5839 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
5840 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005841 break;
Damir Didjusto5f553e92013-10-02 14:54:31 -07005842 case WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ:
5843 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
5844 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
5845 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
5846 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005847 break;
Damir Didjusto5f553e92013-10-02 14:54:31 -07005848 case WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ:
5849 case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
5850 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
5851 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
5852 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
5853 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005854 break;
5855 default:
5856 pr_err("%s Invalid sample rate %d for mclk %d\n",
5857 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5858 rc = -EINVAL;
5859 goto done;
5860 break;
5861 }
5862 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
5863 switch (pdata->dmic_sample_rate) {
Damir Didjusto5f553e92013-10-02 14:54:31 -07005864 case WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ:
5865 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
5866 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
5867 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
5868 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005869 break;
Damir Didjusto5f553e92013-10-02 14:54:31 -07005870 case WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ:
5871 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
5872 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
5873 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
5874 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005875 break;
Damir Didjusto5f553e92013-10-02 14:54:31 -07005876 case WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ:
5877 case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
5878 dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
5879 dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
5880 dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
5881 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07005882 break;
5883 default:
5884 pr_err("%s Invalid sample rate %d for mclk %d\n",
5885 __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
5886 rc = -EINVAL;
5887 goto done;
5888 break;
5889 }
5890 } else {
5891 pr_err("%s MCLK is not set!\n", __func__);
5892 rc = -EINVAL;
5893 goto done;
5894 }
5895
5896 snd_soc_update_bits(codec, TAIKO_A_CDC_TX1_DMIC_CTL,
5897 0x7, dmic_sample_rate_value);
5898 snd_soc_update_bits(codec, TAIKO_A_CDC_TX2_DMIC_CTL,
5899 0x7, dmic_sample_rate_value);
5900 snd_soc_update_bits(codec, TAIKO_A_CDC_TX3_DMIC_CTL,
5901 0x7, dmic_sample_rate_value);
5902 snd_soc_update_bits(codec, TAIKO_A_CDC_TX4_DMIC_CTL,
5903 0x7, dmic_sample_rate_value);
5904 snd_soc_update_bits(codec, TAIKO_A_CDC_TX5_DMIC_CTL,
5905 0x7, dmic_sample_rate_value);
5906 snd_soc_update_bits(codec, TAIKO_A_CDC_TX6_DMIC_CTL,
5907 0x7, dmic_sample_rate_value);
5908 snd_soc_update_bits(codec, TAIKO_A_CDC_TX7_DMIC_CTL,
5909 0x7, dmic_sample_rate_value);
5910 snd_soc_update_bits(codec, TAIKO_A_CDC_TX8_DMIC_CTL,
5911 0x7, dmic_sample_rate_value);
5912 snd_soc_update_bits(codec, TAIKO_A_CDC_TX9_DMIC_CTL,
5913 0x7, dmic_sample_rate_value);
5914 snd_soc_update_bits(codec, TAIKO_A_CDC_TX10_DMIC_CTL,
5915 0x7, dmic_sample_rate_value);
5916 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B1_CTL,
5917 0xEE, dmic_b1_ctl_value);
5918 snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B2_CTL,
5919 0xE, dmic_b2_ctl_value);
5920 snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
5921 0x1, anc_ctl_value);
5922
Kiran Kandic3b24402012-06-11 00:05:59 -07005923done:
5924 return rc;
5925}
5926
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005927static const struct wcd9xxx_reg_mask_val taiko_reg_defaults[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07005928
Kiran Kandi4c56c592012-07-25 11:04:55 -07005929 /* set MCLk to 9.6 */
Gopikrishnaiah Anandana8aec1f2013-01-23 14:26:27 -05005930 TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x02),
Kiran Kandi4c56c592012-07-25 11:04:55 -07005931 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_POWER_CTL, 0x03),
Kiran Kandic3b24402012-06-11 00:05:59 -07005932
Kiran Kandi4c56c592012-07-25 11:04:55 -07005933 /* EAR PA deafults */
5934 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
Kiran Kandic3b24402012-06-11 00:05:59 -07005935
Kiran Kandi4c56c592012-07-25 11:04:55 -07005936 /* RX deafults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005937 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
5938 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
5939 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
5940 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B5_CTL, 0x78),
5941 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B5_CTL, 0x78),
5942 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
5943 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
5944
Kiran Kandi4c56c592012-07-25 11:04:55 -07005945 /* RX1 and RX2 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005946 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
5947 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
5948
Kiran Kandi4c56c592012-07-25 11:04:55 -07005949 /* RX3 to RX7 defaults */
Kiran Kandic3b24402012-06-11 00:05:59 -07005950 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
5951 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
5952 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
5953 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
5954 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
Joonwoo Park1d05bb92013-03-07 16:55:06 -08005955
5956 /* MAD registers */
5957 TAIKO_REG_VAL(TAIKO_A_MAD_ANA_CTRL, 0xF1),
5958 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_1, 0x00),
5959 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_2, 0x00),
5960 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_1, 0x00),
5961 /* Set SAMPLE_TX_EN bit */
5962 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03),
5963 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_3, 0x00),
5964 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_4, 0x00),
5965 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_5, 0x00),
5966 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_6, 0x00),
5967 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_7, 0x00),
5968 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_8, 0x00),
5969 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR, 0x00),
5970 TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL, 0x40),
5971 TAIKO_REG_VAL(TAIKO_A_CDC_DEBUG_B7_CTL, 0x00),
5972 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL, 0x00),
5973 TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_CTL, 0x00),
5974 TAIKO_REG_VAL(TAIKO_A_CDC_CONN_MAD, 0x01),
Bhalchandra Gajareafdb1b12013-06-10 13:45:28 -07005975
5976 /* Set HPH Path to low power mode */
5977 TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x55),
Joonwoo Park58d4a162013-07-23 16:19:37 -07005978
5979 /* BUCK default */
5980 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
5981 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
Kiran Kandic3b24402012-06-11 00:05:59 -07005982};
5983
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005984static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005985 /*
5986 * The following only need to be written for Taiko 1.0 parts.
5987 * Taiko 2.0 will have appropriate defaults for these registers.
5988 */
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005989
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005990 /* Required defaults for class H operation */
5991 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
5992 TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005993 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08005994
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005995 /* Choose max non-overlap time for NCP */
5996 TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
5997 /* Use 25mV/50mV for deltap/m to reduce ripple */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08005998 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07005999 /*
6000 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
6001 * Note that the other bits of this register will be changed during
6002 * Rx PA bring up.
6003 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006004 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006005 /*Reduce EAR DAC bias to 70% */
6006 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
6007 /* Reduce LINE DAC bias to 70% */
6008 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07006009
6010 /*
6011 * There is a diode to pull down the micbias while doing
6012 * insertion detection. This diode can cause leakage.
6013 * Set bit 0 to 1 to prevent leakage.
6014 * Setting this bit of micbias 2 prevents leakage for all other micbias.
6015 */
6016 TAIKO_REG_VAL(TAIKO_A_MICB_2_MBHC, 0x41),
Joonwoo Park3c7bca62012-10-31 12:44:23 -07006017
6018 /* Disable TX7 internal biasing path which can cause leakage */
6019 TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
Joonwoo Park03604052012-11-06 18:40:25 -08006020 /* Enable MICB 4 VDDIO switch to prevent leakage */
6021 TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006022
6023 /* Close leakage on the spkdrv */
6024 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_DBG_PWRSTG, 0x24),
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006025};
6026
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006027/*
6028 * Don't update TAIKO_A_CHIP_CTL, TAIKO_A_BUCK_CTRL_CCL_1 and
6029 * TAIKO_A_RX_EAR_CMBUFF as those are updated in taiko_reg_defaults
6030 */
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006031static const struct wcd9xxx_reg_mask_val taiko_2_0_reg_defaults[] = {
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006032 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_GAIN, 0x2),
6033 TAIKO_REG_VAL(TAIKO_A_CDC_TX_2_GAIN, 0x2),
6034 TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_2_ADC_IB, 0x44),
6035 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_GAIN, 0x2),
6036 TAIKO_REG_VAL(TAIKO_A_CDC_TX_4_GAIN, 0x2),
6037 TAIKO_REG_VAL(TAIKO_A_CDC_TX_3_4_ADC_IB, 0x44),
6038 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_GAIN, 0x2),
6039 TAIKO_REG_VAL(TAIKO_A_CDC_TX_6_GAIN, 0x2),
6040 TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006041 TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
6042 TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
Joonwoo Parkd535b8a2013-08-01 18:44:56 -07006043 TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x51),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006044 TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
6045 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006046 TAIKO_REG_VAL(TAIKO_A_RX_HPH_OCP_CTL, 0x69),
6047 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_CTL, 0xDA),
6048 TAIKO_REG_VAL(TAIKO_A_RX_HPH_CNP_WG_TIME, 0x15),
6049 TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
6050 TAIKO_REG_VAL(TAIKO_A_RX_EAR_CNP, 0xC0),
6051 TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
6052 TAIKO_REG_VAL(TAIKO_A_RX_LINE_1_TEST, 0x2),
6053 TAIKO_REG_VAL(TAIKO_A_RX_LINE_2_TEST, 0x2),
6054 TAIKO_REG_VAL(TAIKO_A_RX_LINE_3_TEST, 0x2),
6055 TAIKO_REG_VAL(TAIKO_A_RX_LINE_4_TEST, 0x2),
6056 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_OCP_CTL, 0x97),
6057 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_CLIP_DET, 0x1),
6058 TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_IEC, 0x0),
6059 TAIKO_REG_VAL(TAIKO_A_CDC_TX1_MUX_CTL, 0x48),
6060 TAIKO_REG_VAL(TAIKO_A_CDC_TX2_MUX_CTL, 0x48),
6061 TAIKO_REG_VAL(TAIKO_A_CDC_TX3_MUX_CTL, 0x48),
6062 TAIKO_REG_VAL(TAIKO_A_CDC_TX4_MUX_CTL, 0x48),
6063 TAIKO_REG_VAL(TAIKO_A_CDC_TX5_MUX_CTL, 0x48),
6064 TAIKO_REG_VAL(TAIKO_A_CDC_TX6_MUX_CTL, 0x48),
6065 TAIKO_REG_VAL(TAIKO_A_CDC_TX7_MUX_CTL, 0x48),
6066 TAIKO_REG_VAL(TAIKO_A_CDC_TX8_MUX_CTL, 0x48),
6067 TAIKO_REG_VAL(TAIKO_A_CDC_TX9_MUX_CTL, 0x48),
6068 TAIKO_REG_VAL(TAIKO_A_CDC_TX10_MUX_CTL, 0x48),
6069 TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B4_CTL, 0x8),
Joonwoo Parkdbbdac02013-03-21 19:24:31 -07006070 TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B4_CTL, 0x8),
6071 TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B4_CTL, 0x8),
6072 TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B4_CTL, 0x8),
6073 TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B4_CTL, 0x8),
6074 TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B4_CTL, 0x8),
6075 TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B4_CTL, 0x8),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006076 TAIKO_REG_VAL(TAIKO_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
6077 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B1_CTL, 0x0),
6078 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B2_CTL, 0x0),
6079 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B3_CTL, 0x0),
6080 TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B4_CTL, 0x0),
6081 TAIKO_REG_VAL(TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
6082 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B4_CTL, 0x37),
6083 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
Joonwoo Park58d4a162013-07-23 16:19:37 -07006084 TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006085};
6086
Kiran Kandic3b24402012-06-11 00:05:59 -07006087static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
6088{
6089 u32 i;
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006090 struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
Kiran Kandic3b24402012-06-11 00:05:59 -07006091
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006092 for (i = 0; i < ARRAY_SIZE(taiko_reg_defaults); i++)
6093 snd_soc_write(codec, taiko_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006094 taiko_reg_defaults[i].val);
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006095
6096 if (TAIKO_IS_1_0(taiko_core->version)) {
6097 for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
6098 snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006099 taiko_1_0_reg_defaults[i].val);
6100 if (spkr_drv_wrnd == 1)
6101 snd_soc_write(codec, TAIKO_A_SPKR_DRV_EN, 0xEF);
6102 } else {
6103 for (i = 0; i < ARRAY_SIZE(taiko_2_0_reg_defaults); i++)
6104 snd_soc_write(codec, taiko_2_0_reg_defaults[i].reg,
6105 taiko_2_0_reg_defaults[i].val);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006106 spkr_drv_wrnd = -1;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006107 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006108}
6109
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006110static const struct wcd9xxx_reg_mask_val taiko_codec_reg_init_val[] = {
Kiran Kandic3b24402012-06-11 00:05:59 -07006111 /* Initialize current threshold to 350MA
6112 * number of wait and run cycles to 4096
6113 */
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006114 {TAIKO_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
Kiran Kandic3b24402012-06-11 00:05:59 -07006115 {TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
Patrick Lai92833bf2012-12-01 10:31:35 -08006116 {TAIKO_A_RX_HPH_L_TEST, 0x01, 0x01},
6117 {TAIKO_A_RX_HPH_R_TEST, 0x01, 0x01},
Kiran Kandic3b24402012-06-11 00:05:59 -07006118
Kiran Kandic3b24402012-06-11 00:05:59 -07006119 /* Initialize gain registers to use register gain */
Kiran Kandi4c56c592012-07-25 11:04:55 -07006120 {TAIKO_A_RX_HPH_L_GAIN, 0x20, 0x20},
6121 {TAIKO_A_RX_HPH_R_GAIN, 0x20, 0x20},
6122 {TAIKO_A_RX_LINE_1_GAIN, 0x20, 0x20},
6123 {TAIKO_A_RX_LINE_2_GAIN, 0x20, 0x20},
6124 {TAIKO_A_RX_LINE_3_GAIN, 0x20, 0x20},
6125 {TAIKO_A_RX_LINE_4_GAIN, 0x20, 0x20},
Joonwoo Parkc7731432012-10-17 12:41:44 -07006126 {TAIKO_A_SPKR_DRV_GAIN, 0x04, 0x04},
Kiran Kandic3b24402012-06-11 00:05:59 -07006127
Kiran Kandic3b24402012-06-11 00:05:59 -07006128 /* Use 16 bit sample size for TX1 to TX6 */
6129 {TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
6130 {TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
6131 {TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
6132 {TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
6133 {TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
6134 {TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
6135
6136 /* Use 16 bit sample size for TX7 to TX10 */
6137 {TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
6138 {TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
6139 {TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
6140 {TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
6141
Kiran Kandic3b24402012-06-11 00:05:59 -07006142 /*enable HPF filter for TX paths */
6143 {TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
6144 {TAIKO_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
6145 {TAIKO_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
6146 {TAIKO_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
6147 {TAIKO_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
6148 {TAIKO_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
6149 {TAIKO_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
6150 {TAIKO_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
6151 {TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
6152 {TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
6153
Joonwoo Parkc7731432012-10-17 12:41:44 -07006154 /* Compander zone selection */
6155 {TAIKO_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
6156 {TAIKO_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
6157 {TAIKO_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
6158 {TAIKO_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
6159 {TAIKO_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
6160 {TAIKO_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
Bhalchandra Gajareef7810e2013-03-29 16:50:37 -07006161
6162 /*
6163 * Setup wavegen timer to 20msec and disable chopper
6164 * as default. This corresponds to Compander OFF
6165 */
6166 {TAIKO_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
6167 {TAIKO_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x58},
6168 {TAIKO_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
6169 {TAIKO_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
Bhalchandra Gajare9581aed2013-03-29 17:06:10 -07006170
6171 /* Choose max non-overlap time for NCP */
6172 {TAIKO_A_NCP_CLK, 0xFF, 0xFC},
6173
6174 /* Program the 0.85 volt VBG_REFERENCE */
6175 {TAIKO_A_BIAS_CURR_CTL_2, 0xFF, 0x04},
Kiran Kandiddbeaa32013-10-06 14:40:11 -07006176
6177 /* set MAD input MIC to DMIC1 */
6178 {TAIKO_A_CDC_CONN_MAD, 0x0F, 0x08},
Kiran Kandic3b24402012-06-11 00:05:59 -07006179};
6180
6181static void taiko_codec_init_reg(struct snd_soc_codec *codec)
6182{
6183 u32 i;
6184
6185 for (i = 0; i < ARRAY_SIZE(taiko_codec_reg_init_val); i++)
6186 snd_soc_update_bits(codec, taiko_codec_reg_init_val[i].reg,
6187 taiko_codec_reg_init_val[i].mask,
6188 taiko_codec_reg_init_val[i].val);
6189}
6190
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006191static void taiko_slim_interface_init_reg(struct snd_soc_codec *codec)
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006192{
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006193 int i;
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006194
6195 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
6196 wcd9xxx_interface_reg_write(codec->control_data,
Joonwoo Parka8890262012-10-15 12:04:27 -07006197 TAIKO_SLIM_PGD_PORT_INT_EN0 + i,
6198 0xFF);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006199}
6200
6201static int taiko_setup_irqs(struct taiko_priv *taiko)
6202{
6203 int ret = 0;
6204 struct snd_soc_codec *codec = taiko->codec;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006205 struct wcd9xxx *wcd9xxx = codec->control_data;
6206 struct wcd9xxx_core_resource *core_res =
6207 &wcd9xxx->core_res;
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006208
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006209 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006210 taiko_slimbus_irq, "SLIMBUS Slave", taiko);
6211 if (ret)
6212 pr_err("%s: Failed to request irq %d\n", __func__,
6213 WCD9XXX_IRQ_SLIMBUS);
6214 else
6215 taiko_slim_interface_init_reg(codec);
6216
Joonwoo Park7680b9f2012-07-13 11:36:48 -07006217 return ret;
6218}
6219
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006220static void taiko_cleanup_irqs(struct taiko_priv *taiko)
6221{
6222 struct snd_soc_codec *codec = taiko->codec;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006223 struct wcd9xxx *wcd9xxx = codec->control_data;
6224 struct wcd9xxx_core_resource *core_res =
6225 &wcd9xxx->core_res;
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006226
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006227 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, taiko);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006228}
6229
Joonwoo Parka8890262012-10-15 12:04:27 -07006230int taiko_hs_detect(struct snd_soc_codec *codec,
6231 struct wcd9xxx_mbhc_config *mbhc_cfg)
6232{
Joonwoo Park88bfa842013-04-15 16:59:21 -07006233 int rc;
Joonwoo Parka8890262012-10-15 12:04:27 -07006234 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Park88bfa842013-04-15 16:59:21 -07006235 rc = wcd9xxx_mbhc_start(&taiko->mbhc, mbhc_cfg);
6236 if (!rc)
6237 taiko->mbhc_started = true;
6238 return rc;
Joonwoo Parka8890262012-10-15 12:04:27 -07006239}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006240EXPORT_SYMBOL(taiko_hs_detect);
Joonwoo Parka8890262012-10-15 12:04:27 -07006241
Joonwoo Parke7d724e2013-08-19 15:51:01 -07006242void taiko_hs_detect_exit(struct snd_soc_codec *codec)
6243{
6244 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
6245 wcd9xxx_mbhc_stop(&taiko->mbhc);
6246 taiko->mbhc_started = false;
6247}
6248EXPORT_SYMBOL(taiko_hs_detect_exit);
6249
Kiran Kandia1bed422013-05-28 18:29:12 -07006250void taiko_event_register(
6251 int (*machine_event_cb)(struct snd_soc_codec *codec,
6252 enum wcd9xxx_codec_event),
6253 struct snd_soc_codec *codec)
6254{
6255 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
6256 taiko->machine_codec_event_cb = machine_event_cb;
6257}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006258EXPORT_SYMBOL(taiko_event_register);
Kiran Kandia1bed422013-05-28 18:29:12 -07006259
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006260static void taiko_init_slim_slave_cfg(struct snd_soc_codec *codec)
6261{
6262 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
6263 struct afe_param_cdc_slimbus_slave_cfg *cfg;
6264 struct wcd9xxx *wcd9xxx = codec->control_data;
6265 uint64_t eaddr = 0;
6266
6267 cfg = &priv->slimbus_slave_cfg;
6268 cfg->minor_version = 1;
6269 cfg->tx_slave_port_offset = 0;
6270 cfg->rx_slave_port_offset = 16;
6271
6272 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
6273 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
6274 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
6275 cfg->device_enum_addr_msw = eaddr >> 32;
6276
6277 pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
6278}
6279
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006280static int taiko_device_down(struct wcd9xxx *wcd9xxx)
6281{
6282 struct snd_soc_codec *codec;
6283
6284 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
6285 snd_soc_card_change_online_state(codec->card, 0);
6286
6287 return 0;
6288}
6289
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -07006290static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
6291 struct list_head *lh)
6292{
6293 int i;
6294 struct snd_soc_codec *codec = mbhc->codec;
6295
6296 const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
6297 {WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
6298 {WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
6299 {WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
6300 {WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
6301 {WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
6302 {WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
6303 {WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
6304 {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
6305 {WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
6306 {WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
6307 {WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
6308 {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
6309 {WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
6310 {WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
6311 {WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
6312 {WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
6313 {WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
6314 {WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
6315 {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
6316 {WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
6317 {WCD9XXX_A_NCP_EN, 0xff, 0xFF},
6318 {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
6319 {WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
6320 {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
6321 {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
6322 };
6323
6324 for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
6325 wcd9xxx_soc_update_bits_push(codec, lh,
6326 reg_set_paon[i].reg,
6327 reg_set_paon[i].mask,
6328 reg_set_paon[i].val, 0);
6329 pr_debug("%s: PAs are prepared\n", __func__);
6330
6331 return 0;
6332}
6333
6334static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
6335{
6336 struct snd_soc_codec *codec = mbhc->codec;
6337 const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
6338 TAIKO_WG_TIME_FACTOR_US;
6339
6340 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
6341 enable ? 0x30 : 0x0);
6342 /* Wait for wave gen time to avoid pop noise */
6343 usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
6344 pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
6345 enable ? "enabled" : "disabled", wg_time);
6346 return 0;
6347}
6348
6349static int taiko_setup_zdet(struct wcd9xxx_mbhc *mbhc,
6350 enum mbhc_impedance_detect_stages stage)
6351{
6352 int ret = 0;
6353 struct snd_soc_codec *codec = mbhc->codec;
6354 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
6355 const int ramp_wait_us = 18 * 1000;
6356
6357#define __wr(reg, mask, value) \
6358 do { \
6359 ret = wcd9xxx_soc_update_bits_push(codec, \
6360 &taiko->reg_save_restore, \
6361 reg, mask, value, 0); \
6362 if (ret < 0) \
6363 return ret; \
6364 } while (0)
6365
6366 switch (stage) {
6367
6368 case PRE_MEAS:
6369 INIT_LIST_HEAD(&taiko->reg_save_restore);
6370 wcd9xxx_prepare_static_pa(mbhc, &taiko->reg_save_restore);
6371 wcd9xxx_enable_static_pa(mbhc, true);
6372
6373 /*
6374 * save old value of registers and write the new value to
6375 * restore old value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL
6376 * registers don't need to be restored as those are solely used
6377 * by impedance detection.
6378 */
6379 /* Phase 1 */
6380 /* Reset the PA Ramp */
6381 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
6382 /*
6383 * Connect the PA Ramp to PA chain and release reset with
6384 * keep it connected.
6385 */
6386 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
6387 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
6388 /*
6389 * Program the PA Ramp to FS_48K, L shift 1 and sample
6390 * num to 24
6391 */
6392 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
6393 0x3 << 4 | 0x6);
6394 /* 0x56 for 10mv. 0xC0 is for 50mv */
6395 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
6396 /* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
6397 __wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
6398 __wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
6399 __wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
6400 __wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
6401 /* Change NSA and NAVG */
6402 __wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
6403 __wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
6404 /* Reset MBHC and set it up for STA */
6405 __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
6406 __wr(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
6407 __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
6408
6409 /* Set HPH_MBHC for zdet */
6410 __wr(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
6411 break;
6412 case POST_MEAS:
6413 /* Phase 2 */
6414 /* Start the PA ramp on HPH L and R */
6415 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
6416 /* Ramp generator takes ~17ms */
6417 usleep_range(ramp_wait_us,
6418 ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
6419
6420 /* Disable Ical */
6421 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
6422 /* Ramp generator takes ~17ms */
6423 usleep_range(ramp_wait_us,
6424 ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
6425 break;
6426 case PA_DISABLE:
6427 /* Ramp HPH L & R back to Zero */
6428 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
6429 /* Ramp generator takes ~17ms */
6430 usleep_range(ramp_wait_us,
6431 ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
6432 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
6433
6434 /* Clean up starts */
6435 /* Turn off PA ramp generator */
6436 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
6437 wcd9xxx_enable_static_pa(mbhc, false);
6438 wcd9xxx_restore_registers(codec, &taiko->reg_save_restore);
6439 break;
6440 }
6441#undef __wr
6442
6443 return ret;
6444}
6445
6446static void taiko_compute_impedance(s16 *l, s16 *r, uint32_t *zl, uint32_t *zr)
6447{
6448
6449 int64_t rl, rr = 0; /* milliohm */
6450 const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
6451 const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
6452 const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
6453 const int rref = 11333; /* not scaled up */
6454 const int shift = 16;
6455
6456 rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
6457 rl = rl * rref * alphal;
6458 rl = rl >> shift;
6459 rl = rl * beta;
6460 rl = rl >> shift;
6461 *zl = rl;
6462
6463 rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
6464 rr = rr * rref * alphar;
6465 rr = rr >> shift;
6466 rr = rr * beta;
6467 rr = rr >> shift;
6468 *zr = rr;
6469}
6470
6471static enum wcd9xxx_cdc_type taiko_get_cdc_type(void)
6472{
6473 return WCD9XXX_CDC_TYPE_TAIKO;
6474}
6475
6476static const struct wcd9xxx_mbhc_cb mbhc_cb = {
6477 .get_cdc_type = taiko_get_cdc_type,
6478 .setup_zdet = taiko_setup_zdet,
6479 .compute_impedance = taiko_compute_impedance,
6480};
6481
Bhalchandra Gajare16748932013-10-01 18:16:05 -07006482static const struct wcd9xxx_mbhc_intr cdc_intr_ids = {
6483 .poll_plug_rem = WCD9XXX_IRQ_MBHC_REMOVAL,
6484 .shortavg_complete = WCD9XXX_IRQ_MBHC_SHORT_TERM,
6485 .potential_button_press = WCD9XXX_IRQ_MBHC_PRESS,
6486 .button_release = WCD9XXX_IRQ_MBHC_RELEASE,
6487 .dce_est_complete = WCD9XXX_IRQ_MBHC_POTENTIAL,
6488 .insertion = WCD9XXX_IRQ_MBHC_INSERTION,
6489 .hph_left_ocp = WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
6490 .hph_right_ocp = WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
6491 .hs_jack_switch = WCD9320_IRQ_MBHC_JACK_SWITCH,
6492};
6493
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006494static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
6495{
6496 int ret = 0;
6497 struct snd_soc_codec *codec;
6498 struct taiko_priv *taiko;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006499 int rco_clk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006500
6501 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
6502 taiko = snd_soc_codec_get_drvdata(codec);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006503
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006504 snd_soc_card_change_online_state(codec->card, 1);
6505
6506 mutex_lock(&codec->mutex);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006507 if (codec->reg_def_copy) {
6508 pr_debug("%s: Update ASOC cache", __func__);
6509 kfree(codec->reg_cache);
6510 codec->reg_cache = kmemdup(codec->reg_def_copy,
6511 codec->reg_size, GFP_KERNEL);
6512 }
6513
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006514 if (spkr_drv_wrnd == 1)
6515 snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006516
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006517 taiko_update_reg_defaults(codec);
6518 taiko_codec_init_reg(codec);
6519 ret = taiko_handle_pdata(taiko);
6520 if (IS_ERR_VALUE(ret))
6521 pr_err("%s: bad pdata\n", __func__);
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08006522
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006523 taiko_init_slim_slave_cfg(codec);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006524 taiko_slim_interface_init_reg(codec);
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006525
Joonwoo Park865bcf02013-07-15 14:05:32 -07006526 wcd9xxx_resmgr_post_ssr(&taiko->resmgr);
6527
Joonwoo Park88bfa842013-04-15 16:59:21 -07006528 if (taiko->mbhc_started) {
6529 wcd9xxx_mbhc_deinit(&taiko->mbhc);
6530 taiko->mbhc_started = false;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006531
6532 if (TAIKO_IS_1_0(wcd9xxx->version))
6533 rco_clk_rate = TAIKO_MCLK_CLK_12P288MHZ;
6534 else
6535 rco_clk_rate = TAIKO_MCLK_CLK_9P6MHZ;
6536
Joonwoo Park88bfa842013-04-15 16:59:21 -07006537 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
Joonwoo Parkccccba72013-04-26 11:19:46 -07006538 taiko_enable_mbhc_micbias,
Bhalchandra Gajare16748932013-10-01 18:16:05 -07006539 &mbhc_cb, &cdc_intr_ids,
6540 rco_clk_rate, true);
Joonwoo Parke7d724e2013-08-19 15:51:01 -07006541 if (ret)
Joonwoo Park88bfa842013-04-15 16:59:21 -07006542 pr_err("%s: mbhc init failed %d\n", __func__, ret);
Joonwoo Parke7d724e2013-08-19 15:51:01 -07006543 else
6544 taiko_hs_detect(codec, taiko->mbhc.mbhc_cfg);
Joonwoo Park88bfa842013-04-15 16:59:21 -07006545 }
Kiran Kandia1bed422013-05-28 18:29:12 -07006546 taiko->machine_codec_event_cb(codec, WCD9XXX_CODEC_EVENT_CODEC_UP);
6547
Joonwoo Parkc98049a2013-07-30 16:43:34 -07006548 taiko_cleanup_irqs(taiko);
6549 ret = taiko_setup_irqs(taiko);
6550 if (ret)
6551 pr_err("%s: Failed to setup irq: %d\n", __func__, ret);
6552
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006553 mutex_unlock(&codec->mutex);
6554 return ret;
6555}
6556
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006557void *taiko_get_afe_config(struct snd_soc_codec *codec,
6558 enum afe_config_type config_type)
6559{
6560 struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -04006561 struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006562
6563 switch (config_type) {
6564 case AFE_SLIMBUS_SLAVE_CONFIG:
6565 return &priv->slimbus_slave_cfg;
6566 case AFE_CDC_REGISTERS_CONFIG:
Damir Didjustodcfdff82013-03-21 23:26:41 -07006567 return &taiko_audio_reg_cfg;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006568 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
6569 return &taiko_slimbus_slave_port_cfg;
Damir Didjustodcfdff82013-03-21 23:26:41 -07006570 case AFE_AANC_VERSION:
6571 return &taiko_cdc_aanc_version;
Gopikrishnaiah Anandaneb51dd72013-04-09 11:39:55 -04006572 case AFE_CLIP_BANK_SEL:
6573 if (!TAIKO_IS_1_0(taiko_core->version))
6574 return &clip_bank_sel;
6575 else
6576 return NULL;
6577 case AFE_CDC_CLIP_REGISTERS_CONFIG:
6578 if (!TAIKO_IS_1_0(taiko_core->version))
6579 return &taiko_clip_reg_cfg;
6580 else
6581 return NULL;
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006582 default:
6583 pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
6584 return NULL;
6585 }
6586}
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006587
Joonwoo Parka8890262012-10-15 12:04:27 -07006588static struct wcd9xxx_reg_address taiko_reg_address = {
6589 .micb_4_mbhc = TAIKO_A_MICB_4_MBHC,
6590 .micb_4_int_rbias = TAIKO_A_MICB_4_INT_RBIAS,
6591 .micb_4_ctl = TAIKO_A_MICB_4_CTL,
6592};
6593
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006594static int wcd9xxx_ssr_register(struct wcd9xxx *control,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006595 int (*device_down_cb)(struct wcd9xxx *wcd9xxx),
6596 int (*device_up_cb)(struct wcd9xxx *wcd9xxx),
6597 void *priv)
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006598{
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006599 control->dev_down = device_down_cb;
6600 control->post_reset = device_up_cb;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006601 control->ssr_priv = priv;
6602 return 0;
6603}
6604
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006605static const struct snd_soc_dapm_widget taiko_1_dapm_widgets[] = {
6606 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
6607 taiko_codec_enable_adc,
6608 SND_SOC_DAPM_PRE_PMU |
6609 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6610 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
6611 taiko_codec_enable_adc,
6612 SND_SOC_DAPM_PRE_PMU |
6613 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6614 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_TX_3_4_EN, 7, 0,
6615 taiko_codec_enable_adc,
6616 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6617 SND_SOC_DAPM_POST_PMD),
6618 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_TX_3_4_EN, 3, 0,
6619 taiko_codec_enable_adc,
6620 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6621 SND_SOC_DAPM_POST_PMD),
6622 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_TX_5_6_EN, 7, 0,
6623 taiko_codec_enable_adc,
6624 SND_SOC_DAPM_POST_PMU),
6625 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_TX_5_6_EN, 3, 0,
6626 taiko_codec_enable_adc,
6627 SND_SOC_DAPM_POST_PMU),
6628};
6629
6630static const struct snd_soc_dapm_widget taiko_2_dapm_widgets[] = {
6631 SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_CDC_TX_1_GAIN, 7, 0,
6632 taiko_codec_enable_adc,
6633 SND_SOC_DAPM_PRE_PMU |
6634 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6635 SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_CDC_TX_2_GAIN, 7, 0,
6636 taiko_codec_enable_adc,
6637 SND_SOC_DAPM_PRE_PMU |
6638 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6639 SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_CDC_TX_3_GAIN, 7, 0,
6640 taiko_codec_enable_adc,
6641 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6642 SND_SOC_DAPM_POST_PMD),
6643 SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_CDC_TX_4_GAIN, 7, 0,
6644 taiko_codec_enable_adc,
6645 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6646 SND_SOC_DAPM_POST_PMD),
6647 SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_CDC_TX_5_GAIN, 7, 0,
6648 taiko_codec_enable_adc,
6649 SND_SOC_DAPM_POST_PMU),
6650 SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_CDC_TX_6_GAIN, 7, 0,
6651 taiko_codec_enable_adc,
6652 SND_SOC_DAPM_POST_PMU),
6653};
6654
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006655static struct regulator *taiko_codec_find_regulator(struct snd_soc_codec *codec,
6656 const char *name)
6657{
6658 int i;
6659 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
6660
6661 for (i = 0; i < core->num_of_supplies; i++) {
6662 if (core->supplies[i].supply &&
6663 !strcmp(core->supplies[i].supply, name))
6664 return core->supplies[i].consumer;
6665 }
6666
6667 return NULL;
6668}
6669
Kiran Kandic3b24402012-06-11 00:05:59 -07006670static int taiko_codec_probe(struct snd_soc_codec *codec)
6671{
6672 struct wcd9xxx *control;
6673 struct taiko_priv *taiko;
Joonwoo Parka8890262012-10-15 12:04:27 -07006674 struct wcd9xxx_pdata *pdata;
6675 struct wcd9xxx *wcd9xxx;
Kiran Kandic3b24402012-06-11 00:05:59 -07006676 struct snd_soc_dapm_context *dapm = &codec->dapm;
6677 int ret = 0;
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006678 int i, rco_clk_rate;
Kuirong Wang906ac472012-07-09 12:54:44 -07006679 void *ptr = NULL;
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006680 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006681 struct wcd9xxx_core_resource *core_res;
Kiran Kandic3b24402012-06-11 00:05:59 -07006682
6683 codec->control_data = dev_get_drvdata(codec->dev->parent);
6684 control = codec->control_data;
6685
Joonwoo Park8ffa2812013-08-07 19:01:30 -07006686 wcd9xxx_ssr_register(control, taiko_device_down,
6687 taiko_post_reset_cb, (void *)codec);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08006688
Kiran Kandi4c56c592012-07-25 11:04:55 -07006689 dev_info(codec->dev, "%s()\n", __func__);
6690
Kiran Kandic3b24402012-06-11 00:05:59 -07006691 taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
6692 if (!taiko) {
6693 dev_err(codec->dev, "Failed to allocate private data\n");
6694 return -ENOMEM;
6695 }
6696 for (i = 0 ; i < NUM_DECIMATORS; i++) {
6697 tx_hpf_work[i].taiko = taiko;
6698 tx_hpf_work[i].decimator = i + 1;
6699 INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
6700 tx_hpf_corner_freq_callback);
6701 }
6702
Kiran Kandic3b24402012-06-11 00:05:59 -07006703 snd_soc_codec_set_drvdata(codec, taiko);
6704
Joonwoo Parka8890262012-10-15 12:04:27 -07006705 /* codec resmgr module init */
6706 wcd9xxx = codec->control_data;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006707 core_res = &wcd9xxx->core_res;
Joonwoo Parka8890262012-10-15 12:04:27 -07006708 pdata = dev_get_platdata(codec->dev->parent);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07006709 ret = wcd9xxx_resmgr_init(&taiko->resmgr, codec, core_res, pdata,
Bhalchandra Gajare9943aa62013-10-09 18:40:11 -07006710 &pdata->micbias, &taiko_reg_address,
6711 WCD9XXX_CDC_TYPE_TAIKO);
Joonwoo Parka8890262012-10-15 12:04:27 -07006712 if (ret) {
6713 pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006714 goto err_init;
Joonwoo Parka8890262012-10-15 12:04:27 -07006715 }
6716
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006717 taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
Bhalchandra Gajare7c739522013-06-20 15:31:02 -07006718 /* Taiko does not support dynamic switching of vdd_cp */
6719 taiko->clsh_d.is_dynamic_vdd_cp = false;
Joonwoo Parka08e0552013-03-05 18:28:23 -08006720 wcd9xxx_clsh_init(&taiko->clsh_d, &taiko->resmgr);
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -08006721
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006722 if (TAIKO_IS_1_0(core->version))
6723 rco_clk_rate = TAIKO_MCLK_CLK_12P288MHZ;
6724 else
6725 rco_clk_rate = TAIKO_MCLK_CLK_9P6MHZ;
6726
Joonwoo Parka8890262012-10-15 12:04:27 -07006727 /* init and start mbhc */
Simmi Pateriya0a44d842013-04-03 01:12:42 +05306728 ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
Joonwoo Parkccccba72013-04-26 11:19:46 -07006729 taiko_enable_mbhc_micbias,
Bhalchandra Gajare16748932013-10-01 18:16:05 -07006730 &mbhc_cb, &cdc_intr_ids,
6731 rco_clk_rate, true);
Joonwoo Parka8890262012-10-15 12:04:27 -07006732 if (ret) {
6733 pr_err("%s: mbhc init failed %d\n", __func__, ret);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006734 goto err_init;
Joonwoo Parka8890262012-10-15 12:04:27 -07006735 }
6736
Kiran Kandic3b24402012-06-11 00:05:59 -07006737 taiko->codec = codec;
Kiran Kandic3b24402012-06-11 00:05:59 -07006738 for (i = 0; i < COMPANDER_MAX; i++) {
6739 taiko->comp_enabled[i] = 0;
6740 taiko->comp_fs[i] = COMPANDER_FS_48KHZ;
6741 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006742 taiko->intf_type = wcd9xxx_get_intf_type();
6743 taiko->aux_pga_cnt = 0;
6744 taiko->aux_l_gain = 0x1F;
6745 taiko->aux_r_gain = 0x1F;
Joonwoo Parkccccba72013-04-26 11:19:46 -07006746 taiko->ldo_h_users = 0;
6747 taiko->micb_2_users = 0;
Kiran Kandic3b24402012-06-11 00:05:59 -07006748 taiko_update_reg_defaults(codec);
Venkat Sudhira50a3762012-11-26 12:12:15 -08006749 pr_debug("%s: MCLK Rate = %x\n", __func__, wcd9xxx->mclk_rate);
6750 if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006751 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x0);
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -07006752 else if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ)
Venkat Sudhir16d95e62013-02-04 16:57:33 -08006753 snd_soc_update_bits(codec, TAIKO_A_CHIP_CTL, 0x06, 0x2);
Kiran Kandic3b24402012-06-11 00:05:59 -07006754 taiko_codec_init_reg(codec);
6755 ret = taiko_handle_pdata(taiko);
6756 if (IS_ERR_VALUE(ret)) {
6757 pr_err("%s: bad pdata\n", __func__);
6758 goto err_pdata;
6759 }
6760
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006761 taiko->spkdrv_reg = taiko_codec_find_regulator(codec,
6762 WCD9XXX_VDD_SPKDRV_NAME);
6763
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006764 if (spkr_drv_wrnd > 0) {
Joonwoo Park533b3682013-06-13 11:41:21 -07006765 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006766 wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
6767 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07006768 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006769 }
6770
Kuirong Wang906ac472012-07-09 12:54:44 -07006771 ptr = kmalloc((sizeof(taiko_rx_chs) +
6772 sizeof(taiko_tx_chs)), GFP_KERNEL);
6773 if (!ptr) {
6774 pr_err("%s: no mem for slim chan ctl data\n", __func__);
6775 ret = -ENOMEM;
6776 goto err_nomem_slimch;
6777 }
6778
Kiran Kandic3b24402012-06-11 00:05:59 -07006779 if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
6780 snd_soc_dapm_new_controls(dapm, taiko_dapm_i2s_widgets,
6781 ARRAY_SIZE(taiko_dapm_i2s_widgets));
6782 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
6783 ARRAY_SIZE(audio_i2s_map));
Joonwoo Park559a5bf2013-02-15 14:46:36 -08006784 if (TAIKO_IS_1_0(core->version))
6785 snd_soc_dapm_add_routes(dapm, audio_i2s_map_1_0,
6786 ARRAY_SIZE(audio_i2s_map_1_0));
6787 else
6788 snd_soc_dapm_add_routes(dapm, audio_i2s_map_2_0,
6789 ARRAY_SIZE(audio_i2s_map_2_0));
Kuirong Wang906ac472012-07-09 12:54:44 -07006790 for (i = 0; i < ARRAY_SIZE(taiko_i2s_dai); i++)
6791 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6792 } else if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
6793 for (i = 0; i < NUM_CODEC_DAIS; i++) {
6794 INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
6795 init_waitqueue_head(&taiko->dai[i].dai_wait);
6796 }
Joonwoo Park1d05bb92013-03-07 16:55:06 -08006797 taiko_slimbus_slave_port_cfg.slave_dev_intfdev_la =
6798 control->slim_slave->laddr;
6799 taiko_slimbus_slave_port_cfg.slave_dev_pgd_la =
6800 control->slim->laddr;
6801 taiko_slimbus_slave_port_cfg.slave_port_mapping[0] =
6802 TAIKO_MAD_SLIMBUS_TX_PORT;
6803
6804 taiko_init_slim_slave_cfg(codec);
Kiran Kandic3b24402012-06-11 00:05:59 -07006805 }
6806
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006807 if (TAIKO_IS_1_0(control->version)) {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006808 snd_soc_dapm_new_controls(dapm, taiko_1_dapm_widgets,
6809 ARRAY_SIZE(taiko_1_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006810 snd_soc_add_codec_controls(codec,
6811 taiko_1_x_analog_gain_controls,
6812 ARRAY_SIZE(taiko_1_x_analog_gain_controls));
6813 } else {
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006814 snd_soc_dapm_new_controls(dapm, taiko_2_dapm_widgets,
6815 ARRAY_SIZE(taiko_2_dapm_widgets));
Kiran Kandiec0db5c2013-03-08 16:03:58 -08006816 snd_soc_add_codec_controls(codec,
6817 taiko_2_x_analog_gain_controls,
6818 ARRAY_SIZE(taiko_2_x_analog_gain_controls));
6819 }
Joonwoo Park2a9170a2013-03-04 17:05:57 -08006820
Joonwoo Parkb755e9e2013-05-28 13:14:05 -07006821 snd_soc_add_codec_controls(codec, impedance_detect_controls,
6822 ARRAY_SIZE(impedance_detect_controls));
6823
Kuirong Wang906ac472012-07-09 12:54:44 -07006824 control->num_rx_port = TAIKO_RX_MAX;
6825 control->rx_chs = ptr;
6826 memcpy(control->rx_chs, taiko_rx_chs, sizeof(taiko_rx_chs));
6827 control->num_tx_port = TAIKO_TX_MAX;
6828 control->tx_chs = ptr + sizeof(taiko_rx_chs);
6829 memcpy(control->tx_chs, taiko_tx_chs, sizeof(taiko_tx_chs));
6830
Kiran Kandic3b24402012-06-11 00:05:59 -07006831 snd_soc_dapm_sync(dapm);
6832
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006833 ret = taiko_setup_irqs(taiko);
6834 if (ret) {
6835 pr_err("%s: taiko irq setup failed %d\n", __func__, ret);
6836 goto err_irq;
6837 }
Kiran Kandic3b24402012-06-11 00:05:59 -07006838
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006839 atomic_set(&kp_taiko_priv, (unsigned long)taiko);
Damir Didjusto2cb06bd2013-01-30 23:14:55 -08006840 mutex_lock(&dapm->codec->mutex);
6841 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
6842 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
6843 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
6844 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
6845 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
6846 snd_soc_dapm_sync(dapm);
6847 mutex_unlock(&dapm->codec->mutex);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006848
Kiran Kandic3b24402012-06-11 00:05:59 -07006849 codec->ignore_pmdown_time = 1;
6850 return ret;
6851
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006852err_irq:
6853 taiko_cleanup_irqs(taiko);
Kiran Kandic3b24402012-06-11 00:05:59 -07006854err_pdata:
Kuirong Wang906ac472012-07-09 12:54:44 -07006855 kfree(ptr);
6856err_nomem_slimch:
Kiran Kandic3b24402012-06-11 00:05:59 -07006857 kfree(taiko);
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006858err_init:
Kiran Kandic3b24402012-06-11 00:05:59 -07006859 return ret;
6860}
6861static int taiko_codec_remove(struct snd_soc_codec *codec)
6862{
Kiran Kandic3b24402012-06-11 00:05:59 -07006863 struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
Joonwoo Parka8890262012-10-15 12:04:27 -07006864
Joonwoo Park533b3682013-06-13 11:41:21 -07006865 WCD9XXX_BG_CLK_LOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006866 atomic_set(&kp_taiko_priv, 0);
6867
6868 if (spkr_drv_wrnd > 0)
6869 wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
6870 WCD9XXX_BANDGAP_AUDIO_MODE);
Joonwoo Park533b3682013-06-13 11:41:21 -07006871 WCD9XXX_BG_CLK_UNLOCK(&taiko->resmgr);
Joonwoo Park125cd4e2012-12-11 15:16:11 -08006872
Ravishankar Sarawadi7b700362013-04-18 15:56:02 -07006873 taiko_cleanup_irqs(taiko);
6874
Joonwoo Parka8890262012-10-15 12:04:27 -07006875 /* cleanup MBHC */
6876 wcd9xxx_mbhc_deinit(&taiko->mbhc);
6877 /* cleanup resmgr */
6878 wcd9xxx_resmgr_deinit(&taiko->resmgr);
6879
Joonwoo Park448a8fc2013-04-10 15:25:58 -07006880 taiko->spkdrv_reg = NULL;
6881
Kiran Kandic3b24402012-06-11 00:05:59 -07006882 kfree(taiko);
6883 return 0;
6884}
6885static struct snd_soc_codec_driver soc_codec_dev_taiko = {
6886 .probe = taiko_codec_probe,
6887 .remove = taiko_codec_remove,
6888
6889 .read = taiko_read,
6890 .write = taiko_write,
6891
6892 .readable_register = taiko_readable,
6893 .volatile_register = taiko_volatile,
6894
6895 .reg_cache_size = TAIKO_CACHE_SIZE,
Kiran Kandi7b7d2ff2012-09-14 14:52:14 -07006896 .reg_cache_default = taiko_reset_reg_defaults,
Kiran Kandic3b24402012-06-11 00:05:59 -07006897 .reg_word_size = 1,
6898
6899 .controls = taiko_snd_controls,
6900 .num_controls = ARRAY_SIZE(taiko_snd_controls),
6901 .dapm_widgets = taiko_dapm_widgets,
6902 .num_dapm_widgets = ARRAY_SIZE(taiko_dapm_widgets),
6903 .dapm_routes = audio_map,
6904 .num_dapm_routes = ARRAY_SIZE(audio_map),
6905};
6906
6907#ifdef CONFIG_PM
6908static int taiko_suspend(struct device *dev)
6909{
6910 dev_dbg(dev, "%s: system suspend\n", __func__);
6911 return 0;
6912}
6913
6914static int taiko_resume(struct device *dev)
6915{
6916 struct platform_device *pdev = to_platform_device(dev);
6917 struct taiko_priv *taiko = platform_get_drvdata(pdev);
6918 dev_dbg(dev, "%s: system resume\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07006919 /* Notify */
6920 wcd9xxx_resmgr_notifier_call(&taiko->resmgr, WCD9XXX_EVENT_POST_RESUME);
Kiran Kandic3b24402012-06-11 00:05:59 -07006921 return 0;
6922}
6923
6924static const struct dev_pm_ops taiko_pm_ops = {
6925 .suspend = taiko_suspend,
6926 .resume = taiko_resume,
6927};
6928#endif
6929
6930static int __devinit taiko_probe(struct platform_device *pdev)
6931{
6932 int ret = 0;
6933 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
6934 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6935 taiko_dai, ARRAY_SIZE(taiko_dai));
6936 else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
6937 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
6938 taiko_i2s_dai, ARRAY_SIZE(taiko_i2s_dai));
6939 return ret;
6940}
6941static int __devexit taiko_remove(struct platform_device *pdev)
6942{
6943 snd_soc_unregister_codec(&pdev->dev);
6944 return 0;
6945}
6946static struct platform_driver taiko_codec_driver = {
6947 .probe = taiko_probe,
6948 .remove = taiko_remove,
6949 .driver = {
6950 .name = "taiko_codec",
6951 .owner = THIS_MODULE,
6952#ifdef CONFIG_PM
6953 .pm = &taiko_pm_ops,
6954#endif
6955 },
6956};
6957
6958static int __init taiko_codec_init(void)
6959{
6960 return platform_driver_register(&taiko_codec_driver);
6961}
6962
6963static void __exit taiko_codec_exit(void)
6964{
6965 platform_driver_unregister(&taiko_codec_driver);
6966}
6967
6968module_init(taiko_codec_init);
6969module_exit(taiko_codec_exit);
6970
6971MODULE_DESCRIPTION("Taiko codec driver");
6972MODULE_LICENSE("GPL v2");