blob: 0b07393d2a23e7f4e3a92c3eba03099d199e8663 [file] [log] [blame]
Banajit Goswamide8271c2017-01-18 00:28:59 -08001/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/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>
21#include <linux/wait.h>
22#include <linux/bitops.h>
23#include <linux/regmap.h>
24#include <linux/mfd/wcd9xxx/core.h>
25#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
26#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
27#include <linux/mfd/wcd9xxx/wcd9330_registers.h>
28#include <linux/mfd/wcd9xxx/pdata.h>
29#include <linux/regulator/consumer.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/tlv.h>
35#include <linux/delay.h>
36#include <linux/pm_runtime.h>
37#include <linux/kernel.h>
38#include <linux/gpio.h>
39#include <linux/clk.h>
40#include "wcd9330.h"
41#include "wcd9xxx-resmgr.h"
42#include "wcd9xxx-common.h"
43#include "wcdcal-hwdep.h"
44#include "wcd_cpe_core.h"
45
46enum {
47 BUS_DOWN,
48 ADC1_TXFE,
49 ADC2_TXFE,
50 ADC3_TXFE,
51 ADC4_TXFE,
52 ADC5_TXFE,
53 ADC6_TXFE,
54 HPH_DELAY,
55};
56
57#define TOMTOM_MAD_SLIMBUS_TX_PORT 12
58#define TOMTOM_MAD_AUDIO_FIRMWARE_PATH "wcd9320/wcd9320_mad_audio.bin"
59#define TOMTOM_VALIDATE_RX_SBPORT_RANGE(port) ((port >= 16) && (port <= 23))
60#define TOMTOM_VALIDATE_TX_SBPORT_RANGE(port) ((port >= 0) && (port <= 15))
61#define TOMTOM_CONVERT_RX_SBPORT_ID(port) (port - 16) /* RX1 port ID = 0 */
62#define TOMTOM_BIT_ADJ_SHIFT_PORT1_6 4
63#define TOMTOM_BIT_ADJ_SHIFT_PORT7_10 5
64
65#define TOMTOM_HPH_PA_SETTLE_COMP_ON 10000
66#define TOMTOM_HPH_PA_SETTLE_COMP_OFF 13000
67#define TOMTOM_HPH_PA_RAMP_DELAY 30000
68
69#define TOMTOM_SVASS_INT_STATUS_RCO_WDOG 0x20
70#define TOMTOM_SVASS_INT_STATUS_WDOG_BITE 0x02
71
72/* Add any SVA IRQs that are to be treated as FATAL */
73#define TOMTOM_CPE_FATAL_IRQS \
74 (TOMTOM_SVASS_INT_STATUS_RCO_WDOG | \
75 TOMTOM_SVASS_INT_STATUS_WDOG_BITE)
76
77#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
78
79/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
80#define TOMTOM_WG_TIME_FACTOR_US 240
81
82#define RX8_PATH 8
83#define HPH_PA_ENABLE true
84#define HPH_PA_DISABLE false
85
86#define SLIM_BW_CLK_GEAR_9 6200000
87#define SLIM_BW_UNVOTE 0
88
89static int cpe_debug_mode;
90module_param(cpe_debug_mode, int, 0664);
91MODULE_PARM_DESC(cpe_debug_mode, "boot cpe in debug mode");
92
93static atomic_t kp_tomtom_priv;
94
95static int high_perf_mode;
96module_param(high_perf_mode, int, 0664);
97MODULE_PARM_DESC(high_perf_mode, "enable/disable class AB config for hph");
98
99static struct afe_param_slimbus_slave_port_cfg tomtom_slimbus_slave_port_cfg = {
100 .minor_version = 1,
101 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
102 .slave_dev_pgd_la = 0,
103 .slave_dev_intfdev_la = 0,
104 .bit_width = 16,
105 .data_format = 0,
106 .num_channels = 1
107};
108
109static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
110 {
111 1,
112 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_MAD_MAIN_CTL_1),
113 HW_MAD_AUDIO_ENABLE, 0x1, 8, 0
114 },
115 {
116 1,
117 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_MAD_AUDIO_CTL_3),
118 HW_MAD_AUDIO_SLEEP_TIME, 0xF, 8, 0
119 },
120 {
121 1,
122 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_MAD_AUDIO_CTL_4),
123 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, 8, 0
124 },
125 {
126 1,
127 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR_MODE),
128 MAD_AUDIO_INT_DEST_SELECT_REG, 0x4, 8, 0
129 },
130 {
131 1,
132 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_MASK0),
133 MAD_AUDIO_INT_MASK_REG, 0x2, 8, 0
134 },
135 {
136 1,
137 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_STATUS0),
138 MAD_AUDIO_INT_STATUS_REG, 0x2, 8, 0
139 },
140 {
141 1,
142 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_CLEAR0),
143 MAD_AUDIO_INT_CLEAR_REG, 0x2, 8, 0
144 },
145 {
146 1,
147 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_SB_PGD_PORT_TX_BASE),
148 SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
149 },
150 {
151 1,
152 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_SB_PGD_PORT_TX_BASE),
153 SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
154 },
155 {
156 1,
157 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_SB_PGD_PORT_RX_BASE),
158 SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
159 },
160 {
161 1,
162 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_SB_PGD_PORT_RX_BASE),
163 SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
164 },
165 { 1,
166 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_ANC1_IIR_B1_CTL),
167 AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
168 },
169 { 1,
170 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_ANC1_IIR_B1_CTL),
171 AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
172 },
173 {
174 1,
175 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_CDC_ANC1_GAIN_CTL),
176 AANC_GAIN_CONTROL, 0xFF, 8, 0
177 },
178 {
179 1,
180 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_MASK0),
181 MAD_CLIP_INT_MASK_REG, 0x10, 8, 0
182 },
183 {
184 1,
185 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_MASK0),
186 MAD2_CLIP_INT_MASK_REG, 0x20, 8, 0
187 },
188 {
189 1,
190 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_STATUS0),
191 MAD_CLIP_INT_STATUS_REG, 0x10, 8, 0
192 },
193 {
194 1,
195 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_STATUS0),
196 MAD2_CLIP_INT_STATUS_REG, 0x20, 8, 0
197 },
198 {
199 1,
200 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_CLEAR0),
201 MAD_CLIP_INT_CLEAR_REG, 0x10, 8, 0
202 },
203 {
204 1,
205 (TOMTOM_REGISTER_START_OFFSET + TOMTOM_A_INTR2_CLEAR0),
206 MAD2_CLIP_INT_CLEAR_REG, 0x20, 8, 0
207 },
208};
209
210static struct afe_param_cdc_reg_cfg clip_reg_cfg[] = {
211 {
212 1,
213 (TOMTOM_REGISTER_START_OFFSET +
214 TOMTOM_A_CDC_SPKR_CLIPDET_B1_CTL),
215 SPKR_CLIP_PIPE_BANK_SEL, 0x3, 8, 0
216 },
217 {
218 1,
219 (TOMTOM_REGISTER_START_OFFSET +
220 TOMTOM_A_CDC_SPKR_CLIPDET_VAL0),
221 SPKR_CLIPDET_VAL0, 0xff, 8, 0
222 },
223 {
224 1,
225 (TOMTOM_REGISTER_START_OFFSET +
226 TOMTOM_A_CDC_SPKR_CLIPDET_VAL1),
227 SPKR_CLIPDET_VAL1, 0xff, 8, 0
228 },
229 {
230 1,
231 (TOMTOM_REGISTER_START_OFFSET +
232 TOMTOM_A_CDC_SPKR_CLIPDET_VAL2),
233 SPKR_CLIPDET_VAL2, 0xff, 8, 0
234 },
235 {
236 1,
237 (TOMTOM_REGISTER_START_OFFSET +
238 TOMTOM_A_CDC_SPKR_CLIPDET_VAL3),
239 SPKR_CLIPDET_VAL3, 0xff, 8, 0
240 },
241 {
242 1,
243 (TOMTOM_REGISTER_START_OFFSET +
244 TOMTOM_A_CDC_SPKR_CLIPDET_VAL4),
245 SPKR_CLIPDET_VAL4, 0xff, 8, 0
246 },
247 {
248 1,
249 (TOMTOM_REGISTER_START_OFFSET +
250 TOMTOM_A_CDC_SPKR_CLIPDET_VAL5),
251 SPKR_CLIPDET_VAL5, 0xff, 8, 0
252 },
253 {
254 1,
255 (TOMTOM_REGISTER_START_OFFSET +
256 TOMTOM_A_CDC_SPKR_CLIPDET_VAL6),
257 SPKR_CLIPDET_VAL6, 0xff, 8, 0
258 },
259 {
260 1,
261 (TOMTOM_REGISTER_START_OFFSET +
262 TOMTOM_A_CDC_SPKR_CLIPDET_VAL7),
263 SPKR_CLIPDET_VAL7, 0xff, 8, 0
264 },
265 {
266 1,
267 (TOMTOM_REGISTER_START_OFFSET +
268 TOMTOM_A_CDC_SPKR2_CLIPDET_B1_CTL),
269 SPKR2_CLIP_PIPE_BANK_SEL, 0x3, 8, 0
270 },
271 {
272 1,
273 (TOMTOM_REGISTER_START_OFFSET +
274 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL0),
275 SPKR2_CLIPDET_VAL0, 0xff, 8, 0
276 },
277 {
278 1,
279 (TOMTOM_REGISTER_START_OFFSET +
280 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL1),
281 SPKR2_CLIPDET_VAL1, 0xff, 8, 0
282 },
283 {
284 1,
285 (TOMTOM_REGISTER_START_OFFSET +
286 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL2),
287 SPKR2_CLIPDET_VAL2, 0xff, 8, 0
288 },
289 {
290 1,
291 (TOMTOM_REGISTER_START_OFFSET +
292 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL3),
293 SPKR2_CLIPDET_VAL3, 0xff, 8, 0
294 },
295 {
296 1,
297 (TOMTOM_REGISTER_START_OFFSET +
298 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL4),
299 SPKR2_CLIPDET_VAL4, 0xff, 8, 0
300 },
301 {
302 1,
303 (TOMTOM_REGISTER_START_OFFSET +
304 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL5),
305 SPKR2_CLIPDET_VAL5, 0xff, 8, 0
306 },
307 {
308 1,
309 (TOMTOM_REGISTER_START_OFFSET +
310 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL6),
311 SPKR2_CLIPDET_VAL6, 0xff, 8, 0
312 },
313 {
314 1,
315 (TOMTOM_REGISTER_START_OFFSET +
316 TOMTOM_A_CDC_SPKR2_CLIPDET_VAL7),
317 SPKR2_CLIPDET_VAL7, 0xff, 8, 0
318 },
319};
320
321static struct afe_param_cdc_reg_cfg_data tomtom_audio_reg_cfg = {
322 .num_registers = ARRAY_SIZE(audio_reg_cfg),
323 .reg_data = audio_reg_cfg,
324};
325
326static struct afe_param_cdc_reg_cfg_data tomtom_clip_reg_cfg = {
327 .num_registers = ARRAY_SIZE(clip_reg_cfg),
328 .reg_data = clip_reg_cfg,
329};
330
331static struct afe_param_id_cdc_aanc_version tomtom_cdc_aanc_version = {
332 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
333 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
334};
335
336static struct afe_param_id_clip_bank_sel clip_bank_sel = {
337 .minor_version = AFE_API_VERSION_CLIP_BANK_SEL_CFG,
338 .num_banks = AFE_CLIP_MAX_BANKS,
339 .bank_map = {0, 1, 2, 3},
340};
341
342#define WCD9330_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
343 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
344 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
345
346#define NUM_DECIMATORS 10
347#define NUM_INTERPOLATORS 8
348#define BITS_PER_REG 8
349#define TOMTOM_TX_PORT_NUMBER 16
350#define TOMTOM_RX_PORT_START_NUMBER 16
351
352#define TOMTOM_I2S_MASTER_MODE_MASK 0x08
353
354#define TOMTOM_SLIM_CLOSE_TIMEOUT 1000
355#define TOMTOM_SLIM_IRQ_OVERFLOW (1 << 0)
356#define TOMTOM_SLIM_IRQ_UNDERFLOW (1 << 1)
357#define TOMTOM_SLIM_IRQ_PORT_CLOSED (1 << 2)
358#define TOMTOM_MCLK_CLK_12P288MHZ 12288000
359#define TOMTOM_MCLK_CLK_9P6MHZ 9600000
360
361#define TOMTOM_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
362 SNDRV_PCM_FORMAT_S24_LE)
363
364#define TOMTOM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
365
366#define TOMTOM_SLIM_PGD_PORT_INT_TX_EN0 (TOMTOM_SLIM_PGD_PORT_INT_EN0 + 2)
367#define TOMTOM_ZDET_BOX_CAR_AVG_LOOP_COUNT 1
368#define TOMTOM_ZDET_MUL_FACTOR_1X 7218
369#define TOMTOM_ZDET_MUL_FACTOR_10X (TOMTOM_ZDET_MUL_FACTOR_1X * 10)
370#define TOMTOM_ZDET_MUL_FACTOR_100X (TOMTOM_ZDET_MUL_FACTOR_1X * 100)
371#define TOMTOM_ZDET_ERROR_APPROX_MUL_FACTOR 655
372#define TOMTOM_ZDET_ERROR_APPROX_SHIFT 16
373#define TOMTOM_ZDET_ZONE_3_DEFAULT_VAL 1000000
374
375enum {
376 AIF1_PB = 0,
377 AIF1_CAP,
378 AIF2_PB,
379 AIF2_CAP,
380 AIF3_PB,
381 AIF3_CAP,
382 AIF4_VIFEED,
383 AIF4_MAD_TX,
384 NUM_CODEC_DAIS,
385};
386
387enum {
388 RX_MIX1_INP_SEL_ZERO = 0,
389 RX_MIX1_INP_SEL_SRC1,
390 RX_MIX1_INP_SEL_SRC2,
391 RX_MIX1_INP_SEL_IIR1,
392 RX_MIX1_INP_SEL_IIR2,
393 RX_MIX1_INP_SEL_RX1,
394 RX_MIX1_INP_SEL_RX2,
395 RX_MIX1_INP_SEL_RX3,
396 RX_MIX1_INP_SEL_RX4,
397 RX_MIX1_INP_SEL_RX5,
398 RX_MIX1_INP_SEL_RX6,
399 RX_MIX1_INP_SEL_RX7,
400 RX_MIX1_INP_SEL_AUXRX,
401};
402enum {
403 RX8_MIX1_INP_SEL_ZERO = 0,
404 RX8_MIX1_INP_SEL_IIR1,
405 RX8_MIX1_INP_SEL_IIR2,
406 RX8_MIX1_INP_SEL_RX1,
407 RX8_MIX1_INP_SEL_RX2,
408 RX8_MIX1_INP_SEL_RX3,
409 RX8_MIX1_INP_SEL_RX4,
410 RX8_MIX1_INP_SEL_RX5,
411 RX8_MIX1_INP_SEL_RX6,
412 RX8_MIX1_INP_SEL_RX7,
413 RX8_MIX1_INP_SEL_RX8,
414};
415
416#define TOMTOM_COMP_DIGITAL_GAIN_OFFSET 3
417
418static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
419static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
420static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
421static struct snd_soc_dai_driver tomtom_dai[];
422static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
423
424/* Codec supports 2 IIR filters */
425enum {
426 IIR1 = 0,
427 IIR2,
428 IIR_MAX,
429};
430/* Codec supports 5 bands */
431enum {
432 BAND1 = 0,
433 BAND2,
434 BAND3,
435 BAND4,
436 BAND5,
437 BAND_MAX,
438};
439
440enum {
441 COMPANDER_0,
442 COMPANDER_1,
443 COMPANDER_2,
444 COMPANDER_MAX,
445};
446
447enum {
448 COMPANDER_FS_8KHZ = 0,
449 COMPANDER_FS_16KHZ,
450 COMPANDER_FS_32KHZ,
451 COMPANDER_FS_48KHZ,
452 COMPANDER_FS_96KHZ,
453 COMPANDER_FS_192KHZ,
454 COMPANDER_FS_MAX,
455};
456
457struct comp_sample_dependent_params {
458 u32 peak_det_timeout;
459 u32 rms_meter_div_fact;
460 u32 rms_meter_resamp_fact;
461};
462
463struct hpf_work {
464 struct tomtom_priv *tomtom;
465 u32 decimator;
466 u8 tx_hpf_cut_of_freq;
467 bool tx_hpf_bypass;
468 struct delayed_work dwork;
469};
470
471static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
472
473static const struct wcd9xxx_ch tomtom_rx_chs[TOMTOM_RX_MAX] = {
474 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER, 0),
475 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 1, 1),
476 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 2, 2),
477 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 3, 3),
478 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 4, 4),
479 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 5, 5),
480 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 6, 6),
481 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 7, 7),
482 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 8, 8),
483 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 9, 9),
484 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 10, 10),
485 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 11, 11),
486 WCD9XXX_CH(TOMTOM_RX_PORT_START_NUMBER + 12, 12),
487};
488
489static const struct wcd9xxx_ch tomtom_tx_chs[TOMTOM_TX_MAX] = {
490 WCD9XXX_CH(0, 0),
491 WCD9XXX_CH(1, 1),
492 WCD9XXX_CH(2, 2),
493 WCD9XXX_CH(3, 3),
494 WCD9XXX_CH(4, 4),
495 WCD9XXX_CH(5, 5),
496 WCD9XXX_CH(6, 6),
497 WCD9XXX_CH(7, 7),
498 WCD9XXX_CH(8, 8),
499 WCD9XXX_CH(9, 9),
500 WCD9XXX_CH(10, 10),
501 WCD9XXX_CH(11, 11),
502 WCD9XXX_CH(12, 12),
503 WCD9XXX_CH(13, 13),
504 WCD9XXX_CH(14, 14),
505 WCD9XXX_CH(15, 15),
506};
507
508static const u32 vport_check_table[NUM_CODEC_DAIS] = {
509 0, /* AIF1_PB */
510 (1 << AIF2_CAP) | (1 << AIF3_CAP), /* AIF1_CAP */
511 0, /* AIF2_PB */
512 (1 << AIF1_CAP) | (1 << AIF3_CAP), /* AIF2_CAP */
513 0, /* AIF3_PB */
514 (1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF3_CAP */
515};
516
517static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
518 0, /* AIF1_PB */
519 0, /* AIF1_CAP */
520 0, /* AIF2_PB */
521 0, /* AIF2_CAP */
522};
523
524/*
525 * Interrupt table for v3 corresponds to newer version
526 * codecs (wcd9330)
527 */
528static const struct intr_data wcd9330_intr_tbl[] = {
529 {WCD9XXX_IRQ_SLIMBUS, false},
530 {WCD9XXX_IRQ_MBHC_INSERTION, true},
531 {WCD9XXX_IRQ_MBHC_POTENTIAL, true},
532 {WCD9XXX_IRQ_MBHC_RELEASE, true},
533 {WCD9XXX_IRQ_MBHC_PRESS, true},
534 {WCD9XXX_IRQ_MBHC_SHORT_TERM, true},
535 {WCD9XXX_IRQ_MBHC_REMOVAL, true},
536 {WCD9330_IRQ_MBHC_JACK_SWITCH, true},
537 {WCD9XXX_IRQ_BG_PRECHARGE, false},
538 {WCD9XXX_IRQ_PA1_STARTUP, false},
539 {WCD9XXX_IRQ_PA2_STARTUP, false},
540 {WCD9XXX_IRQ_PA3_STARTUP, false},
541 {WCD9XXX_IRQ_PA4_STARTUP, false},
542 {WCD9XXX_IRQ_PA5_STARTUP, false},
543 {WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
544 {WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
545 {WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
546 {WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
547 {WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
548 {WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
549 {WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
550 {WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
551 {WCD9320_IRQ_EAR_PA_STARTUP, false},
552 {WCD9330_IRQ_SVASS_ERR_EXCEPTION, false},
553 {WCD9330_IRQ_SVASS_ENGINE, true},
554 {WCD9330_IRQ_MAD_AUDIO, false},
555 {WCD9330_IRQ_MAD_BEACON, false},
556 {WCD9330_IRQ_MAD_ULTRASOUND, false},
557 {WCD9330_IRQ_SPEAKER1_CLIPPING, false},
558 {WCD9330_IRQ_SPEAKER2_CLIPPING, false},
559 {WCD9330_IRQ_VBAT_MONITOR_ATTACK, false},
560 {WCD9330_IRQ_VBAT_MONITOR_RELEASE, false},
561};
562
563struct tomtom_priv {
564 struct snd_soc_codec *codec;
565 u32 adc_count;
566 u32 rx_bias_count;
567 s32 dmic_1_2_clk_cnt;
568 s32 dmic_3_4_clk_cnt;
569 s32 dmic_5_6_clk_cnt;
570 s32 ldo_h_users;
571 s32 micb_2_users;
572
573 u32 anc_slot;
574 bool anc_func;
575
576 /* cal info for codec */
577 struct fw_info *fw_data;
578
579 /*track tomtom interface type*/
580 u8 intf_type;
581
582 /* num of slim ports required */
583 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
584
585 /*compander*/
586 int comp_enabled[COMPANDER_MAX];
587 u32 comp_fs[COMPANDER_MAX];
588
589 /* Maintain the status of AUX PGA */
590 int aux_pga_cnt;
591 u8 aux_l_gain;
592 u8 aux_r_gain;
593
594 bool spkr_pa_widget_on;
595 struct regulator *spkdrv_reg;
596 struct regulator *spkdrv2_reg;
597
598 bool mbhc_started;
599
600 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
601
602 /* resmgr module */
603 struct wcd9xxx_resmgr resmgr;
604 /* mbhc module */
605 struct wcd9xxx_mbhc mbhc;
606
607 /* class h specific data */
608 struct wcd9xxx_clsh_cdc_data clsh_d;
609
610 int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
611 enum wcd9xxx_codec_event);
612 int (*codec_ext_clk_en_cb)(struct snd_soc_codec *codec,
613 int enable, bool dapm);
614 int (*codec_get_ext_clk_cnt)(void);
615 /*
616 * list used to save/restore registers at start and
617 * end of impedance measurement
618 */
619 struct list_head reg_save_restore;
620
621 /* handle to cpe core */
622 struct wcd_cpe_core *cpe_core;
623
624 /* UHQA (class AB) mode */
625 u8 uhqa_mode;
626
627 /* Multiplication factor used for impedance detection */
628 int zdet_gain_mul_fact;
629
630 /* to track the status */
631 unsigned long status_mask;
632
633 int ext_clk_users;
634 struct clk *wcd_ext_clk;
635
636 /* Port values for Rx and Tx codec_dai */
637 unsigned int rx_port_value;
638 unsigned int tx_port_value;
639
640 struct mutex codec_mutex;
641};
642
643static const u32 comp_shift[] = {
644 4, /* Compander 0's clock source is on interpolator 7 */
645 0,
646 2,
647};
648
649static const int comp_rx_path[] = {
650 COMPANDER_1,
651 COMPANDER_1,
652 COMPANDER_2,
653 COMPANDER_2,
654 COMPANDER_2,
655 COMPANDER_2,
656 COMPANDER_0,
657 COMPANDER_0,
658 COMPANDER_MAX,
659};
660
661static const struct comp_sample_dependent_params comp_samp_params[] = {
662 {
663 /* 8 Khz */
664 .peak_det_timeout = 0x06,
665 .rms_meter_div_fact = 0x09,
666 .rms_meter_resamp_fact = 0x06,
667 },
668 {
669 /* 16 Khz */
670 .peak_det_timeout = 0x07,
671 .rms_meter_div_fact = 0x0A,
672 .rms_meter_resamp_fact = 0x0C,
673 },
674 {
675 /* 32 Khz */
676 .peak_det_timeout = 0x08,
677 .rms_meter_div_fact = 0x0B,
678 .rms_meter_resamp_fact = 0x1E,
679 },
680 {
681 /* 48 Khz */
682 .peak_det_timeout = 0x09,
683 .rms_meter_div_fact = 0x0B,
684 .rms_meter_resamp_fact = 0x28,
685 },
686 {
687 /* 96 Khz */
688 .peak_det_timeout = 0x0A,
689 .rms_meter_div_fact = 0x0C,
690 .rms_meter_resamp_fact = 0x50,
691 },
692 {
693 /* 192 Khz */
694 .peak_det_timeout = 0x0B,
695 .rms_meter_div_fact = 0xC,
696 .rms_meter_resamp_fact = 0xA0,
697 },
698};
699
700static unsigned short rx_digital_gain_reg[] = {
701 TOMTOM_A_CDC_RX1_VOL_CTL_B2_CTL,
702 TOMTOM_A_CDC_RX2_VOL_CTL_B2_CTL,
703 TOMTOM_A_CDC_RX3_VOL_CTL_B2_CTL,
704 TOMTOM_A_CDC_RX4_VOL_CTL_B2_CTL,
705 TOMTOM_A_CDC_RX5_VOL_CTL_B2_CTL,
706 TOMTOM_A_CDC_RX6_VOL_CTL_B2_CTL,
707 TOMTOM_A_CDC_RX7_VOL_CTL_B2_CTL,
708 TOMTOM_A_CDC_RX8_VOL_CTL_B2_CTL,
709};
710
711
712static unsigned short tx_digital_gain_reg[] = {
713 TOMTOM_A_CDC_TX1_VOL_CTL_GAIN,
714 TOMTOM_A_CDC_TX2_VOL_CTL_GAIN,
715 TOMTOM_A_CDC_TX3_VOL_CTL_GAIN,
716 TOMTOM_A_CDC_TX4_VOL_CTL_GAIN,
717 TOMTOM_A_CDC_TX5_VOL_CTL_GAIN,
718 TOMTOM_A_CDC_TX6_VOL_CTL_GAIN,
719 TOMTOM_A_CDC_TX7_VOL_CTL_GAIN,
720 TOMTOM_A_CDC_TX8_VOL_CTL_GAIN,
721 TOMTOM_A_CDC_TX9_VOL_CTL_GAIN,
722 TOMTOM_A_CDC_TX10_VOL_CTL_GAIN,
723};
724
725/*
726 * wcd9330_get_codec_info: Get codec specific information
727 *
728 * @wcd9xxx: pointer to wcd9xxx structure
729 * @wcd_type: pointer to wcd9xxx_codec_type structure
730 *
731 * Returns 0 for success or negative error code for failure
732 */
733int wcd9330_get_codec_info(struct wcd9xxx *wcd9xxx,
734 struct wcd9xxx_codec_type *wcd_type)
735{
736 u16 id_minor, id_major;
737 struct regmap *wcd_regmap;
738 int rc, val, version = 0;
739
740 if (!wcd9xxx || !wcd_type)
741 return -EINVAL;
742
743 if (!wcd9xxx->regmap) {
744 dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
745 __func__);
746 return -EINVAL;
747 }
748 wcd_regmap = wcd9xxx->regmap;
749 rc = regmap_bulk_read(wcd_regmap, TOMTOM_A_CHIP_ID_BYTE_0,
750 (u8 *)&id_minor, sizeof(u16));
751 if (rc)
752 return -EINVAL;
753
754 rc = regmap_bulk_read(wcd_regmap, TOMTOM_A_CHIP_ID_BYTE_2,
755 (u8 *)&id_major, sizeof(u16));
756 if (rc)
757 return -EINVAL;
758
759 dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
760 __func__, id_major, id_minor);
761
762 if (id_minor == cpu_to_le16(0x1))
763 version = 2;
764 else if (id_minor == cpu_to_le16(0x0))
765 version = 1;
766 else
767 dev_err(wcd9xxx->dev, "%s: wcd9330 version unknown (major 0x%x, minor 0x%x)\n",
768 __func__, id_major, id_minor);
769
770 /* Fill codec type info */
771 wcd_type->id_major = id_major;
772 wcd_type->id_minor = id_minor;
773 wcd_type->num_irqs = WCD9330_NUM_IRQS;
774 wcd_type->version = version;
775 wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
776 wcd_type->i2c_chip_status = 0x01;
777 wcd_type->intr_tbl = wcd9330_intr_tbl;
778 wcd_type->intr_tbl_size = ARRAY_SIZE(wcd9330_intr_tbl);
779
780 wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
781 TOMTOM_A_INTR1_STATUS0;
782 wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
783 TOMTOM_A_INTR1_CLEAR0;
784 wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
785 TOMTOM_A_INTR1_MASK0;
786 wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
787 TOMTOM_A_INTR1_LEVEL0;
788 wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
789 TOMTOM_A_INTR_MODE;
790
791 return rc;
792}
793EXPORT_SYMBOL(wcd9330_get_codec_info);
794
795/*
796 * wcd9330_bringdown: Bringdown WCD Codec
797 *
798 * @wcd9xxx: Pointer to wcd9xxx structure
799 *
800 * Returns 0 for success or negative error code for failure
801 */
802int wcd9330_bringdown(struct wcd9xxx *wcd9xxx)
803{
804 if (!wcd9xxx || !wcd9xxx->regmap)
805 return -EINVAL;
806
807 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0x7);
808 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0x6);
809 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0xe);
810 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0x8);
811
812 return 0;
813}
814EXPORT_SYMBOL(wcd9330_bringdown);
815
816/*
817 * wcd9330_bringup: Bring up WCD Codec
818 *
819 * @wcd9xxx: Pointer to wcd9xxx structure
820 *
821 * Returns 0 for success or negative error code for failure
822 */
823int wcd9330_bringup(struct wcd9xxx *wcd9xxx)
824{
825 if (!wcd9xxx || !wcd9xxx->regmap)
826 return -EINVAL;
827
828 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0x4);
829 regmap_write(wcd9xxx->regmap, TOMTOM_A_CDC_CTL, 0x0);
830 /* wait for 5ms after codec reset for it to complete */
831 usleep_range(5000, 5100);
832 regmap_write(wcd9xxx->regmap, TOMTOM_A_CDC_CTL, 0x1);
833 regmap_write(wcd9xxx->regmap, TOMTOM_A_LEAKAGE_CTL, 0x3);
834 regmap_write(wcd9xxx->regmap, TOMTOM_A_CDC_CTL, 0x3);
835
836 return 0;
837}
838EXPORT_SYMBOL(wcd9330_bringup);
839
840int tomtom_enable_qfuse_sensing(struct snd_soc_codec *codec)
841{
842 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
843
844 if (tomtom->wcd_ext_clk)
845 tomtom_codec_mclk_enable(codec, true, false);
846
847 snd_soc_write(codec, TOMTOM_A_QFUSE_CTL, 0x03);
848 /*
849 * 5ms sleep required after enabling qfuse control
850 * before checking the status.
851 */
852 usleep_range(5000, 5500);
853 if ((snd_soc_read(codec, TOMTOM_A_QFUSE_STATUS) & (0x03)) != 0x03)
854 WARN(1, "%s: Qfuse sense is not complete\n", __func__);
855
856 if (tomtom->wcd_ext_clk)
857 tomtom_codec_mclk_enable(codec, false, false);
858 return 0;
859}
860EXPORT_SYMBOL(tomtom_enable_qfuse_sensing);
861
862static int tomtom_get_sample_rate(struct snd_soc_codec *codec, int path)
863{
864 if (path == RX8_PATH)
865 return snd_soc_read(codec, TOMTOM_A_CDC_RX8_B5_CTL);
866 else
867 return snd_soc_read(codec,
868 (TOMTOM_A_CDC_RX1_B5_CTL + 8 * (path - 1)));
869}
870
871static int tomtom_compare_bit_format(struct snd_soc_codec *codec,
872 int bit_format)
873{
874 int i = 0;
875 int ret = 0;
876 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
877
878 for (i = 0; i < NUM_CODEC_DAIS; i++) {
879 if (tomtom_p->dai[i].bit_width == bit_format) {
880 ret = 1;
881 break;
882 }
883 }
884 return ret;
885}
886
887static int tomtom_update_uhqa_mode(struct snd_soc_codec *codec, int path)
888{
889 int ret = 0;
890 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
891
892 /* UHQA path has fs=192KHz & bit=24 bit */
893 if (((tomtom_get_sample_rate(codec, path) & 0xE0) == 0xA0) &&
894 (tomtom_compare_bit_format(codec, 24))) {
895 tomtom_p->uhqa_mode = 1;
896 } else {
897 tomtom_p->uhqa_mode = 0;
898 }
899 dev_dbg(codec->dev, "%s: uhqa_mode=%d", __func__, tomtom_p->uhqa_mode);
900 return ret;
901}
902
903static int tomtom_get_anc_slot(struct snd_kcontrol *kcontrol,
904 struct snd_ctl_elem_value *ucontrol)
905{
906 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
907 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
908
909 ucontrol->value.integer.value[0] = tomtom->anc_slot;
910 return 0;
911}
912
913static int tomtom_put_anc_slot(struct snd_kcontrol *kcontrol,
914 struct snd_ctl_elem_value *ucontrol)
915{
916 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
917 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
918
919 tomtom->anc_slot = ucontrol->value.integer.value[0];
920 return 0;
921}
922
923static int tomtom_get_anc_func(struct snd_kcontrol *kcontrol,
924 struct snd_ctl_elem_value *ucontrol)
925{
926 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
927 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
928
929 ucontrol->value.integer.value[0] = (tomtom->anc_func == true ? 1 : 0);
930 return 0;
931}
932
933static int tomtom_put_anc_func(struct snd_kcontrol *kcontrol,
934 struct snd_ctl_elem_value *ucontrol)
935{
936 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
937 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
938 struct snd_soc_dapm_context *dapm =
939 snd_soc_codec_get_dapm(codec);
940
941 mutex_lock(&tomtom->codec_mutex);
942 tomtom->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
943
944 dev_dbg(codec->dev, "%s: anc_func %x", __func__, tomtom->anc_func);
945
946 if (tomtom->anc_func == true) {
947 snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
948 snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
949 snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
950 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
951 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
952 snd_soc_dapm_disable_pin(dapm, "HPHR");
953 snd_soc_dapm_disable_pin(dapm, "HPHL");
954 snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
955 snd_soc_dapm_disable_pin(dapm, "EAR PA");
956 snd_soc_dapm_disable_pin(dapm, "EAR");
957 } else {
958 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
959 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
960 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
961 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
962 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
963 snd_soc_dapm_enable_pin(dapm, "HPHR");
964 snd_soc_dapm_enable_pin(dapm, "HPHL");
965 snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
966 snd_soc_dapm_enable_pin(dapm, "EAR PA");
967 snd_soc_dapm_enable_pin(dapm, "EAR");
968 }
969 mutex_unlock(&tomtom->codec_mutex);
970 snd_soc_dapm_sync(dapm);
971 return 0;
972}
973
974static int tomtom_get_iir_enable_audio_mixer(
975 struct snd_kcontrol *kcontrol,
976 struct snd_ctl_elem_value *ucontrol)
977{
978 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
979 int iir_idx = ((struct soc_multi_mixer_control *)
980 kcontrol->private_value)->reg;
981 int band_idx = ((struct soc_multi_mixer_control *)
982 kcontrol->private_value)->shift;
983
984 ucontrol->value.integer.value[0] =
985 (snd_soc_read(codec, (TOMTOM_A_CDC_IIR1_CTL + 16 * iir_idx)) &
986 (1 << band_idx)) != 0;
987
988 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
989 iir_idx, band_idx,
990 (uint32_t)ucontrol->value.integer.value[0]);
991 return 0;
992}
993
994static int tomtom_put_iir_enable_audio_mixer(
995 struct snd_kcontrol *kcontrol,
996 struct snd_ctl_elem_value *ucontrol)
997{
998 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
999 int iir_idx = ((struct soc_multi_mixer_control *)
1000 kcontrol->private_value)->reg;
1001 int band_idx = ((struct soc_multi_mixer_control *)
1002 kcontrol->private_value)->shift;
1003 int value = ucontrol->value.integer.value[0];
1004
1005 /* Mask first 5 bits, 6-8 are reserved */
1006 snd_soc_update_bits(codec, (TOMTOM_A_CDC_IIR1_CTL + 16 * iir_idx),
1007 (1 << band_idx), (value << band_idx));
1008
1009 pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
1010 iir_idx, band_idx,
1011 ((snd_soc_read(codec, (TOMTOM_A_CDC_IIR1_CTL + 16 * iir_idx)) &
1012 (1 << band_idx)) != 0));
1013 return 0;
1014}
1015static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
1016 int iir_idx, int band_idx,
1017 int coeff_idx)
1018{
1019 uint32_t value = 0;
1020
1021 /* Address does not automatically update if reading */
1022 snd_soc_write(codec,
1023 (TOMTOM_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
1024 ((band_idx * BAND_MAX + coeff_idx)
1025 * sizeof(uint32_t)) & 0x7F);
1026
1027 value |= snd_soc_read(codec,
1028 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx));
1029
1030 snd_soc_write(codec,
1031 (TOMTOM_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
1032 ((band_idx * BAND_MAX + coeff_idx)
1033 * sizeof(uint32_t) + 1) & 0x7F);
1034
1035 value |= (snd_soc_read(codec,
1036 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 8);
1037
1038 snd_soc_write(codec,
1039 (TOMTOM_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
1040 ((band_idx * BAND_MAX + coeff_idx)
1041 * sizeof(uint32_t) + 2) & 0x7F);
1042
1043 value |= (snd_soc_read(codec,
1044 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 16);
1045
1046 snd_soc_write(codec,
1047 (TOMTOM_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
1048 ((band_idx * BAND_MAX + coeff_idx)
1049 * sizeof(uint32_t) + 3) & 0x7F);
1050
1051 /* Mask bits top 2 bits since they are reserved */
1052 value |= ((snd_soc_read(codec,
1053 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) & 0x3F) << 24);
1054
1055 return value;
1056}
1057
1058static int tomtom_get_iir_band_audio_mixer(
1059 struct snd_kcontrol *kcontrol,
1060 struct snd_ctl_elem_value *ucontrol)
1061{
1062 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1063 int iir_idx = ((struct soc_multi_mixer_control *)
1064 kcontrol->private_value)->reg;
1065 int band_idx = ((struct soc_multi_mixer_control *)
1066 kcontrol->private_value)->shift;
1067
1068 ucontrol->value.integer.value[0] =
1069 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
1070 ucontrol->value.integer.value[1] =
1071 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
1072 ucontrol->value.integer.value[2] =
1073 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
1074 ucontrol->value.integer.value[3] =
1075 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
1076 ucontrol->value.integer.value[4] =
1077 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
1078
1079 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
1080 "%s: IIR #%d band #%d b1 = 0x%x\n"
1081 "%s: IIR #%d band #%d b2 = 0x%x\n"
1082 "%s: IIR #%d band #%d a1 = 0x%x\n"
1083 "%s: IIR #%d band #%d a2 = 0x%x\n",
1084 __func__, iir_idx, band_idx,
1085 (uint32_t)ucontrol->value.integer.value[0],
1086 __func__, iir_idx, band_idx,
1087 (uint32_t)ucontrol->value.integer.value[1],
1088 __func__, iir_idx, band_idx,
1089 (uint32_t)ucontrol->value.integer.value[2],
1090 __func__, iir_idx, band_idx,
1091 (uint32_t)ucontrol->value.integer.value[3],
1092 __func__, iir_idx, band_idx,
1093 (uint32_t)ucontrol->value.integer.value[4]);
1094 return 0;
1095}
1096
1097static void set_iir_band_coeff(struct snd_soc_codec *codec,
1098 int iir_idx, int band_idx,
1099 uint32_t value)
1100{
1101 snd_soc_write(codec,
1102 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
1103 (value & 0xFF));
1104
1105 snd_soc_write(codec,
1106 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
1107 (value >> 8) & 0xFF);
1108
1109 snd_soc_write(codec,
1110 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
1111 (value >> 16) & 0xFF);
1112
1113 /* Mask top 2 bits, 7-8 are reserved */
1114 snd_soc_write(codec,
1115 (TOMTOM_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
1116 (value >> 24) & 0x3F);
1117}
1118
1119static int tomtom_put_iir_band_audio_mixer(
1120 struct snd_kcontrol *kcontrol,
1121 struct snd_ctl_elem_value *ucontrol)
1122{
1123 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1124 int iir_idx = ((struct soc_multi_mixer_control *)
1125 kcontrol->private_value)->reg;
1126 int band_idx = ((struct soc_multi_mixer_control *)
1127 kcontrol->private_value)->shift;
1128
1129 /* Mask top bit it is reserved */
1130 /* Updates addr automatically for each B2 write */
1131 snd_soc_write(codec,
1132 (TOMTOM_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
1133 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
1134
1135 set_iir_band_coeff(codec, iir_idx, band_idx,
1136 ucontrol->value.integer.value[0]);
1137 set_iir_band_coeff(codec, iir_idx, band_idx,
1138 ucontrol->value.integer.value[1]);
1139 set_iir_band_coeff(codec, iir_idx, band_idx,
1140 ucontrol->value.integer.value[2]);
1141 set_iir_band_coeff(codec, iir_idx, band_idx,
1142 ucontrol->value.integer.value[3]);
1143 set_iir_band_coeff(codec, iir_idx, band_idx,
1144 ucontrol->value.integer.value[4]);
1145
1146 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
1147 "%s: IIR #%d band #%d b1 = 0x%x\n"
1148 "%s: IIR #%d band #%d b2 = 0x%x\n"
1149 "%s: IIR #%d band #%d a1 = 0x%x\n"
1150 "%s: IIR #%d band #%d a2 = 0x%x\n",
1151 __func__, iir_idx, band_idx,
1152 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
1153 __func__, iir_idx, band_idx,
1154 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
1155 __func__, iir_idx, band_idx,
1156 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
1157 __func__, iir_idx, band_idx,
1158 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
1159 __func__, iir_idx, band_idx,
1160 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
1161 return 0;
1162}
1163
1164static int tomtom_get_compander(struct snd_kcontrol *kcontrol,
1165 struct snd_ctl_elem_value *ucontrol)
1166{
1167
1168 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1169 int comp = ((struct soc_multi_mixer_control *)
1170 kcontrol->private_value)->shift;
1171 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
1172
1173 ucontrol->value.integer.value[0] = tomtom->comp_enabled[comp];
1174 return 0;
1175}
1176
1177static int tomtom_set_compander(struct snd_kcontrol *kcontrol,
1178 struct snd_ctl_elem_value *ucontrol)
1179{
1180 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1181 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
1182 int comp = ((struct soc_multi_mixer_control *)
1183 kcontrol->private_value)->shift;
1184 int value = ucontrol->value.integer.value[0];
1185
1186 pr_debug("%s: Compander %d enable current %d, new %d\n",
1187 __func__, comp, tomtom->comp_enabled[comp], value);
1188 tomtom->comp_enabled[comp] = value;
1189
1190 if (comp == COMPANDER_1 &&
1191 tomtom->comp_enabled[comp] == 1) {
1192 /* Wavegen to 5 msec */
1193 snd_soc_write(codec, TOMTOM_A_RX_HPH_CNP_WG_CTL, 0xDB);
1194 snd_soc_write(codec, TOMTOM_A_RX_HPH_CNP_WG_TIME, 0x2A);
1195 snd_soc_write(codec, TOMTOM_A_RX_HPH_BIAS_WG_OCP, 0x2A);
1196
1197 /* Enable Chopper */
1198 snd_soc_update_bits(codec,
1199 TOMTOM_A_RX_HPH_CHOP_CTL, 0x80, 0x80);
1200
1201 snd_soc_write(codec, TOMTOM_A_NCP_DTEST, 0x20);
1202 pr_debug("%s: Enabled Chopper and set wavegen to 5 msec\n",
1203 __func__);
1204 } else if (comp == COMPANDER_1 &&
1205 tomtom->comp_enabled[comp] == 0) {
1206 /* Wavegen to 20 msec */
1207 snd_soc_write(codec, TOMTOM_A_RX_HPH_CNP_WG_CTL, 0xDB);
1208 snd_soc_write(codec, TOMTOM_A_RX_HPH_CNP_WG_TIME, 0x58);
1209 snd_soc_write(codec, TOMTOM_A_RX_HPH_BIAS_WG_OCP, 0x1A);
1210
1211 /* Disable CHOPPER block */
1212 snd_soc_update_bits(codec,
1213 TOMTOM_A_RX_HPH_CHOP_CTL, 0x80, 0x00);
1214
1215 snd_soc_write(codec, TOMTOM_A_NCP_DTEST, 0x10);
1216 pr_debug("%s: Disabled Chopper and set wavegen to 20 msec\n",
1217 __func__);
1218 }
1219 return 0;
1220}
1221
1222static int tomtom_config_gain_compander(struct snd_soc_codec *codec,
1223 int comp, bool enable)
1224{
1225 int ret = 0;
1226
1227 switch (comp) {
1228 case COMPANDER_0:
1229 snd_soc_update_bits(codec, TOMTOM_A_SPKR_DRV1_GAIN,
1230 1 << 2, !enable << 2);
1231 snd_soc_update_bits(codec, TOMTOM_A_SPKR_DRV2_GAIN,
1232 1 << 2, !enable << 2);
1233 break;
1234 case COMPANDER_1:
1235 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_L_GAIN,
1236 1 << 5, !enable << 5);
1237 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_R_GAIN,
1238 1 << 5, !enable << 5);
1239 break;
1240 case COMPANDER_2:
1241 snd_soc_update_bits(codec, TOMTOM_A_RX_LINE_1_GAIN,
1242 1 << 5, !enable << 5);
1243 snd_soc_update_bits(codec, TOMTOM_A_RX_LINE_3_GAIN,
1244 1 << 5, !enable << 5);
1245 snd_soc_update_bits(codec, TOMTOM_A_RX_LINE_2_GAIN,
1246 1 << 5, !enable << 5);
1247 snd_soc_update_bits(codec, TOMTOM_A_RX_LINE_4_GAIN,
1248 1 << 5, !enable << 5);
1249 break;
1250 default:
1251 WARN_ON(1);
1252 ret = -EINVAL;
1253 }
1254
1255 return ret;
1256}
1257
1258static void tomtom_discharge_comp(struct snd_soc_codec *codec, int comp)
1259{
1260 /* Level meter DIV Factor to 5*/
1261 snd_soc_update_bits(codec, TOMTOM_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
1262 0x05 << 4);
1263 /* RMS meter Sampling to 0x01 */
1264 snd_soc_write(codec, TOMTOM_A_CDC_COMP0_B3_CTL + (comp * 8), 0x01);
1265
1266 /* Worst case timeout for compander CnP sleep timeout */
1267 usleep_range(3000, 3100);
1268}
1269
1270static enum wcd9xxx_buck_volt tomtom_codec_get_buck_mv(
1271 struct snd_soc_codec *codec)
1272{
1273 int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
1274 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
1275 struct wcd9xxx_pdata *pdata = tomtom->resmgr.pdata;
1276 int i;
1277
1278 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
1279 if (!strcmp(pdata->regulator[i].name,
1280 WCD9XXX_SUPPLY_BUCK_NAME)) {
1281 if ((pdata->regulator[i].min_uV ==
1282 WCD9XXX_CDC_BUCK_MV_1P8) ||
1283 (pdata->regulator[i].min_uV ==
1284 WCD9XXX_CDC_BUCK_MV_2P15))
1285 buck_volt = pdata->regulator[i].min_uV;
1286 break;
1287 }
1288 }
1289 return buck_volt;
1290}
1291
1292static int tomtom_config_compander(struct snd_soc_dapm_widget *w,
1293 struct snd_kcontrol *kcontrol, int event)
1294{
1295 int mask, enable_mask;
1296 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1297 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
1298 const int comp = w->shift;
1299 const u32 rate = tomtom->comp_fs[comp];
1300 const struct comp_sample_dependent_params *comp_params =
1301 &comp_samp_params[rate];
1302 enum wcd9xxx_buck_volt buck_mv;
1303
1304 pr_debug("%s: %s event %d compander %d, enabled %d", __func__,
1305 w->name, event, comp, tomtom->comp_enabled[comp]);
1306
1307 if (!tomtom->comp_enabled[comp])
1308 return 0;
1309
1310 /* Compander 0 has two channels */
1311 mask = enable_mask = 0x03;
1312 buck_mv = tomtom_codec_get_buck_mv(codec);
1313
1314 switch (event) {
1315 case SND_SOC_DAPM_PRE_PMU:
1316 /* Set compander Sample rate */
1317 snd_soc_update_bits(codec,
1318 TOMTOM_A_CDC_COMP0_FS_CFG + (comp * 8),
1319 0x07, rate);
1320 /* Set the static gain offset for HPH Path */
1321 if (comp == COMPANDER_1) {
1322 if (buck_mv == WCD9XXX_CDC_BUCK_MV_2P15) {
1323 snd_soc_update_bits(codec,
1324 TOMTOM_A_CDC_COMP0_B4_CTL + (comp * 8),
1325 0x80, 0x00);
1326 } else {
1327 snd_soc_update_bits(codec,
1328 TOMTOM_A_CDC_COMP0_B4_CTL + (comp * 8),
1329 0x80, 0x80);
1330 }
1331 }
1332 /* Enable RX interpolation path compander clocks */
1333 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_RX_B2_CTL,
1334 mask << comp_shift[comp],
1335 mask << comp_shift[comp]);
1336 /* Toggle compander reset bits */
1337 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_OTHR_RESET_B2_CTL,
1338 mask << comp_shift[comp],
1339 mask << comp_shift[comp]);
1340 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_OTHR_RESET_B2_CTL,
1341 mask << comp_shift[comp], 0);
1342
1343 /* Set gain source to compander */
1344 tomtom_config_gain_compander(codec, comp, true);
1345
1346 /* Compander enable */
1347 snd_soc_update_bits(codec, TOMTOM_A_CDC_COMP0_B1_CTL +
1348 (comp * 8), enable_mask, enable_mask);
1349
1350 tomtom_discharge_comp(codec, comp);
1351
1352 /* Set sample rate dependent parameter */
1353 snd_soc_write(codec, TOMTOM_A_CDC_COMP0_B3_CTL + (comp * 8),
1354 comp_params->rms_meter_resamp_fact);
1355 snd_soc_update_bits(codec,
1356 TOMTOM_A_CDC_COMP0_B2_CTL + (comp * 8),
1357 0xF0, comp_params->rms_meter_div_fact << 4);
1358 snd_soc_update_bits(codec,
1359 TOMTOM_A_CDC_COMP0_B2_CTL + (comp * 8),
1360 0x0F, comp_params->peak_det_timeout);
1361 break;
1362 case SND_SOC_DAPM_PRE_PMD:
1363 /* Disable compander */
1364 snd_soc_update_bits(codec,
1365 TOMTOM_A_CDC_COMP0_B1_CTL + (comp * 8),
1366 enable_mask, 0x00);
1367
1368 /* Toggle compander reset bits */
1369 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_OTHR_RESET_B2_CTL,
1370 mask << comp_shift[comp],
1371 mask << comp_shift[comp]);
1372 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_OTHR_RESET_B2_CTL,
1373 mask << comp_shift[comp], 0);
1374
1375 /* Turn off the clock for compander in pair */
1376 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_RX_B2_CTL,
1377 mask << comp_shift[comp], 0);
1378
1379 /* Set gain source to register */
1380 tomtom_config_gain_compander(codec, comp, false);
1381 break;
1382 }
1383 return 0;
1384}
1385
1386
1387
1388static const char *const tomtom_anc_func_text[] = {"OFF", "ON"};
1389static const struct soc_enum tomtom_anc_func_enum =
1390 SOC_ENUM_SINGLE_EXT(2, tomtom_anc_func_text);
1391
1392static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
1393static const struct soc_enum tabla_ear_pa_gain_enum[] = {
1394 SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
1395};
1396
1397/*cut of frequency for high pass filter*/
1398static const char * const cf_text[] = {
1399 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
1400};
1401
1402static const char * const rx_cf_text[] = {
1403 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz",
1404 "MIN_3DB_0P48Hz"
1405};
1406
1407static const struct soc_enum cf_dec1_enum =
1408 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
1409
1410static const struct soc_enum cf_dec2_enum =
1411 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
1412
1413static const struct soc_enum cf_dec3_enum =
1414 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
1415
1416static const struct soc_enum cf_dec4_enum =
1417 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
1418
1419static const struct soc_enum cf_dec5_enum =
1420 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
1421
1422static const struct soc_enum cf_dec6_enum =
1423 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
1424
1425static const struct soc_enum cf_dec7_enum =
1426 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
1427
1428static const struct soc_enum cf_dec8_enum =
1429 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
1430
1431static const struct soc_enum cf_dec9_enum =
1432 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
1433
1434static const struct soc_enum cf_dec10_enum =
1435 SOC_ENUM_SINGLE(TOMTOM_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
1436
1437static const struct soc_enum cf_rxmix1_enum =
1438 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX1_B4_CTL, 0, 4, rx_cf_text);
1439
1440static const struct soc_enum cf_rxmix2_enum =
1441 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX2_B4_CTL, 0, 4, rx_cf_text);
1442
1443static const struct soc_enum cf_rxmix3_enum =
1444 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX3_B4_CTL, 0, 4, rx_cf_text);
1445
1446static const struct soc_enum cf_rxmix4_enum =
1447 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX4_B4_CTL, 0, 4, rx_cf_text);
1448
1449static const struct soc_enum cf_rxmix5_enum =
1450 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX5_B4_CTL, 0, 4, rx_cf_text)
1451;
1452static const struct soc_enum cf_rxmix6_enum =
1453 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX6_B4_CTL, 0, 4, rx_cf_text);
1454
1455static const struct soc_enum cf_rxmix7_enum =
1456 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX7_B4_CTL, 0, 4, rx_cf_text);
1457
1458static const struct soc_enum cf_rxmix8_enum =
1459 SOC_ENUM_SINGLE(TOMTOM_A_CDC_RX8_B4_CTL, 0, 4, rx_cf_text);
1460
1461static const char * const class_h_dsm_text[] = {
1462 "ZERO", "DSM_HPHL_RX1", "DSM_SPKR_RX7"
1463};
1464
1465static const struct soc_enum class_h_dsm_enum =
1466 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_CLSH_CTL, 4, 3, class_h_dsm_text);
1467
1468static const struct snd_kcontrol_new class_h_dsm_mux =
1469 SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
1470
1471static const char * const rx1_interp_text[] = {
1472 "ZERO", "RX1 MIX2"
1473};
1474
1475static const struct soc_enum rx1_interp_enum =
1476 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CLK_RX_B1_CTL, 0, 2, rx1_interp_text);
1477
1478static const struct snd_kcontrol_new rx1_interp_mux =
1479 SOC_DAPM_ENUM("RX1 INTERP MUX Mux", rx1_interp_enum);
1480
1481static const char * const rx2_interp_text[] = {
1482 "ZERO", "RX2 MIX2"
1483};
1484
1485static const struct soc_enum rx2_interp_enum =
1486 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CLK_RX_B1_CTL, 1, 2, rx2_interp_text);
1487
1488static const struct snd_kcontrol_new rx2_interp_mux =
1489 SOC_DAPM_ENUM("RX2 INTERP MUX Mux", rx2_interp_enum);
1490
1491static const char *const tomtom_conn_mad_text[] = {
1492 "ADC_MB", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "NOTUSED1",
1493 "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "NOTUSED2",
1494 "NOTUSED3"};
1495
1496static const struct soc_enum tomtom_conn_mad_enum =
1497 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tomtom_conn_mad_text),
1498 tomtom_conn_mad_text);
1499
1500
1501static int tomtom_mad_input_get(struct snd_kcontrol *kcontrol,
1502 struct snd_ctl_elem_value *ucontrol)
1503{
1504 u8 tomtom_mad_input;
1505 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1506
1507 tomtom_mad_input = snd_soc_read(codec, TOMTOM_A_CDC_MAD_INP_SEL);
1508
1509 tomtom_mad_input = tomtom_mad_input & 0x0F;
1510
1511 ucontrol->value.integer.value[0] = tomtom_mad_input;
1512
1513 pr_debug("%s: tomtom_mad_input = %s\n", __func__,
1514 tomtom_conn_mad_text[tomtom_mad_input]);
1515
1516 return 0;
1517}
1518
1519static int tomtom_mad_input_put(struct snd_kcontrol *kcontrol,
1520 struct snd_ctl_elem_value *ucontrol)
1521{
1522 u8 tomtom_mad_input;
1523 u16 micb_int_reg, micb_4_int_reg;
1524 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1525 struct snd_soc_card *card = codec->component.card;
1526 char mad_amic_input_widget[6];
1527 u32 adc;
1528 const char *mad_input_widget;
1529 const char *source_widget = NULL;
1530 u32 mic_bias_found = 0;
1531 u32 i;
1532 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
1533 int ret = 0;
1534 char *mad_input;
1535
1536 tomtom_mad_input = ucontrol->value.integer.value[0];
1537 micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias;
1538
1539 pr_debug("%s: tomtom_mad_input = %s\n", __func__,
1540 tomtom_conn_mad_text[tomtom_mad_input]);
1541
1542 if (!strcmp(tomtom_conn_mad_text[tomtom_mad_input], "NOTUSED1") ||
1543 !strcmp(tomtom_conn_mad_text[tomtom_mad_input], "NOTUSED2") ||
1544 !strcmp(tomtom_conn_mad_text[tomtom_mad_input], "NOTUSED3") ||
1545 !strcmp(tomtom_conn_mad_text[tomtom_mad_input], "ADC_MB")) {
1546 pr_info("%s: tomtom mad input is set to unsupported input = %s\n",
1547 __func__, tomtom_conn_mad_text[tomtom_mad_input]);
1548 return -EINVAL;
1549 }
1550
1551 if (strnstr(tomtom_conn_mad_text[tomtom_mad_input],
1552 "ADC", sizeof("ADC"))) {
1553 mad_input = strpbrk(tomtom_conn_mad_text[tomtom_mad_input],
1554 "123456");
1555 if (!mad_input) {
1556 dev_err(codec->dev, "%s: Invalid MAD input %s\n",
1557 __func__, tomtom_conn_mad_text[tomtom_mad_input]);
1558 return -EINVAL;
1559 }
1560 ret = kstrtouint(mad_input, 10, &adc);
1561 if ((ret < 0) || (adc > 6)) {
1562 pr_err("%s: Invalid ADC = %s\n", __func__,
1563 tomtom_conn_mad_text[tomtom_mad_input]);
1564 ret = -EINVAL;
1565 }
1566
1567 snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
1568
1569 mad_input_widget = mad_amic_input_widget;
1570 pr_debug("%s: tomtom amic input widget = %s\n", __func__,
1571 mad_amic_input_widget);
1572 } else {
1573 /* DMIC type input widget*/
1574 mad_input_widget = tomtom_conn_mad_text[tomtom_mad_input];
1575 }
1576
1577 pr_debug("%s: tomtom input widget = %s\n", __func__, mad_input_widget);
1578
1579 for (i = 0; i < card->num_dapm_routes; i++) {
1580
1581 if (!strcmp(card->dapm_routes[i].sink, mad_input_widget)) {
1582
1583 source_widget = card->dapm_routes[i].source;
1584 if (!source_widget) {
1585 dev_err(codec->dev,
1586 "%s: invalid source widget\n",
1587 __func__);
1588 return -EINVAL;
1589 }
1590
1591 if (strnstr(source_widget,
1592 "MIC BIAS1", sizeof("MIC BIAS1"))) {
1593 mic_bias_found = 1;
1594 micb_int_reg = TOMTOM_A_MICB_1_INT_RBIAS;
1595 break;
1596 } else if (strnstr(source_widget,
1597 "MIC BIAS2", sizeof("MIC BIAS2"))) {
1598 mic_bias_found = 2;
1599 micb_int_reg = TOMTOM_A_MICB_2_INT_RBIAS;
1600 break;
1601 } else if (strnstr(source_widget,
1602 "MIC BIAS3", sizeof("MIC BIAS3"))) {
1603 mic_bias_found = 3;
1604 micb_int_reg = TOMTOM_A_MICB_3_INT_RBIAS;
1605 break;
1606 } else if (strnstr(source_widget,
1607 "MIC BIAS4", sizeof("MIC BIAS4"))) {
1608 mic_bias_found = 4;
1609 micb_int_reg = micb_4_int_reg;
1610 break;
1611 }
1612 }
1613 }
1614
1615 if (mic_bias_found) {
1616 pr_debug("%s: source mic bias = %s. sink = %s\n", __func__,
1617 card->dapm_routes[i].source,
1618 card->dapm_routes[i].sink);
1619
1620 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_INP_SEL,
1621 0x0F, tomtom_mad_input);
1622 snd_soc_update_bits(codec, TOMTOM_A_MAD_ANA_CTRL,
1623 0x07, mic_bias_found);
1624
1625 /* Setup internal micbias */
1626
1627 if (strnstr(source_widget, "Internal1", strlen(source_widget)))
1628 snd_soc_update_bits(codec,
1629 micb_int_reg,
1630 0xE0, 0xE0);
1631 else if (strnstr(source_widget, "Internal2",
1632 strlen(source_widget)))
1633 snd_soc_update_bits(codec,
1634 micb_int_reg,
1635 0x1C, 0x1C);
1636 else if (strnstr(source_widget, "Internal3",
1637 strlen(source_widget)))
1638 snd_soc_update_bits(codec,
1639 micb_int_reg,
1640 0x3, 0x3);
1641 else
1642 /*
1643 * If not internal, make sure to write the
1644 * register to default value
1645 */
1646 snd_soc_write(codec, micb_int_reg, 0x24);
1647 return 0;
1648 }
1649
1650 pr_err("%s: mic bias source not found for input = %s\n",
1651 __func__, mad_input_widget);
1652 return -EINVAL;
1653}
1654
1655static int tomtom_tx_hpf_bypass_get(struct snd_kcontrol *kcontrol,
1656 struct snd_ctl_elem_value *ucontrol)
1657{
1658 u32 tx_index;
1659
1660 tx_index = (u32)kcontrol->private_value;
1661
1662 if (tx_index > NUM_DECIMATORS) {
1663 pr_err("%s: Invalid TX decimator %d\n", __func__,
1664 tx_index);
1665 return -EINVAL;
1666 }
1667
1668 ucontrol->value.integer.value[0] =
1669 tx_hpf_work[tx_index-1].tx_hpf_bypass;
1670
1671 return 0;
1672}
1673
1674static int tomtom_tx_hpf_bypass_put(struct snd_kcontrol *kcontrol,
1675 struct snd_ctl_elem_value *ucontrol)
1676{
1677 bool tx_hpf_bypass_cfg;
1678 u32 tx_index;
1679
1680 tx_hpf_bypass_cfg = (bool)ucontrol->value.integer.value[0];
1681
1682 pr_debug("%s: tx_hpf_bypass = %d\n", __func__,
1683 tx_hpf_bypass_cfg);
1684
1685 tx_index = (u32)kcontrol->private_value;
1686
1687 if (tx_index > NUM_DECIMATORS) {
1688 pr_err("%s: Invalid TX decimator %d\n", __func__,
1689 tx_index);
1690 return -EINVAL;
1691 }
1692 if (tx_hpf_work[tx_index-1].tx_hpf_bypass != tx_hpf_bypass_cfg)
1693 tx_hpf_work[tx_index-1].tx_hpf_bypass = tx_hpf_bypass_cfg;
1694
1695 pr_debug("%s: Set TX%d HPF bypass configuration %d",
1696 __func__, tx_index,
1697 tx_hpf_work[tx_index-1].tx_hpf_bypass);
1698
1699 return 0;
1700}
1701
1702static const struct snd_kcontrol_new tomtom_snd_controls[] = {
1703
1704 SOC_SINGLE_SX_TLV("RX1 Digital Volume", TOMTOM_A_CDC_RX1_VOL_CTL_B2_CTL,
1705 0, -84, 40, digital_gain),
1706 SOC_SINGLE_SX_TLV("RX2 Digital Volume", TOMTOM_A_CDC_RX2_VOL_CTL_B2_CTL,
1707 0, -84, 40, digital_gain),
1708 SOC_SINGLE_SX_TLV("RX3 Digital Volume", TOMTOM_A_CDC_RX3_VOL_CTL_B2_CTL,
1709 0, -84, 40, digital_gain),
1710 SOC_SINGLE_SX_TLV("RX4 Digital Volume", TOMTOM_A_CDC_RX4_VOL_CTL_B2_CTL,
1711 0, -84, 40, digital_gain),
1712 SOC_SINGLE_SX_TLV("RX5 Digital Volume", TOMTOM_A_CDC_RX5_VOL_CTL_B2_CTL,
1713 0, -84, 40, digital_gain),
1714 SOC_SINGLE_SX_TLV("RX6 Digital Volume", TOMTOM_A_CDC_RX6_VOL_CTL_B2_CTL,
1715 0, -84, 40, digital_gain),
1716 SOC_SINGLE_SX_TLV("RX7 Digital Volume", TOMTOM_A_CDC_RX7_VOL_CTL_B2_CTL,
1717 0, -84, 40, digital_gain),
1718 SOC_SINGLE_SX_TLV("RX8 Digital Volume", TOMTOM_A_CDC_RX8_VOL_CTL_B2_CTL,
1719 0, -84, 40, digital_gain),
1720
1721 SOC_SINGLE_SX_TLV("DEC1 Volume", TOMTOM_A_CDC_TX1_VOL_CTL_GAIN, 0,
1722 -84, 40, digital_gain),
1723 SOC_SINGLE_SX_TLV("DEC2 Volume", TOMTOM_A_CDC_TX2_VOL_CTL_GAIN, 0,
1724 -84, 40, digital_gain),
1725 SOC_SINGLE_SX_TLV("DEC3 Volume", TOMTOM_A_CDC_TX3_VOL_CTL_GAIN, 0,
1726 -84, 40, digital_gain),
1727 SOC_SINGLE_SX_TLV("DEC4 Volume", TOMTOM_A_CDC_TX4_VOL_CTL_GAIN, 0,
1728 -84, 40, digital_gain),
1729 SOC_SINGLE_SX_TLV("DEC5 Volume", TOMTOM_A_CDC_TX5_VOL_CTL_GAIN, 0,
1730 -84, 40, digital_gain),
1731 SOC_SINGLE_SX_TLV("DEC6 Volume", TOMTOM_A_CDC_TX6_VOL_CTL_GAIN, 0,
1732 -84, 40, digital_gain),
1733 SOC_SINGLE_SX_TLV("DEC7 Volume", TOMTOM_A_CDC_TX7_VOL_CTL_GAIN, 0,
1734 -84, 40, digital_gain),
1735 SOC_SINGLE_SX_TLV("DEC8 Volume", TOMTOM_A_CDC_TX8_VOL_CTL_GAIN, 0,
1736 -84, 40, digital_gain),
1737 SOC_SINGLE_SX_TLV("DEC9 Volume", TOMTOM_A_CDC_TX9_VOL_CTL_GAIN, 0,
1738 -84, 40, digital_gain),
1739 SOC_SINGLE_SX_TLV("DEC10 Volume", TOMTOM_A_CDC_TX10_VOL_CTL_GAIN, 0,
1740 -84, 40, digital_gain),
1741
1742 SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", TOMTOM_A_CDC_IIR1_GAIN_B1_CTL, 0,
1743 -84, 40, digital_gain),
1744 SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", TOMTOM_A_CDC_IIR1_GAIN_B2_CTL, 0,
1745 -84, 40, digital_gain),
1746 SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", TOMTOM_A_CDC_IIR1_GAIN_B3_CTL, 0,
1747 -84, 40, digital_gain),
1748 SOC_SINGLE_SX_TLV("IIR1 INP4 Volume", TOMTOM_A_CDC_IIR1_GAIN_B4_CTL, 0,
1749 -84, 40, digital_gain),
1750 SOC_SINGLE_SX_TLV("IIR2 INP1 Volume", TOMTOM_A_CDC_IIR2_GAIN_B1_CTL, 0,
1751 -84, 40, digital_gain),
1752 SOC_SINGLE_SX_TLV("IIR2 INP2 Volume", TOMTOM_A_CDC_IIR2_GAIN_B2_CTL, 0,
1753 -84, 40, digital_gain),
1754 SOC_SINGLE_SX_TLV("IIR2 INP3 Volume", TOMTOM_A_CDC_IIR2_GAIN_B3_CTL, 0,
1755 -84, 40, digital_gain),
1756 SOC_SINGLE_SX_TLV("IIR2 INP4 Volume", TOMTOM_A_CDC_IIR2_GAIN_B4_CTL, 0,
1757 -84, 40, digital_gain),
1758
1759 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tomtom_get_anc_slot,
1760 tomtom_put_anc_slot),
1761 SOC_ENUM_EXT("ANC Function", tomtom_anc_func_enum, tomtom_get_anc_func,
1762 tomtom_put_anc_func),
1763
1764 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
1765 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
1766 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
1767 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
1768 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
1769 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
1770 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
1771 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
1772 SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
1773 SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
1774
1775 SOC_SINGLE_BOOL_EXT("TX1 HPF Switch", 1,
1776 tomtom_tx_hpf_bypass_get,
1777 tomtom_tx_hpf_bypass_put),
1778 SOC_SINGLE_BOOL_EXT("TX2 HPF Switch", 2,
1779 tomtom_tx_hpf_bypass_get,
1780 tomtom_tx_hpf_bypass_put),
1781 SOC_SINGLE_BOOL_EXT("TX3 HPF Switch", 3,
1782 tomtom_tx_hpf_bypass_get,
1783 tomtom_tx_hpf_bypass_put),
1784 SOC_SINGLE_BOOL_EXT("TX4 HPF Switch", 4,
1785 tomtom_tx_hpf_bypass_get,
1786 tomtom_tx_hpf_bypass_put),
1787 SOC_SINGLE_BOOL_EXT("TX5 HPF Switch", 5,
1788 tomtom_tx_hpf_bypass_get,
1789 tomtom_tx_hpf_bypass_put),
1790 SOC_SINGLE_BOOL_EXT("TX6 HPF Switch", 6,
1791 tomtom_tx_hpf_bypass_get,
1792 tomtom_tx_hpf_bypass_put),
1793 SOC_SINGLE_BOOL_EXT("TX7 HPF Switch", 7,
1794 tomtom_tx_hpf_bypass_get,
1795 tomtom_tx_hpf_bypass_put),
1796 SOC_SINGLE_BOOL_EXT("TX8 HPF Switch", 8,
1797 tomtom_tx_hpf_bypass_get,
1798 tomtom_tx_hpf_bypass_put),
1799 SOC_SINGLE_BOOL_EXT("TX9 HPF Switch", 9,
1800 tomtom_tx_hpf_bypass_get,
1801 tomtom_tx_hpf_bypass_put),
1802 SOC_SINGLE_BOOL_EXT("TX10 HPF Switch", 10,
1803 tomtom_tx_hpf_bypass_get,
1804 tomtom_tx_hpf_bypass_put),
1805
1806 SOC_SINGLE("RX1 HPF Switch", TOMTOM_A_CDC_RX1_B5_CTL, 2, 1, 0),
1807 SOC_SINGLE("RX2 HPF Switch", TOMTOM_A_CDC_RX2_B5_CTL, 2, 1, 0),
1808 SOC_SINGLE("RX3 HPF Switch", TOMTOM_A_CDC_RX3_B5_CTL, 2, 1, 0),
1809 SOC_SINGLE("RX4 HPF Switch", TOMTOM_A_CDC_RX4_B5_CTL, 2, 1, 0),
1810 SOC_SINGLE("RX5 HPF Switch", TOMTOM_A_CDC_RX5_B5_CTL, 2, 1, 0),
1811 SOC_SINGLE("RX6 HPF Switch", TOMTOM_A_CDC_RX6_B5_CTL, 2, 1, 0),
1812 SOC_SINGLE("RX7 HPF Switch", TOMTOM_A_CDC_RX7_B5_CTL, 2, 1, 0),
1813 SOC_SINGLE("RX8 HPF Switch", TOMTOM_A_CDC_RX8_B5_CTL, 2, 1, 0),
1814
1815 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
1816 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
1817 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
1818 SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
1819 SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
1820 SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
1821 SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
1822 SOC_ENUM("RX8 HPF cut off", cf_rxmix8_enum),
1823
1824 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
1825 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1826 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
1827 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1828 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
1829 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1830 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
1831 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1832 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
1833 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1834 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
1835 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1836 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
1837 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1838 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
1839 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1840 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
1841 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1842 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
1843 tomtom_get_iir_enable_audio_mixer, tomtom_put_iir_enable_audio_mixer),
1844
1845 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
1846 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1847 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
1848 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1849 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
1850 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1851 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
1852 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1853 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
1854 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1855 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
1856 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1857 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
1858 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1859 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
1860 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1861 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
1862 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1863 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
1864 tomtom_get_iir_band_audio_mixer, tomtom_put_iir_band_audio_mixer),
1865
1866 SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
1867 tomtom_get_compander, tomtom_set_compander),
1868 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
1869 tomtom_get_compander, tomtom_set_compander),
1870 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
1871 tomtom_get_compander, tomtom_set_compander),
1872
1873 SOC_ENUM_EXT("MAD Input", tomtom_conn_mad_enum,
1874 tomtom_mad_input_get, tomtom_mad_input_put),
1875
1876};
1877
1878static int tomtom_pa_gain_get(struct snd_kcontrol *kcontrol,
1879 struct snd_ctl_elem_value *ucontrol)
1880{
1881 u8 ear_pa_gain;
1882 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1883
1884 ear_pa_gain = snd_soc_read(codec, TOMTOM_A_RX_EAR_GAIN);
1885
1886 ear_pa_gain = ear_pa_gain >> 5;
1887
1888 ucontrol->value.integer.value[0] = ear_pa_gain;
1889
1890 pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
1891
1892 return 0;
1893}
1894
1895static int tomtom_pa_gain_put(struct snd_kcontrol *kcontrol,
1896 struct snd_ctl_elem_value *ucontrol)
1897{
1898 u8 ear_pa_gain;
1899 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1900
1901 pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
1902 ucontrol->value.integer.value[0]);
1903
1904 ear_pa_gain = ucontrol->value.integer.value[0] << 5;
1905
1906 snd_soc_update_bits(codec, TOMTOM_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
1907 return 0;
1908}
1909
1910static const char * const tomtom_1_x_ear_pa_gain_text[] = {
1911 "POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB",
1912 "POS_0_DB", "NEG_2P5_DB", "UNDEFINED", "NEG_12_DB"
1913};
1914
1915static const struct soc_enum tomtom_1_x_ear_pa_gain_enum =
1916 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tomtom_1_x_ear_pa_gain_text),
1917 tomtom_1_x_ear_pa_gain_text);
1918
1919static const struct snd_kcontrol_new tomtom_1_x_analog_gain_controls[] = {
1920
1921 SOC_ENUM_EXT("EAR PA Gain", tomtom_1_x_ear_pa_gain_enum,
1922 tomtom_pa_gain_get, tomtom_pa_gain_put),
1923
1924 SOC_SINGLE_TLV("HPHL Volume", TOMTOM_A_RX_HPH_L_GAIN, 0, 20, 1,
1925 line_gain),
1926 SOC_SINGLE_TLV("HPHR Volume", TOMTOM_A_RX_HPH_R_GAIN, 0, 20, 1,
1927 line_gain),
1928
1929 SOC_SINGLE_TLV("LINEOUT1 Volume", TOMTOM_A_RX_LINE_1_GAIN, 0, 20, 1,
1930 line_gain),
1931 SOC_SINGLE_TLV("LINEOUT2 Volume", TOMTOM_A_RX_LINE_2_GAIN, 0, 20, 1,
1932 line_gain),
1933 SOC_SINGLE_TLV("LINEOUT3 Volume", TOMTOM_A_RX_LINE_3_GAIN, 0, 20, 1,
1934 line_gain),
1935 SOC_SINGLE_TLV("LINEOUT4 Volume", TOMTOM_A_RX_LINE_4_GAIN, 0, 20, 1,
1936 line_gain),
1937
1938 SOC_SINGLE_TLV("SPK DRV Volume", TOMTOM_A_SPKR_DRV1_GAIN, 3, 8, 1,
1939 line_gain),
1940 SOC_SINGLE_TLV("SPK DRV2 Volume", TOMTOM_A_SPKR_DRV2_GAIN, 3, 8, 1,
1941 line_gain),
1942
1943 SOC_SINGLE_TLV("ADC1 Volume", TOMTOM_A_TX_1_GAIN, 2, 19, 0,
1944 analog_gain),
1945 SOC_SINGLE_TLV("ADC2 Volume", TOMTOM_A_TX_2_GAIN, 2, 19, 0,
1946 analog_gain),
1947 SOC_SINGLE_TLV("ADC3 Volume", TOMTOM_A_TX_3_GAIN, 2, 19, 0,
1948 analog_gain),
1949 SOC_SINGLE_TLV("ADC4 Volume", TOMTOM_A_TX_4_GAIN, 2, 19, 0,
1950 analog_gain),
1951 SOC_SINGLE_TLV("ADC5 Volume", TOMTOM_A_TX_5_GAIN, 2, 19, 0,
1952 analog_gain),
1953 SOC_SINGLE_TLV("ADC6 Volume", TOMTOM_A_TX_6_GAIN, 2, 19, 0,
1954 analog_gain),
1955};
1956
1957static int tomtom_hph_impedance_get(struct snd_kcontrol *kcontrol,
1958 struct snd_ctl_elem_value *ucontrol)
1959{
1960 uint32_t zl, zr;
1961 bool hphr;
1962 struct soc_multi_mixer_control *mc;
1963 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1964 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
1965
1966 mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
1967
1968 hphr = mc->shift;
1969 wcd9xxx_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
1970 pr_debug("%s: zl %u, zr %u\n", __func__, zl, zr);
1971 ucontrol->value.integer.value[0] = hphr ? zr : zl;
1972
1973 return 0;
1974}
1975
1976static const struct snd_kcontrol_new impedance_detect_controls[] = {
1977 SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
1978 tomtom_hph_impedance_get, NULL),
1979 SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
1980 tomtom_hph_impedance_get, NULL),
1981};
1982
1983static int tomtom_get_hph_type(struct snd_kcontrol *kcontrol,
1984 struct snd_ctl_elem_value *ucontrol)
1985{
1986 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
1987 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
1988 struct wcd9xxx_mbhc *mbhc;
1989
1990 if (!priv) {
1991 pr_debug("%s: wcd9330 private data is NULL\n", __func__);
1992 return 0;
1993 }
1994
1995 mbhc = &priv->mbhc;
1996 if (!mbhc) {
1997 pr_debug("%s: mbhc not initialized\n", __func__);
1998 return 0;
1999 }
2000
2001 ucontrol->value.integer.value[0] = (u32) mbhc->hph_type;
2002 pr_debug("%s: hph_type = %u\n", __func__, mbhc->hph_type);
2003
2004 return 0;
2005}
2006
2007static const struct snd_kcontrol_new hph_type_detect_controls[] = {
2008 SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0,
2009 tomtom_get_hph_type, NULL),
2010};
2011
2012static const char * const rx_mix1_text[] = {
2013 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
2014 "RX5", "RX6", "RX7"
2015};
2016
2017static const char * const rx8_mix1_text[] = {
2018 "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
2019 "RX5", "RX6", "RX7", "RX8"
2020};
2021
2022static const char * const rx_mix2_text[] = {
2023 "ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
2024};
2025
2026static const char * const rx_rdac5_text[] = {
2027 "DEM4", "DEM3_INV"
2028};
2029
2030static const char * const rx_rdac7_text[] = {
2031 "DEM6", "DEM5_INV"
2032};
2033
2034static const char * const mad_sel_text[] = {
2035 "SPE", "MSM"
2036};
2037
2038static const char * const sb_tx1_mux_text[] = {
2039 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2040 "DEC1", "RMIX8"
2041};
2042
2043static const char * const sb_tx2_mux_text[] = {
2044 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2045 "DEC2", "RMIX8"
2046};
2047
2048static const char * const sb_tx3_mux_text[] = {
2049 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2050 "DEC3", "RMIX8"
2051};
2052
2053static const char * const sb_tx4_mux_text[] = {
2054 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2055 "DEC4", "RMIX8"
2056};
2057
2058static const char * const sb_tx5_mux_text[] = {
2059 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2060 "DEC5", "RMIX8"
2061};
2062
2063static const char * const sb_tx6_mux_text[] = {
2064 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2065 "DEC6", "RMIX8"
2066};
2067
2068static const char * const sb_tx7_to_tx10_mux_text[] = {
2069 "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
2070 "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
2071 "DEC9", "DEC10"
2072};
2073
2074static const char * const dec1_mux_text[] = {
2075 "ZERO", "DMIC1", "ADC6",
2076};
2077
2078static const char * const dec2_mux_text[] = {
2079 "ZERO", "DMIC2", "ADC5",
2080};
2081
2082static const char * const dec3_mux_text[] = {
2083 "ZERO", "DMIC3", "ADC4",
2084};
2085
2086static const char * const dec4_mux_text[] = {
2087 "ZERO", "DMIC4", "ADC3",
2088};
2089
2090static const char * const dec5_mux_text[] = {
2091 "ZERO", "DMIC5", "ADC2",
2092};
2093
2094static const char * const dec6_mux_text[] = {
2095 "ZERO", "DMIC6", "ADC1",
2096};
2097
2098static const char * const dec7_mux_text[] = {
2099 "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
2100};
2101
2102static const char * const dec8_mux_text[] = {
2103 "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5", "ANC1_FB", "ANC2_FB",
2104};
2105
2106static const char * const dec9_mux_text[] = {
2107 "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
2108};
2109
2110static const char * const dec10_mux_text[] = {
2111 "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
2112};
2113
2114static const char * const anc_mux_text[] = {
2115 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
2116 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
2117};
2118
2119static const char * const anc1_fb_mux_text[] = {
2120 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
2121};
2122
2123static const char * const iir_inp1_text[] = {
2124 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
2125 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
2126};
2127
2128static const char * const iir_inp2_text[] = {
2129 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
2130 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
2131};
2132
2133static const char * const iir_inp3_text[] = {
2134 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
2135 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
2136};
2137
2138static const char * const iir_inp4_text[] = {
2139 "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
2140 "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
2141};
2142
2143static const struct soc_enum rx_mix1_inp1_chain_enum =
2144 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
2145
2146static const struct soc_enum rx_mix1_inp2_chain_enum =
2147 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
2148
2149static const struct soc_enum rx_mix1_inp3_chain_enum =
2150 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
2151
2152static const struct soc_enum rx2_mix1_inp1_chain_enum =
2153 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
2154
2155static const struct soc_enum rx2_mix1_inp2_chain_enum =
2156 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
2157
2158static const struct soc_enum rx3_mix1_inp1_chain_enum =
2159 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
2160
2161static const struct soc_enum rx3_mix1_inp2_chain_enum =
2162 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
2163
2164static const struct soc_enum rx4_mix1_inp1_chain_enum =
2165 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
2166
2167static const struct soc_enum rx4_mix1_inp2_chain_enum =
2168 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
2169
2170static const struct soc_enum rx5_mix1_inp1_chain_enum =
2171 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
2172
2173static const struct soc_enum rx5_mix1_inp2_chain_enum =
2174 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
2175
2176static const struct soc_enum rx6_mix1_inp1_chain_enum =
2177 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
2178
2179static const struct soc_enum rx6_mix1_inp2_chain_enum =
2180 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
2181
2182static const struct soc_enum rx7_mix1_inp1_chain_enum =
2183 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
2184
2185static const struct soc_enum rx7_mix1_inp2_chain_enum =
2186 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
2187
2188static const struct soc_enum rx8_mix1_inp1_chain_enum =
2189 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX8_B1_CTL, 0, 11, rx8_mix1_text);
2190
2191static const struct soc_enum rx8_mix1_inp2_chain_enum =
2192 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX8_B1_CTL, 4, 11, rx8_mix1_text);
2193
2194static const struct soc_enum rx1_mix2_inp1_chain_enum =
2195 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
2196
2197static const struct soc_enum rx1_mix2_inp2_chain_enum =
2198 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
2199
2200static const struct soc_enum rx2_mix2_inp1_chain_enum =
2201 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
2202
2203static const struct soc_enum rx2_mix2_inp2_chain_enum =
2204 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
2205
2206static const struct soc_enum rx7_mix2_inp1_chain_enum =
2207 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
2208
2209static const struct soc_enum rx7_mix2_inp2_chain_enum =
2210 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
2211
2212static const struct soc_enum rx_rdac5_enum =
2213 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
2214
2215static const struct soc_enum rx_rdac7_enum =
2216 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
2217
2218static const struct soc_enum mad_sel_enum =
2219 SOC_ENUM_SINGLE(TOMTOM_A_SVASS_CFG, 0, 2, mad_sel_text);
2220
2221static const struct soc_enum sb_tx1_mux_enum =
2222 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B1_CTL, 0, 10, sb_tx1_mux_text);
2223
2224static const struct soc_enum sb_tx2_mux_enum =
2225 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B2_CTL, 0, 10, sb_tx2_mux_text);
2226
2227static const struct soc_enum sb_tx3_mux_enum =
2228 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B3_CTL, 0, 10, sb_tx3_mux_text);
2229
2230static const struct soc_enum sb_tx4_mux_enum =
2231 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B4_CTL, 0, 10, sb_tx4_mux_text);
2232
2233static const struct soc_enum sb_tx5_mux_enum =
2234 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B5_CTL, 0, 10, sb_tx5_mux_text);
2235
2236static const struct soc_enum sb_tx6_mux_enum =
2237 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B6_CTL, 0, 10, sb_tx6_mux_text);
2238
2239static const struct soc_enum sb_tx7_mux_enum =
2240 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
2241 sb_tx7_to_tx10_mux_text);
2242
2243static const struct soc_enum sb_tx8_mux_enum =
2244 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
2245 sb_tx7_to_tx10_mux_text);
2246
2247static const struct soc_enum sb_tx9_mux_enum =
2248 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
2249 sb_tx7_to_tx10_mux_text);
2250
2251static const struct soc_enum sb_tx10_mux_enum =
2252 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
2253 sb_tx7_to_tx10_mux_text);
2254
2255static const struct soc_enum dec1_mux_enum =
2256 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
2257
2258static const struct soc_enum dec2_mux_enum =
2259 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
2260
2261static const struct soc_enum dec3_mux_enum =
2262 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
2263
2264static const struct soc_enum dec4_mux_enum =
2265 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
2266
2267static const struct soc_enum dec5_mux_enum =
2268 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
2269
2270static const struct soc_enum dec6_mux_enum =
2271 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
2272
2273static const struct soc_enum dec7_mux_enum =
2274 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
2275
2276static const struct soc_enum dec8_mux_enum =
2277 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
2278
2279static const struct soc_enum dec9_mux_enum =
2280 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
2281
2282static const struct soc_enum dec10_mux_enum =
2283 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
2284
2285static const struct soc_enum anc1_mux_enum =
2286 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_ANC_B1_CTL, 0, 15, anc_mux_text);
2287
2288static const struct soc_enum anc2_mux_enum =
2289 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_ANC_B1_CTL, 4, 15, anc_mux_text);
2290
2291static const struct soc_enum anc1_fb_mux_enum =
2292 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
2293
2294static const struct soc_enum iir1_inp1_mux_enum =
2295 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
2296
2297static const struct soc_enum iir2_inp1_mux_enum =
2298 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
2299
2300static const struct soc_enum iir1_inp2_mux_enum =
2301 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ1_B2_CTL, 0, 18, iir_inp2_text);
2302
2303static const struct soc_enum iir2_inp2_mux_enum =
2304 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ2_B2_CTL, 0, 18, iir_inp2_text);
2305
2306static const struct soc_enum iir1_inp3_mux_enum =
2307 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ1_B3_CTL, 0, 18, iir_inp3_text);
2308
2309static const struct soc_enum iir2_inp3_mux_enum =
2310 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ2_B3_CTL, 0, 18, iir_inp3_text);
2311
2312static const struct soc_enum iir1_inp4_mux_enum =
2313 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ1_B4_CTL, 0, 18, iir_inp4_text);
2314
2315static const struct soc_enum iir2_inp4_mux_enum =
2316 SOC_ENUM_SINGLE(TOMTOM_A_CDC_CONN_EQ2_B4_CTL, 0, 18, iir_inp4_text);
2317
2318static const struct snd_kcontrol_new rx_mix1_inp1_mux =
2319 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
2320
2321static const struct snd_kcontrol_new rx_mix1_inp2_mux =
2322 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
2323
2324static const struct snd_kcontrol_new rx_mix1_inp3_mux =
2325 SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
2326
2327static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
2328 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
2329
2330static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
2331 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
2332
2333static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
2334 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
2335
2336static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
2337 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
2338
2339static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
2340 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
2341
2342static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
2343 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
2344
2345static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
2346 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
2347
2348static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
2349 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
2350
2351static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
2352 SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
2353
2354static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
2355 SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
2356
2357static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
2358 SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
2359
2360static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
2361 SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
2362
2363static const struct snd_kcontrol_new rx8_mix1_inp1_mux =
2364 SOC_DAPM_ENUM("RX8 MIX1 INP1 Mux", rx8_mix1_inp1_chain_enum);
2365
2366static const struct snd_kcontrol_new rx8_mix1_inp2_mux =
2367 SOC_DAPM_ENUM("RX8 MIX1 INP2 Mux", rx8_mix1_inp2_chain_enum);
2368
2369static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
2370 SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
2371
2372static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
2373 SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
2374
2375static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
2376 SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
2377
2378static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
2379 SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
2380
2381static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
2382 SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
2383
2384static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
2385 SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
2386
2387static const struct snd_kcontrol_new rx_dac5_mux =
2388 SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
2389
2390static const struct snd_kcontrol_new rx_dac7_mux =
2391 SOC_DAPM_ENUM("RDAC7 MUX Mux", rx_rdac7_enum);
2392
2393static const struct snd_kcontrol_new mad_sel_mux =
2394 SOC_DAPM_ENUM("MAD_SEL MUX Mux", mad_sel_enum);
2395
2396static const struct snd_kcontrol_new sb_tx1_mux =
2397 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
2398
2399static const struct snd_kcontrol_new sb_tx2_mux =
2400 SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
2401
2402static const struct snd_kcontrol_new sb_tx3_mux =
2403 SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
2404
2405static const struct snd_kcontrol_new sb_tx4_mux =
2406 SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
2407
2408static const struct snd_kcontrol_new sb_tx5_mux =
2409 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
2410
2411static const struct snd_kcontrol_new sb_tx6_mux =
2412 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
2413
2414static const struct snd_kcontrol_new sb_tx7_mux =
2415 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
2416
2417static const struct snd_kcontrol_new sb_tx8_mux =
2418 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
2419
2420static const struct snd_kcontrol_new sb_tx9_mux =
2421 SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
2422
2423static const struct snd_kcontrol_new sb_tx10_mux =
2424 SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
2425
2426
2427static int wcd9330_put_dec_enum(struct snd_kcontrol *kcontrol,
2428 struct snd_ctl_elem_value *ucontrol)
2429{
2430 struct snd_soc_dapm_widget_list *wlist =
2431 dapm_kcontrol_get_wlist(kcontrol);
2432 struct snd_soc_dapm_widget *w = wlist->widgets[0];
2433 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2434 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2435 unsigned int dec_mux, decimator;
2436 char *dec_name = NULL;
2437 char *widget_name = NULL;
2438 char *temp;
2439 u16 tx_mux_ctl_reg;
2440 u8 adc_dmic_sel = 0x0;
2441 int ret = 0;
2442 char *dec;
2443
2444 if (ucontrol->value.enumerated.item[0] >= e->items)
2445 return -EINVAL;
2446
2447 dec_mux = ucontrol->value.enumerated.item[0];
2448
2449 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
2450 if (!widget_name)
2451 return -ENOMEM;
2452 temp = widget_name;
2453
2454 dec_name = strsep(&widget_name, " ");
2455 widget_name = temp;
2456 if (!dec_name) {
2457 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
2458 ret = -EINVAL;
2459 goto out;
2460 }
2461 dec = strpbrk(dec_name, "123456789");
2462 if (!dec) {
2463 dev_err(w->dapm->dev, "%s: decimator index not found\n",
2464 __func__);
2465 ret = -EINVAL;
2466 goto out;
2467 }
2468 ret = kstrtouint(dec, 10, &decimator);
2469 if (ret < 0) {
2470 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
2471 ret = -EINVAL;
2472 goto out;
2473 }
2474
2475 dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
2476 , __func__, w->name, decimator, dec_mux);
2477
2478
2479 switch (decimator) {
2480 case 1:
2481 case 2:
2482 case 3:
2483 case 4:
2484 case 5:
2485 case 6:
2486 if (dec_mux == 1)
2487 adc_dmic_sel = 0x1;
2488 else
2489 adc_dmic_sel = 0x0;
2490 break;
2491 case 7:
2492 case 8:
2493 case 9:
2494 case 10:
2495 if ((dec_mux == 1) || (dec_mux == 2))
2496 adc_dmic_sel = 0x1;
2497 else
2498 adc_dmic_sel = 0x0;
2499 break;
2500 default:
2501 pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
2502 ret = -EINVAL;
2503 goto out;
2504 }
2505
2506 tx_mux_ctl_reg = TOMTOM_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
2507
2508 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
2509
2510 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
2511
2512out:
2513 kfree(widget_name);
2514 return ret;
2515}
2516
2517#define WCD9330_DEC_ENUM(xname, xenum) \
2518{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
2519 .info = snd_soc_info_enum_double, \
2520 .get = snd_soc_dapm_get_enum_double, \
2521 .put = wcd9330_put_dec_enum, \
2522 .private_value = (unsigned long)&xenum }
2523
2524static const struct snd_kcontrol_new dec1_mux =
2525 WCD9330_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
2526
2527static const struct snd_kcontrol_new dec2_mux =
2528 WCD9330_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
2529
2530static const struct snd_kcontrol_new dec3_mux =
2531 WCD9330_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
2532
2533static const struct snd_kcontrol_new dec4_mux =
2534 WCD9330_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
2535
2536static const struct snd_kcontrol_new dec5_mux =
2537 WCD9330_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
2538
2539static const struct snd_kcontrol_new dec6_mux =
2540 WCD9330_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
2541
2542static const struct snd_kcontrol_new dec7_mux =
2543 WCD9330_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
2544
2545static const struct snd_kcontrol_new dec8_mux =
2546 WCD9330_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
2547
2548static const struct snd_kcontrol_new dec9_mux =
2549 WCD9330_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
2550
2551static const struct snd_kcontrol_new dec10_mux =
2552 WCD9330_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
2553
2554static const struct snd_kcontrol_new iir1_inp1_mux =
2555 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
2556
2557static const struct snd_kcontrol_new iir2_inp1_mux =
2558 SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
2559
2560static const struct snd_kcontrol_new iir1_inp2_mux =
2561 SOC_DAPM_ENUM("IIR1 INP2 Mux", iir1_inp2_mux_enum);
2562
2563static const struct snd_kcontrol_new iir2_inp2_mux =
2564 SOC_DAPM_ENUM("IIR2 INP2 Mux", iir2_inp2_mux_enum);
2565
2566static const struct snd_kcontrol_new iir1_inp3_mux =
2567 SOC_DAPM_ENUM("IIR1 INP3 Mux", iir1_inp3_mux_enum);
2568
2569static const struct snd_kcontrol_new iir2_inp3_mux =
2570 SOC_DAPM_ENUM("IIR2 INP3 Mux", iir2_inp3_mux_enum);
2571
2572static const struct snd_kcontrol_new iir1_inp4_mux =
2573 SOC_DAPM_ENUM("IIR1 INP4 Mux", iir1_inp4_mux_enum);
2574
2575static const struct snd_kcontrol_new iir2_inp4_mux =
2576 SOC_DAPM_ENUM("IIR2 INP4 Mux", iir2_inp4_mux_enum);
2577
2578static const struct snd_kcontrol_new anc1_mux =
2579 SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
2580
2581static const struct snd_kcontrol_new anc2_mux =
2582 SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
2583
2584static const struct snd_kcontrol_new anc1_fb_mux =
2585 SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
2586
2587static const struct snd_kcontrol_new dac1_switch[] = {
2588 SOC_DAPM_SINGLE("Switch", TOMTOM_A_RX_EAR_EN, 5, 1, 0)
2589};
2590static const struct snd_kcontrol_new hphl_switch[] = {
2591 SOC_DAPM_SINGLE("Switch", TOMTOM_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
2592};
2593
2594static const struct snd_kcontrol_new hphl_pa_mix[] = {
2595 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2596 7, 1, 0),
2597};
2598
2599static const struct snd_kcontrol_new hphr_pa_mix[] = {
2600 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2601 6, 1, 0),
2602};
2603
2604static const struct snd_kcontrol_new ear_pa_mix[] = {
2605 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2606 5, 1, 0),
2607};
2608static const struct snd_kcontrol_new lineout1_pa_mix[] = {
2609 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2610 4, 1, 0),
2611};
2612
2613static const struct snd_kcontrol_new lineout2_pa_mix[] = {
2614 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2615 3, 1, 0),
2616};
2617
2618static const struct snd_kcontrol_new lineout3_pa_mix[] = {
2619 SOC_DAPM_SINGLE("AUX_PGA_L Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2620 2, 1, 0),
2621};
2622
2623static const struct snd_kcontrol_new lineout4_pa_mix[] = {
2624 SOC_DAPM_SINGLE("AUX_PGA_R Switch", TOMTOM_A_RX_PA_AUX_IN_CONN,
2625 1, 1, 0),
2626};
2627
2628static const struct snd_kcontrol_new lineout3_ground_switch =
2629 SOC_DAPM_SINGLE("Switch", TOMTOM_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
2630
2631static const struct snd_kcontrol_new lineout4_ground_switch =
2632 SOC_DAPM_SINGLE("Switch", TOMTOM_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
2633
2634static const struct snd_kcontrol_new aif4_mad_switch =
2635 SOC_DAPM_SINGLE("Switch", TOMTOM_A_SVASS_CLKRST_CTL, 0, 1, 0);
2636
2637static const struct snd_kcontrol_new aif4_vi_switch =
2638 SOC_DAPM_SINGLE("Switch", TOMTOM_A_SPKR1_PROT_EN, 3, 1, 0);
2639
2640/* virtual port entries */
2641static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
2642 struct snd_ctl_elem_value *ucontrol)
2643{
2644 struct snd_soc_dapm_widget_list *wlist =
2645 dapm_kcontrol_get_wlist(kcontrol);
2646 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2647 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2648 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
2649
2650 ucontrol->value.integer.value[0] = tomtom_p->tx_port_value;
2651 return 0;
2652}
2653
2654static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
2655 struct snd_ctl_elem_value *ucontrol)
2656{
2657 struct snd_soc_dapm_widget_list *wlist =
2658 dapm_kcontrol_get_wlist(kcontrol);
2659 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2660 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2661 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
2662 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2663 struct snd_soc_dapm_update *update = NULL;
2664 struct soc_multi_mixer_control *mixer =
2665 ((struct soc_multi_mixer_control *)kcontrol->private_value);
2666 u32 dai_id = widget->shift;
2667 u32 port_id = mixer->shift;
2668 u32 enable = ucontrol->value.integer.value[0];
2669 u32 vtable = vport_check_table[dai_id];
2670
2671
2672 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2673 widget->name, ucontrol->id.name, tomtom_p->tx_port_value,
2674 widget->shift, ucontrol->value.integer.value[0]);
2675
2676 mutex_lock(&tomtom_p->codec_mutex);
2677
2678 if (tomtom_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
2679 if (dai_id != AIF1_CAP) {
2680 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2681 __func__);
2682 mutex_unlock(&tomtom_p->codec_mutex);
2683 return -EINVAL;
2684 }
2685 }
2686 switch (dai_id) {
2687 case AIF1_CAP:
2688 case AIF2_CAP:
2689 case AIF3_CAP:
2690 /* only add to the list if value not set
2691 */
2692 if (enable && !(tomtom_p->tx_port_value & 1 << port_id)) {
2693
2694 if (tomtom_p->intf_type ==
2695 WCD9XXX_INTERFACE_TYPE_SLIMBUS)
2696 vtable = vport_check_table[dai_id];
2697 if (tomtom_p->intf_type ==
2698 WCD9XXX_INTERFACE_TYPE_I2C)
2699 vtable = vport_i2s_check_table[dai_id];
2700
2701 if (wcd9xxx_tx_vport_validation(
2702 vtable,
2703 port_id,
2704 tomtom_p->dai, NUM_CODEC_DAIS)) {
2705 dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
2706 __func__, port_id + 1);
2707 mutex_unlock(&tomtom_p->codec_mutex);
2708 return 0;
2709 }
2710 tomtom_p->tx_port_value |= 1 << port_id;
2711 list_add_tail(&core->tx_chs[port_id].list,
2712 &tomtom_p->dai[dai_id].wcd9xxx_ch_list
2713 );
2714 } else if (!enable && (tomtom_p->tx_port_value &
2715 1 << port_id)) {
2716 tomtom_p->tx_port_value &= ~(1 << port_id);
2717 list_del_init(&core->tx_chs[port_id].list);
2718 } else {
2719 if (enable)
2720 dev_dbg(codec->dev, "%s: TX%u port is used by\n"
2721 "this virtual port\n",
2722 __func__, port_id + 1);
2723 else
2724 dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
2725 "this virtual port\n",
2726 __func__, port_id + 1);
2727 /* avoid update power function */
2728 mutex_unlock(&tomtom_p->codec_mutex);
2729 return 0;
2730 }
2731 break;
2732 default:
2733 pr_err("Unknown AIF %d\n", dai_id);
2734 mutex_unlock(&tomtom_p->codec_mutex);
2735 return -EINVAL;
2736 }
2737 pr_debug("%s: name %s sname %s updated value %u shift %d\n", __func__,
2738 widget->name, widget->sname, tomtom_p->tx_port_value,
2739 widget->shift);
2740
2741 mutex_unlock(&tomtom_p->codec_mutex);
2742 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
2743
2744 return 0;
2745}
2746
2747static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
2748 struct snd_ctl_elem_value *ucontrol)
2749{
2750 struct snd_soc_dapm_widget_list *wlist =
2751 dapm_kcontrol_get_wlist(kcontrol);
2752 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2753 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2754 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
2755
2756 ucontrol->value.enumerated.item[0] = tomtom_p->rx_port_value;
2757 return 0;
2758}
2759
2760static const char *const slim_rx_mux_text[] = {
2761 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB"
2762};
2763
2764static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
2765 struct snd_ctl_elem_value *ucontrol)
2766{
2767 struct snd_soc_dapm_widget_list *wlist =
2768 dapm_kcontrol_get_wlist(kcontrol);
2769 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2770 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
2771 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
2772 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
2773 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2774 struct snd_soc_dapm_update *update = NULL;
2775 u32 port_id = widget->shift;
2776
2777 pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
2778 widget->name, ucontrol->id.name, tomtom_p->rx_port_value,
2779 widget->shift, ucontrol->value.integer.value[0]);
2780
2781 tomtom_p->rx_port_value = ucontrol->value.enumerated.item[0];
2782
2783 mutex_lock(&tomtom_p->codec_mutex);
2784
2785 if (tomtom_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
2786 if (tomtom_p->rx_port_value > 2) {
2787 dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
2788 __func__);
2789 goto err;
2790 }
2791 }
2792 /* value need to match the Virtual port and AIF number
2793 */
2794 switch (tomtom_p->rx_port_value) {
2795 case 0:
2796 list_del_init(&core->rx_chs[port_id].list);
2797 break;
2798 case 1:
2799 if (wcd9xxx_rx_vport_validation(port_id +
2800 TOMTOM_RX_PORT_START_NUMBER,
2801 &tomtom_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
2802 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2803 __func__, port_id + 1);
2804 goto rtn;
2805 }
2806 list_add_tail(&core->rx_chs[port_id].list,
2807 &tomtom_p->dai[AIF1_PB].wcd9xxx_ch_list);
2808 break;
2809 case 2:
2810 if (wcd9xxx_rx_vport_validation(port_id +
2811 TOMTOM_RX_PORT_START_NUMBER,
2812 &tomtom_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
2813 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2814 __func__, port_id + 1);
2815 goto rtn;
2816 }
2817 list_add_tail(&core->rx_chs[port_id].list,
2818 &tomtom_p->dai[AIF2_PB].wcd9xxx_ch_list);
2819 break;
2820 case 3:
2821 if (wcd9xxx_rx_vport_validation(port_id +
2822 TOMTOM_RX_PORT_START_NUMBER,
2823 &tomtom_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
2824 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
2825 __func__, port_id + 1);
2826 goto rtn;
2827 }
2828 list_add_tail(&core->rx_chs[port_id].list,
2829 &tomtom_p->dai[AIF3_PB].wcd9xxx_ch_list);
2830 break;
2831 default:
2832 pr_err("Unknown AIF %d\n", tomtom_p->rx_port_value);
2833 goto err;
2834 }
2835rtn:
2836 mutex_unlock(&tomtom_p->codec_mutex);
2837 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
2838 tomtom_p->rx_port_value, e, update);
2839
2840 return 0;
2841err:
2842 mutex_unlock(&tomtom_p->codec_mutex);
2843 return -EINVAL;
2844}
2845
2846static const struct soc_enum slim_rx_mux_enum =
2847 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
2848
2849static const struct snd_kcontrol_new slim_rx_mux[TOMTOM_RX_MAX] = {
2850 SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
2851 slim_rx_mux_get, slim_rx_mux_put),
2852 SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
2853 slim_rx_mux_get, slim_rx_mux_put),
2854 SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
2855 slim_rx_mux_get, slim_rx_mux_put),
2856 SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
2857 slim_rx_mux_get, slim_rx_mux_put),
2858 SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
2859 slim_rx_mux_get, slim_rx_mux_put),
2860 SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
2861 slim_rx_mux_get, slim_rx_mux_put),
2862 SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
2863 slim_rx_mux_get, slim_rx_mux_put),
2864 SOC_DAPM_ENUM_EXT("SLIM RX8 Mux", slim_rx_mux_enum,
2865 slim_rx_mux_get, slim_rx_mux_put),
2866};
2867
2868static const struct snd_kcontrol_new aif1_cap_mixer[] = {
2869 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TOMTOM_TX1, 1, 0,
2870 slim_tx_mixer_get, slim_tx_mixer_put),
2871 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TOMTOM_TX2, 1, 0,
2872 slim_tx_mixer_get, slim_tx_mixer_put),
2873 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TOMTOM_TX3, 1, 0,
2874 slim_tx_mixer_get, slim_tx_mixer_put),
2875 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TOMTOM_TX4, 1, 0,
2876 slim_tx_mixer_get, slim_tx_mixer_put),
2877 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TOMTOM_TX5, 1, 0,
2878 slim_tx_mixer_get, slim_tx_mixer_put),
2879 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TOMTOM_TX6, 1, 0,
2880 slim_tx_mixer_get, slim_tx_mixer_put),
2881 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TOMTOM_TX7, 1, 0,
2882 slim_tx_mixer_get, slim_tx_mixer_put),
2883 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TOMTOM_TX8, 1, 0,
2884 slim_tx_mixer_get, slim_tx_mixer_put),
2885 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TOMTOM_TX9, 1, 0,
2886 slim_tx_mixer_get, slim_tx_mixer_put),
2887 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TOMTOM_TX10, 1, 0,
2888 slim_tx_mixer_get, slim_tx_mixer_put),
2889};
2890
2891static const struct snd_kcontrol_new aif2_cap_mixer[] = {
2892 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TOMTOM_TX1, 1, 0,
2893 slim_tx_mixer_get, slim_tx_mixer_put),
2894 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TOMTOM_TX2, 1, 0,
2895 slim_tx_mixer_get, slim_tx_mixer_put),
2896 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TOMTOM_TX3, 1, 0,
2897 slim_tx_mixer_get, slim_tx_mixer_put),
2898 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TOMTOM_TX4, 1, 0,
2899 slim_tx_mixer_get, slim_tx_mixer_put),
2900 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TOMTOM_TX5, 1, 0,
2901 slim_tx_mixer_get, slim_tx_mixer_put),
2902 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TOMTOM_TX6, 1, 0,
2903 slim_tx_mixer_get, slim_tx_mixer_put),
2904 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TOMTOM_TX7, 1, 0,
2905 slim_tx_mixer_get, slim_tx_mixer_put),
2906 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TOMTOM_TX8, 1, 0,
2907 slim_tx_mixer_get, slim_tx_mixer_put),
2908 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TOMTOM_TX9, 1, 0,
2909 slim_tx_mixer_get, slim_tx_mixer_put),
2910 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TOMTOM_TX10, 1, 0,
2911 slim_tx_mixer_get, slim_tx_mixer_put),
2912};
2913
2914static const struct snd_kcontrol_new aif3_cap_mixer[] = {
2915 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TOMTOM_TX1, 1, 0,
2916 slim_tx_mixer_get, slim_tx_mixer_put),
2917 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TOMTOM_TX2, 1, 0,
2918 slim_tx_mixer_get, slim_tx_mixer_put),
2919 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TOMTOM_TX3, 1, 0,
2920 slim_tx_mixer_get, slim_tx_mixer_put),
2921 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TOMTOM_TX4, 1, 0,
2922 slim_tx_mixer_get, slim_tx_mixer_put),
2923 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TOMTOM_TX5, 1, 0,
2924 slim_tx_mixer_get, slim_tx_mixer_put),
2925 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, TOMTOM_TX6, 1, 0,
2926 slim_tx_mixer_get, slim_tx_mixer_put),
2927 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, TOMTOM_TX7, 1, 0,
2928 slim_tx_mixer_get, slim_tx_mixer_put),
2929 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, TOMTOM_TX8, 1, 0,
2930 slim_tx_mixer_get, slim_tx_mixer_put),
2931 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, TOMTOM_TX9, 1, 0,
2932 slim_tx_mixer_get, slim_tx_mixer_put),
2933 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, TOMTOM_TX10, 1, 0,
2934 slim_tx_mixer_get, slim_tx_mixer_put),
2935};
2936
2937static void tomtom_codec_enable_adc_block(struct snd_soc_codec *codec,
2938 int enable)
2939{
2940 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
2941
2942 pr_debug("%s %d\n", __func__, enable);
2943
2944 if (enable) {
2945 tomtom->adc_count++;
2946 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
2947 0x2, 0x2);
2948 } else {
2949 tomtom->adc_count--;
2950 if (!tomtom->adc_count)
2951 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
2952 0x2, 0x0);
2953 }
2954}
2955
2956static int tomtom_codec_enable_adc(struct snd_soc_dapm_widget *w,
2957 struct snd_kcontrol *kcontrol, int event)
2958{
2959 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2960 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
2961 u16 adc_reg;
2962 u16 tx_fe_clkdiv_reg;
2963 u8 tx_fe_clkdiv_mask;
2964 u8 init_bit_shift;
2965 u8 bit_pos;
2966
2967 pr_debug("%s %d\n", __func__, event);
2968
2969 switch (w->reg) {
2970 case TOMTOM_A_TX_1_GAIN:
2971 adc_reg = TOMTOM_A_TX_1_2_TEST_CTL;
2972 tx_fe_clkdiv_reg = TOMTOM_A_TX_1_2_TXFE_CLKDIV;
2973 tx_fe_clkdiv_mask = 0x0F;
2974 init_bit_shift = 7;
2975 bit_pos = ADC1_TXFE;
2976 break;
2977 case TOMTOM_A_TX_2_GAIN:
2978 adc_reg = TOMTOM_A_TX_1_2_TEST_CTL;
2979 tx_fe_clkdiv_reg = TOMTOM_A_TX_1_2_TXFE_CLKDIV;
2980 tx_fe_clkdiv_mask = 0xF0;
2981 init_bit_shift = 6;
2982 bit_pos = ADC2_TXFE;
2983 break;
2984 case TOMTOM_A_TX_3_GAIN:
2985 adc_reg = TOMTOM_A_TX_3_4_TEST_CTL;
2986 init_bit_shift = 7;
2987 tx_fe_clkdiv_reg = TOMTOM_A_TX_3_4_TXFE_CKDIV;
2988 tx_fe_clkdiv_mask = 0x0F;
2989 bit_pos = ADC3_TXFE;
2990 break;
2991 case TOMTOM_A_TX_4_GAIN:
2992 adc_reg = TOMTOM_A_TX_3_4_TEST_CTL;
2993 init_bit_shift = 6;
2994 tx_fe_clkdiv_reg = TOMTOM_A_TX_3_4_TXFE_CKDIV;
2995 tx_fe_clkdiv_mask = 0xF0;
2996 bit_pos = ADC4_TXFE;
2997 break;
2998 case TOMTOM_A_TX_5_GAIN:
2999 adc_reg = TOMTOM_A_TX_5_6_TEST_CTL;
3000 init_bit_shift = 7;
3001 tx_fe_clkdiv_reg = TOMTOM_A_TX_5_6_TXFE_CKDIV;
3002 tx_fe_clkdiv_mask = 0x0F;
3003 bit_pos = ADC5_TXFE;
3004 break;
3005 case TOMTOM_A_TX_6_GAIN:
3006 adc_reg = TOMTOM_A_TX_5_6_TEST_CTL;
3007 init_bit_shift = 6;
3008 tx_fe_clkdiv_reg = TOMTOM_A_TX_5_6_TXFE_CKDIV;
3009 tx_fe_clkdiv_mask = 0xF0;
3010 bit_pos = ADC6_TXFE;
3011 break;
3012 default:
3013 pr_err("%s: Error, invalid adc register\n", __func__);
3014 return -EINVAL;
3015 }
3016
3017 switch (event) {
3018 case SND_SOC_DAPM_PRE_PMU:
3019 snd_soc_update_bits(codec, tx_fe_clkdiv_reg, tx_fe_clkdiv_mask,
3020 0x0);
3021 set_bit(bit_pos, &priv->status_mask);
3022 tomtom_codec_enable_adc_block(codec, 1);
3023 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
3024 1 << init_bit_shift);
3025 break;
3026 case SND_SOC_DAPM_POST_PMU:
3027 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
3028 break;
3029 case SND_SOC_DAPM_POST_PMD:
3030 tomtom_codec_enable_adc_block(codec, 0);
3031 break;
3032 }
3033 return 0;
3034}
3035
3036static int tomtom_codec_ext_clk_en(struct snd_soc_codec *codec,
3037 int enable, bool dapm)
3038{
3039 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3040
3041 if (!tomtom->codec_ext_clk_en_cb) {
3042 dev_err(codec->dev,
3043 "%s: Invalid ext_clk_callback\n",
3044 __func__);
3045 return -EINVAL;
3046 }
3047
3048 return tomtom->codec_ext_clk_en_cb(codec, enable, dapm);
3049}
3050
3051static int __tomtom_mclk_enable(struct tomtom_priv *tomtom, int mclk_enable)
3052{
3053 int ret = 0;
3054
3055 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3056 if (mclk_enable) {
3057 tomtom->ext_clk_users++;
3058 if (tomtom->ext_clk_users > 1)
3059 goto bg_clk_unlock;
3060 ret = clk_prepare_enable(tomtom->wcd_ext_clk);
3061 if (ret) {
3062 pr_err("%s: ext clk enable failed\n",
3063 __func__);
3064 tomtom->ext_clk_users--;
3065 goto bg_clk_unlock;
3066 }
3067 wcd9xxx_resmgr_get_bandgap(&tomtom->resmgr,
3068 WCD9XXX_BANDGAP_AUDIO_MODE);
3069 wcd9xxx_resmgr_get_clk_block(&tomtom->resmgr, WCD9XXX_CLK_MCLK);
3070 } else {
3071 tomtom->ext_clk_users--;
3072 if (tomtom->ext_clk_users == 0) {
3073 /* Put clock and BG */
3074 wcd9xxx_resmgr_put_clk_block(&tomtom->resmgr,
3075 WCD9XXX_CLK_MCLK);
3076 wcd9xxx_resmgr_put_bandgap(&tomtom->resmgr,
3077 WCD9XXX_BANDGAP_AUDIO_MODE);
3078 clk_disable_unprepare(tomtom->wcd_ext_clk);
3079 }
3080 }
3081bg_clk_unlock:
3082 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3083
3084 return ret;
3085}
3086
3087int tomtom_codec_mclk_enable(struct snd_soc_codec *codec,
3088 int enable, bool dapm)
3089{
3090 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3091
3092 if (tomtom->wcd_ext_clk) {
3093 dev_dbg(codec->dev, "%s: mclk_enable = %u, dapm = %d\n",
3094 __func__, enable, dapm);
3095 return __tomtom_mclk_enable(tomtom, enable);
3096 } else if (tomtom->codec_ext_clk_en_cb)
3097 return tomtom_codec_ext_clk_en(codec, enable, dapm);
3098 else {
3099 dev_err(codec->dev,
3100 "%s: Cannot turn on MCLK\n",
3101 __func__);
3102 return -EINVAL;
3103 }
3104}
3105EXPORT_SYMBOL(tomtom_codec_mclk_enable);
3106
3107static int tomtom_codec_get_ext_clk_users(struct tomtom_priv *tomtom)
3108{
3109 if (tomtom->wcd_ext_clk)
3110 return tomtom->ext_clk_users;
3111 else if (tomtom->codec_get_ext_clk_cnt)
3112 return tomtom->codec_get_ext_clk_cnt();
3113 else
3114 return 0;
3115}
3116
3117/* tomtom_codec_internal_rco_ctrl( )
3118 * Make sure that BG_CLK_LOCK is not acquired. Exit if acquired to avoid
3119 * potential deadlock as ext_clk_en_cb() also tries to acquire the same
3120 * lock to enable MCLK for RCO calibration
3121 */
3122static int tomtom_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
3123 bool enable)
3124{
3125 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3126 int ret = 0;
3127
3128 if (enable) {
3129 if (wcd9xxx_resmgr_get_clk_type(&tomtom->resmgr) ==
3130 WCD9XXX_CLK_RCO) {
3131 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3132 wcd9xxx_resmgr_get_clk_block(&tomtom->resmgr,
3133 WCD9XXX_CLK_RCO);
3134 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3135 } else {
3136 tomtom_codec_mclk_enable(codec, true, false);
3137 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3138 tomtom->resmgr.ext_clk_users =
3139 tomtom_codec_get_ext_clk_users(tomtom);
3140 wcd9xxx_resmgr_get_clk_block(&tomtom->resmgr,
3141 WCD9XXX_CLK_RCO);
3142 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3143 tomtom_codec_mclk_enable(codec, false, false);
3144 }
3145
3146 } else {
3147 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3148 wcd9xxx_resmgr_put_clk_block(&tomtom->resmgr,
3149 WCD9XXX_CLK_RCO);
3150 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3151 }
3152
3153 return ret;
3154}
3155
3156static int tomtom_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
3157 struct snd_kcontrol *kcontrol, int event)
3158{
3159 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3160 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3161
3162 pr_debug("%s: %d\n", __func__, event);
3163
3164 switch (event) {
3165 case SND_SOC_DAPM_PRE_PMU:
3166 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3167 wcd9xxx_resmgr_get_bandgap(&tomtom->resmgr,
3168 WCD9XXX_BANDGAP_AUDIO_MODE);
3169 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3170 /* AUX PGA requires RCO or MCLK */
3171 tomtom_codec_internal_rco_ctrl(codec, true);
3172 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3173 wcd9xxx_resmgr_enable_rx_bias(&tomtom->resmgr, 1);
3174 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3175 break;
3176
3177 case SND_SOC_DAPM_POST_PMD:
3178 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3179 wcd9xxx_resmgr_enable_rx_bias(&tomtom->resmgr, 0);
3180 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3181 tomtom_codec_internal_rco_ctrl(codec, false);
3182 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
3183 wcd9xxx_resmgr_put_bandgap(&tomtom->resmgr,
3184 WCD9XXX_BANDGAP_AUDIO_MODE);
3185 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
3186 break;
3187 }
3188 return 0;
3189}
3190
3191static int tomtom_codec_enable_lineout(struct snd_soc_dapm_widget *w,
3192 struct snd_kcontrol *kcontrol, int event)
3193{
3194 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3195 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3196 u16 lineout_gain_reg;
3197
3198 pr_debug("%s %d %s\n", __func__, event, w->name);
3199
3200 switch (w->shift) {
3201 case 0:
3202 lineout_gain_reg = TOMTOM_A_RX_LINE_1_GAIN;
3203 break;
3204 case 1:
3205 lineout_gain_reg = TOMTOM_A_RX_LINE_2_GAIN;
3206 break;
3207 case 2:
3208 lineout_gain_reg = TOMTOM_A_RX_LINE_3_GAIN;
3209 break;
3210 case 3:
3211 lineout_gain_reg = TOMTOM_A_RX_LINE_4_GAIN;
3212 break;
3213 default:
3214 pr_err("%s: Error, incorrect lineout register value\n",
3215 __func__);
3216 return -EINVAL;
3217 }
3218
3219 switch (event) {
3220 case SND_SOC_DAPM_PRE_PMU:
3221 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
3222 break;
3223 case SND_SOC_DAPM_POST_PMU:
3224 wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
3225 WCD9XXX_CLSH_STATE_LO,
3226 WCD9XXX_CLSH_REQ_ENABLE,
3227 WCD9XXX_CLSH_EVENT_POST_PA);
3228 pr_debug("%s: sleeping 5 ms after %s PA turn on\n",
3229 __func__, w->name);
3230 /* Wait for CnP time after PA enable */
3231 usleep_range(5000, 5100);
3232 break;
3233 case SND_SOC_DAPM_POST_PMD:
3234 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
3235 pr_debug("%s: sleeping 5 ms after %s PA turn off\n",
3236 __func__, w->name);
3237 /* Wait for CnP time after PA disable */
3238 usleep_range(5000, 5100);
3239 break;
3240 }
3241 return 0;
3242}
3243
3244static int tomtom_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
3245 struct snd_kcontrol *kcontrol, int event)
3246{
3247 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3248 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3249 u16 spk_drv_reg;
3250
3251 pr_debug("%s: %d %s\n", __func__, event, w->name);
3252 if (strnstr(w->name, "SPK2 PA", sizeof("SPK2 PA")))
3253 spk_drv_reg = TOMTOM_A_SPKR_DRV2_EN;
3254 else
3255 spk_drv_reg = TOMTOM_A_SPKR_DRV1_EN;
3256
3257 switch (event) {
3258 case SND_SOC_DAPM_PRE_PMU:
3259 tomtom->spkr_pa_widget_on = true;
3260 snd_soc_update_bits(codec, spk_drv_reg, 0x80, 0x80);
3261 break;
3262 case SND_SOC_DAPM_POST_PMD:
3263 tomtom->spkr_pa_widget_on = false;
3264 snd_soc_update_bits(codec, spk_drv_reg, 0x80, 0x00);
3265 break;
3266 }
3267 return 0;
3268}
3269
3270static u8 tomtom_get_dmic_clk_val(struct snd_soc_codec *codec,
3271 u32 mclk_rate, u32 dmic_clk_rate)
3272{
3273 u32 div_factor;
3274 u8 dmic_ctl_val;
3275
3276 dev_dbg(codec->dev,
3277 "%s: mclk_rate = %d, dmic_sample_rate = %d\n",
3278 __func__, mclk_rate, dmic_clk_rate);
3279
3280 /* Default value to return in case of error */
3281 if (mclk_rate == TOMTOM_MCLK_CLK_9P6MHZ)
3282 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_2;
3283 else
3284 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_3;
3285
3286 if (dmic_clk_rate == 0) {
3287 dev_err(codec->dev,
3288 "%s: dmic_sample_rate cannot be 0\n",
3289 __func__);
3290 goto done;
3291 }
3292
3293 div_factor = mclk_rate / dmic_clk_rate;
3294 switch (div_factor) {
3295 case 2:
3296 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_2;
3297 break;
3298 case 3:
3299 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_3;
3300 break;
3301 case 4:
3302 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_4;
3303 break;
3304 case 6:
3305 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_6;
3306 break;
3307 case 16:
3308 dmic_ctl_val = WCD9330_DMIC_CLK_DIV_16;
3309 break;
3310 default:
3311 dev_err(codec->dev,
3312 "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
3313 __func__, div_factor, mclk_rate, dmic_clk_rate);
3314 break;
3315 }
3316
3317done:
3318 return dmic_ctl_val;
3319}
3320
3321static int tomtom_codec_enable_dmic(struct snd_soc_dapm_widget *w,
3322 struct snd_kcontrol *kcontrol, int event)
3323{
3324 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3325 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3326 struct wcd9xxx_pdata *pdata = tomtom->resmgr.pdata;
3327 u8 dmic_clk_en;
3328 u16 dmic_clk_reg;
3329 s32 *dmic_clk_cnt;
3330 u8 dmic_rate_val, dmic_rate_shift;
3331 unsigned int dmic;
3332 int ret;
3333 char *wname;
3334
3335 wname = strpbrk(w->name, "123456");
3336 if (!wname) {
3337 dev_err(codec->dev, "%s: widget not found\n", __func__);
3338 return -EINVAL;
3339 }
3340
3341 ret = kstrtouint(wname, 10, &dmic);
3342 if (ret < 0) {
3343 pr_err("%s: Invalid DMIC line on the codec\n", __func__);
3344 return -EINVAL;
3345 }
3346
3347 switch (dmic) {
3348 case 1:
3349 case 2:
3350 dmic_clk_en = 0x01;
3351 dmic_clk_cnt = &(tomtom->dmic_1_2_clk_cnt);
3352 dmic_clk_reg = TOMTOM_A_DMIC_B1_CTL;
3353 dmic_rate_shift = 5;
3354 pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
3355 __func__, event, dmic, *dmic_clk_cnt);
3356
3357 break;
3358
3359 case 3:
3360 case 4:
3361 dmic_clk_en = 0x02;
3362 dmic_clk_cnt = &(tomtom->dmic_3_4_clk_cnt);
3363 dmic_clk_reg = TOMTOM_A_DMIC_B2_CTL;
3364 dmic_rate_shift = 1;
3365 pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
3366 __func__, event, dmic, *dmic_clk_cnt);
3367 break;
3368
3369 case 5:
3370 case 6:
3371 dmic_clk_en = 0x04;
3372 dmic_clk_cnt = &(tomtom->dmic_5_6_clk_cnt);
3373 dmic_clk_reg = TOMTOM_A_DMIC_B2_CTL;
3374 dmic_rate_shift = 4;
3375 pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
3376 __func__, event, dmic, *dmic_clk_cnt);
3377
3378 break;
3379
3380 default:
3381 pr_err("%s: Invalid DMIC Selection\n", __func__);
3382 return -EINVAL;
3383 }
3384
3385 switch (event) {
3386 case SND_SOC_DAPM_PRE_PMU:
3387
3388 dmic_rate_val =
3389 tomtom_get_dmic_clk_val(codec,
3390 pdata->mclk_rate,
3391 pdata->dmic_sample_rate);
3392
3393 (*dmic_clk_cnt)++;
3394 if (*dmic_clk_cnt == 1) {
3395 snd_soc_update_bits(codec, dmic_clk_reg,
3396 0x07 << dmic_rate_shift,
3397 dmic_rate_val << dmic_rate_shift);
3398 snd_soc_update_bits(codec, TOMTOM_A_DMIC_B1_CTL,
3399 dmic_clk_en, dmic_clk_en);
3400 }
3401
3402 break;
3403 case SND_SOC_DAPM_POST_PMD:
3404
3405 dmic_rate_val =
3406 tomtom_get_dmic_clk_val(codec,
3407 pdata->mclk_rate,
3408 pdata->mad_dmic_sample_rate);
3409 (*dmic_clk_cnt)--;
3410 if (*dmic_clk_cnt == 0) {
3411 snd_soc_update_bits(codec, TOMTOM_A_DMIC_B1_CTL,
3412 dmic_clk_en, 0);
3413 snd_soc_update_bits(codec, dmic_clk_reg,
3414 0x07 << dmic_rate_shift,
3415 dmic_rate_val << dmic_rate_shift);
3416 }
3417 break;
3418 }
3419 return 0;
3420}
3421
3422static int tomtom_codec_config_mad(struct snd_soc_codec *codec)
3423{
3424 int ret = 0;
3425 const struct firmware *fw;
3426 struct firmware_cal *hwdep_cal = NULL;
3427 struct mad_audio_cal *mad_cal;
3428 const void *data;
3429 const char *filename = TOMTOM_MAD_AUDIO_FIRMWARE_PATH;
3430 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3431 size_t cal_size;
3432 int idx;
3433
3434 pr_debug("%s: enter\n", __func__);
3435
3436 if (!tomtom->fw_data) {
3437 dev_err(codec->dev, "%s: invalid cal data\n",
3438 __func__);
3439 return -ENODEV;
3440 }
3441
3442 hwdep_cal = wcdcal_get_fw_cal(tomtom->fw_data, WCD9XXX_MAD_CAL);
3443 if (hwdep_cal) {
3444 data = hwdep_cal->data;
3445 cal_size = hwdep_cal->size;
3446 dev_dbg(codec->dev, "%s: using hwdep calibration\n",
3447 __func__);
3448 } else {
3449 ret = request_firmware(&fw, filename, codec->dev);
3450 if (ret != 0) {
3451 pr_err("Failed to acquire MAD firwmare data %s: %d\n",
3452 filename, ret);
3453 return -ENODEV;
3454 }
3455 if (!fw) {
3456 dev_err(codec->dev, "failed to get mad fw");
3457 return -ENODEV;
3458 }
3459 data = fw->data;
3460 cal_size = fw->size;
3461 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
3462 __func__);
3463 }
3464 if (cal_size < sizeof(struct mad_audio_cal)) {
3465 pr_err("%s: incorrect hwdep cal size %zu\n",
3466 __func__, cal_size);
3467 ret = -ENOMEM;
3468 goto err;
3469 }
3470
3471 mad_cal = (struct mad_audio_cal *)(data);
3472 if (!mad_cal) {
3473 dev_err(codec->dev, "%s: Invalid calibration data\n",
3474 __func__);
3475 ret = -EINVAL;
3476 goto err;
3477 }
3478
3479 snd_soc_write(codec, TOMTOM_A_CDC_MAD_MAIN_CTL_2,
3480 mad_cal->microphone_info.cycle_time);
3481 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
3482 ((uint16_t)mad_cal->microphone_info.settle_time)
3483 << 3);
3484
3485 /* Audio */
3486 snd_soc_write(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_8,
3487 mad_cal->audio_info.rms_omit_samples);
3488 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_1,
3489 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
3490 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_2, 0x03 << 2,
3491 mad_cal->audio_info.detection_mechanism << 2);
3492 snd_soc_write(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_7,
3493 mad_cal->audio_info.rms_diff_threshold & 0x3F);
3494 snd_soc_write(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_5,
3495 mad_cal->audio_info.rms_threshold_lsb);
3496 snd_soc_write(codec, TOMTOM_A_CDC_MAD_AUDIO_CTL_6,
3497 mad_cal->audio_info.rms_threshold_msb);
3498
3499 for (idx = 0; idx < ARRAY_SIZE(mad_cal->audio_info.iir_coefficients);
3500 idx++) {
3501 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_AUDIO_IIR_CTL_PTR,
3502 0x3F, idx);
3503 snd_soc_write(codec, TOMTOM_A_CDC_MAD_AUDIO_IIR_CTL_VAL,
3504 mad_cal->audio_info.iir_coefficients[idx]);
3505 dev_dbg(codec->dev, "%s:MAD Audio IIR Coef[%d] = 0X%x",
3506 __func__, idx,
3507 mad_cal->audio_info.iir_coefficients[idx]);
3508 }
3509
3510 /* Beacon */
3511 snd_soc_write(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_8,
3512 mad_cal->beacon_info.rms_omit_samples);
3513 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_1,
3514 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
3515 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_2, 0x03 << 2,
3516 mad_cal->beacon_info.detection_mechanism << 2);
3517 snd_soc_write(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_7,
3518 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
3519 snd_soc_write(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_5,
3520 mad_cal->beacon_info.rms_threshold_lsb);
3521 snd_soc_write(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_6,
3522 mad_cal->beacon_info.rms_threshold_msb);
3523
3524 /* Ultrasound */
3525 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_BEACON_CTL_1,
3526 0x07 << 4, mad_cal->beacon_info.rms_comp_time);
3527 snd_soc_update_bits(codec, TOMTOM_A_CDC_MAD_ULTR_CTL_2, 0x03 << 2,
3528 mad_cal->ultrasound_info.detection_mechanism);
3529 snd_soc_write(codec, TOMTOM_A_CDC_MAD_ULTR_CTL_7,
3530 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
3531 snd_soc_write(codec, TOMTOM_A_CDC_MAD_ULTR_CTL_5,
3532 mad_cal->ultrasound_info.rms_threshold_lsb);
3533 snd_soc_write(codec, TOMTOM_A_CDC_MAD_ULTR_CTL_6,
3534 mad_cal->ultrasound_info.rms_threshold_msb);
3535
3536 /* Set MAD intr time to 20 msec */
3537 snd_soc_update_bits(codec, 0x4E, 0x01F, 0x13);
3538
3539 pr_debug("%s: leave ret %d\n", __func__, ret);
3540err:
3541 if (!hwdep_cal)
3542 release_firmware(fw);
3543 return ret;
3544}
3545
3546static int tomtom_codec_enable_mad(struct snd_soc_dapm_widget *w,
3547 struct snd_kcontrol *kcontrol, int event)
3548{
3549 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3550 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3551 int ret = 0;
3552 u8 mad_micb, mad_cfilt;
3553 u16 mad_cfilt_reg;
3554
3555 mad_micb = snd_soc_read(codec, TOMTOM_A_MAD_ANA_CTRL) & 0x07;
3556 switch (mad_micb) {
3557 case 1:
3558 mad_cfilt = tomtom->resmgr.pdata->micbias.bias1_cfilt_sel;
3559 break;
3560 case 2:
3561 mad_cfilt = tomtom->resmgr.pdata->micbias.bias2_cfilt_sel;
3562 break;
3563 case 3:
3564 mad_cfilt = tomtom->resmgr.pdata->micbias.bias3_cfilt_sel;
3565 break;
3566 case 4:
3567 mad_cfilt = tomtom->resmgr.pdata->micbias.bias4_cfilt_sel;
3568 break;
3569 default:
3570 dev_err(codec->dev,
3571 "%s: Invalid micbias selection 0x%x\n",
3572 __func__, mad_micb);
3573 return -EINVAL;
3574 }
3575
3576 switch (mad_cfilt) {
3577 case WCD9XXX_CFILT1_SEL:
3578 mad_cfilt_reg = TOMTOM_A_MICB_CFILT_1_VAL;
3579 break;
3580 case WCD9XXX_CFILT2_SEL:
3581 mad_cfilt_reg = TOMTOM_A_MICB_CFILT_2_VAL;
3582 break;
3583 case WCD9XXX_CFILT3_SEL:
3584 mad_cfilt_reg = TOMTOM_A_MICB_CFILT_3_VAL;
3585 break;
3586 default:
3587 dev_err(codec->dev,
3588 "%s: invalid cfilt 0x%x for micb 0x%x\n",
3589 __func__, mad_cfilt, mad_micb);
3590 return -EINVAL;
3591 }
3592
3593 dev_dbg(codec->dev,
3594 "%s event = %d, mad_cfilt_reg = 0x%x\n",
3595 __func__, event, mad_cfilt_reg);
3596
3597 switch (event) {
3598 case SND_SOC_DAPM_PRE_PMU:
3599 /* Undo reset for MAD */
3600 snd_soc_update_bits(codec, TOMTOM_A_SVASS_CLKRST_CTL,
3601 0x02, 0x00);
3602
3603 ret = tomtom_codec_config_mad(codec);
3604 if (ret) {
3605 pr_err("%s: Failed to config MAD\n", __func__);
3606 break;
3607 }
3608
3609 /* setup MAD micbias to VDDIO */
3610 snd_soc_update_bits(codec, mad_cfilt_reg,
3611 0x02, 0x02);
3612 break;
3613 case SND_SOC_DAPM_POST_PMD:
3614 /* Reset the MAD block */
3615 snd_soc_update_bits(codec, TOMTOM_A_SVASS_CLKRST_CTL,
3616 0x02, 0x02);
3617
3618 /* Undo setup of MAD micbias to VDDIO */
3619 snd_soc_update_bits(codec, mad_cfilt_reg,
3620 0x02, 0x00);
3621 }
3622 return ret;
3623}
3624
3625static int tomtom_codec_enable_micbias(struct snd_soc_dapm_widget *w,
3626 struct snd_kcontrol *kcontrol, int event)
3627{
3628 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3629 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
3630 u16 micb_int_reg = 0, micb_ctl_reg = 0;
3631 u8 cfilt_sel_val = 0;
3632 char *internal1_text = "Internal1";
3633 char *internal2_text = "Internal2";
3634 char *internal3_text = "Internal3";
3635 enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
3636
3637 pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
3638 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
3639 micb_ctl_reg = TOMTOM_A_MICB_1_CTL;
3640 micb_int_reg = TOMTOM_A_MICB_1_INT_RBIAS;
3641 cfilt_sel_val = tomtom->resmgr.pdata->micbias.bias1_cfilt_sel;
3642 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
3643 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
3644 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
3645 } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
3646 micb_ctl_reg = TOMTOM_A_MICB_2_CTL;
3647 micb_int_reg = TOMTOM_A_MICB_2_INT_RBIAS;
3648 cfilt_sel_val = tomtom->resmgr.pdata->micbias.bias2_cfilt_sel;
3649 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
3650 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
3651 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
3652 } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
3653 micb_ctl_reg = TOMTOM_A_MICB_3_CTL;
3654 micb_int_reg = TOMTOM_A_MICB_3_INT_RBIAS;
3655 cfilt_sel_val = tomtom->resmgr.pdata->micbias.bias3_cfilt_sel;
3656 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
3657 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
3658 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
3659 } else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4"))) {
3660 micb_ctl_reg = TOMTOM_A_MICB_4_CTL;
3661 micb_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias;
3662 cfilt_sel_val = tomtom->resmgr.pdata->micbias.bias4_cfilt_sel;
3663 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_4_ON;
3664 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_4_ON;
3665 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_4_OFF;
3666 } else {
3667 pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
3668 return -EINVAL;
3669 }
3670
3671 switch (event) {
3672 case SND_SOC_DAPM_PRE_PMU:
3673 /* Let MBHC module know so micbias switch to be off */
3674 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_pre_on);
3675
3676 /* Get cfilt */
3677 wcd9xxx_resmgr_cfilt_get(&tomtom->resmgr, cfilt_sel_val);
3678
3679 if (strnstr(w->name, internal1_text, 30))
3680 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
3681 else if (strnstr(w->name, internal2_text, 30))
3682 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
3683 else if (strnstr(w->name, internal3_text, 30))
3684 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
3685 else
3686 /*
3687 * If not internal, make sure to write the
3688 * register to default value
3689 */
3690 snd_soc_write(codec, micb_int_reg, 0x24);
3691 if (tomtom->mbhc_started && micb_ctl_reg ==
3692 TOMTOM_A_MICB_2_CTL) {
3693 if (++tomtom->micb_2_users == 1) {
3694 if (tomtom->resmgr.pdata->
3695 micbias.bias2_is_headset_only)
3696 wcd9xxx_resmgr_add_cond_update_bits(
3697 &tomtom->resmgr,
3698 WCD9XXX_COND_HPH_MIC,
3699 micb_ctl_reg, w->shift,
3700 false);
3701 else
3702 snd_soc_update_bits(codec, micb_ctl_reg,
3703 1 << w->shift,
3704 1 << w->shift);
3705 }
3706 pr_debug("%s: micb_2_users %d\n", __func__,
3707 tomtom->micb_2_users);
3708 } else {
3709 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
3710 1 << w->shift);
3711 }
3712 break;
3713 case SND_SOC_DAPM_POST_PMU:
3714 usleep_range(5000, 5100);
3715 /* Let MBHC module know so micbias is on */
3716 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_post_on);
3717 break;
3718 case SND_SOC_DAPM_POST_PMD:
3719 if (tomtom->mbhc_started && micb_ctl_reg ==
3720 TOMTOM_A_MICB_2_CTL) {
3721 if (--tomtom->micb_2_users == 0) {
3722 if (tomtom->resmgr.pdata->
3723 micbias.bias2_is_headset_only)
3724 wcd9xxx_resmgr_rm_cond_update_bits(
3725 &tomtom->resmgr,
3726 WCD9XXX_COND_HPH_MIC,
3727 micb_ctl_reg, 7, false);
3728 else
3729 snd_soc_update_bits(codec, micb_ctl_reg,
3730 1 << w->shift, 0);
3731 }
3732 pr_debug("%s: micb_2_users %d\n", __func__,
3733 tomtom->micb_2_users);
3734 WARN(tomtom->micb_2_users < 0,
3735 "Unexpected micbias users %d\n",
3736 tomtom->micb_2_users);
3737 } else {
3738 snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
3739 0);
3740 }
3741
3742 /* Let MBHC module know so micbias switch to be off */
3743 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_post_off);
3744
3745 if (strnstr(w->name, internal1_text, 30))
3746 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
3747 else if (strnstr(w->name, internal2_text, 30))
3748 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
3749 else if (strnstr(w->name, internal3_text, 30))
3750 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
3751
3752 /* Put cfilt */
3753 wcd9xxx_resmgr_cfilt_put(&tomtom->resmgr, cfilt_sel_val);
3754 break;
3755 }
3756
3757 return 0;
3758}
3759
3760/* called under codec_resource_lock acquisition */
3761static int tomtom_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable,
3762 enum wcd9xxx_micbias_num micb_num)
3763{
3764 int rc;
3765
3766 if (micb_num != MBHC_MICBIAS2) {
3767 dev_err(codec->dev, "%s: Unsupported micbias, micb_num=%d\n",
3768 __func__, micb_num);
3769 return -EINVAL;
3770 }
3771
3772 if (enable)
3773 rc = snd_soc_dapm_force_enable_pin(
3774 snd_soc_codec_get_dapm(codec),
3775 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
3776 else
3777 rc = snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(codec),
3778 DAPM_MICBIAS2_EXTERNAL_STANDALONE);
3779 if (!rc)
3780 snd_soc_dapm_sync(snd_soc_codec_get_dapm(codec));
3781 pr_debug("%s: leave ret %d\n", __func__, rc);
3782 return rc;
3783}
3784
3785static void txfe_clkdiv_update(struct snd_soc_codec *codec)
3786{
3787 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
3788
3789 if (test_bit(ADC1_TXFE, &priv->status_mask)) {
3790 snd_soc_update_bits(codec, TOMTOM_A_TX_1_2_TXFE_CLKDIV,
3791 0x0F, 0x05);
3792 clear_bit(ADC1_TXFE, &priv->status_mask);
3793 }
3794 if (test_bit(ADC2_TXFE, &priv->status_mask)) {
3795 snd_soc_update_bits(codec, TOMTOM_A_TX_1_2_TXFE_CLKDIV,
3796 0xF0, 0x50);
3797 clear_bit(ADC2_TXFE, &priv->status_mask);
3798 }
3799 if (test_bit(ADC3_TXFE, &priv->status_mask)) {
3800 snd_soc_update_bits(codec, TOMTOM_A_TX_3_4_TXFE_CKDIV,
3801 0x0F, 0x05);
3802 clear_bit(ADC3_TXFE, &priv->status_mask);
3803 }
3804 if (test_bit(ADC4_TXFE, &priv->status_mask)) {
3805 snd_soc_update_bits(codec, TOMTOM_A_TX_3_4_TXFE_CKDIV,
3806 0xF0, 0x50);
3807 clear_bit(ADC4_TXFE, &priv->status_mask);
3808 }
3809 if (test_bit(ADC5_TXFE, &priv->status_mask)) {
3810 snd_soc_update_bits(codec, TOMTOM_A_TX_5_6_TXFE_CKDIV,
3811 0x0F, 0x05);
3812 clear_bit(ADC5_TXFE, &priv->status_mask);
3813 }
3814 if (test_bit(ADC6_TXFE, &priv->status_mask)) {
3815 snd_soc_update_bits(codec, TOMTOM_A_TX_5_6_TXFE_CKDIV,
3816 0xF0, 0x50);
3817 clear_bit(ADC6_TXFE, &priv->status_mask);
3818 }
3819}
3820
3821static void tx_hpf_corner_freq_callback(struct work_struct *work)
3822{
3823 struct delayed_work *hpf_delayed_work;
3824 struct hpf_work *hpf_work;
3825 struct tomtom_priv *tomtom;
3826 struct snd_soc_codec *codec;
3827 u16 tx_mux_ctl_reg;
3828 u8 hpf_cut_of_freq;
3829
3830 hpf_delayed_work = to_delayed_work(work);
3831 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
3832 tomtom = hpf_work->tomtom;
3833 codec = hpf_work->tomtom->codec;
3834 hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
3835
3836 tx_mux_ctl_reg = TOMTOM_A_CDC_TX1_MUX_CTL +
3837 (hpf_work->decimator - 1) * 8;
3838
3839 pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
3840 hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
3841
3842 /*
3843 * Restore TXFE ClkDiv registers to default.
3844 * If any of these registers are modified during analog
3845 * front-end enablement, they will be restored back to the
3846 * default
3847 */
3848 txfe_clkdiv_update(codec);
3849
3850 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
3851}
3852
3853#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
3854#define CF_MIN_3DB_4HZ 0x0
3855#define CF_MIN_3DB_75HZ 0x1
3856#define CF_MIN_3DB_150HZ 0x2
3857
3858static int tomtom_codec_enable_dec(struct snd_soc_dapm_widget *w,
3859 struct snd_kcontrol *kcontrol, int event)
3860{
3861 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3862 unsigned int decimator;
3863 char *dec_name = NULL;
3864 char *widget_name = NULL;
3865 char *temp;
3866 int ret = 0;
3867 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
3868 u8 dec_hpf_cut_of_freq;
3869 int offset;
3870 char *dec;
3871
3872 pr_debug("%s %d\n", __func__, event);
3873
3874 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
3875 if (!widget_name)
3876 return -ENOMEM;
3877 temp = widget_name;
3878
3879 dec_name = strsep(&widget_name, " ");
3880 widget_name = temp;
3881 if (!dec_name) {
3882 pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
3883 ret = -EINVAL;
3884 goto out;
3885 }
3886
3887 dec = strpbrk(dec_name, "123456789");
3888 if (!dec) {
3889 dev_err(codec->dev, "%s: decimator index not found\n",
3890 __func__);
3891 ret = -EINVAL;
3892 goto out;
3893 }
3894
3895 ret = kstrtouint(dec, 10, &decimator);
3896 if (ret < 0) {
3897 pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
3898 ret = -EINVAL;
3899 goto out;
3900 }
3901
3902 pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
3903 w->name, dec_name, decimator);
3904
3905 if (w->reg == TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
3906 dec_reset_reg = TOMTOM_A_CDC_CLK_TX_RESET_B1_CTL;
3907 offset = 0;
3908 } else if (w->reg == TOMTOM_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
3909 dec_reset_reg = TOMTOM_A_CDC_CLK_TX_RESET_B2_CTL;
3910 offset = 8;
3911 } else {
3912 pr_err("%s: Error, incorrect dec\n", __func__);
3913 return -EINVAL;
3914 }
3915
3916 tx_vol_ctl_reg = TOMTOM_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
3917 tx_mux_ctl_reg = TOMTOM_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
3918
3919 switch (event) {
3920 case SND_SOC_DAPM_PRE_PMU:
3921
3922 /* Enableable TX digital mute */
3923 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
3924
3925 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
3926 1 << w->shift);
3927 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
3928
3929 pr_debug("%s: decimator = %u, bypass = %d\n", __func__,
3930 decimator, tx_hpf_work[decimator - 1].tx_hpf_bypass);
3931 if (tx_hpf_work[decimator - 1].tx_hpf_bypass != true) {
3932 dec_hpf_cut_of_freq = snd_soc_read(codec,
3933 tx_mux_ctl_reg);
3934
3935 dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
3936
3937 tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
3938 dec_hpf_cut_of_freq;
3939
3940 if (dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ) {
3941
3942 /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
3943 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
3944 CF_MIN_3DB_150HZ << 4);
3945 }
3946
3947 /* enable HPF */
3948 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x00);
3949 } else
3950 /* bypass HPF */
3951 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
3952
3953 break;
3954
3955 case SND_SOC_DAPM_POST_PMU:
3956
3957 /* Disable TX digital mute */
3958 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
3959
3960 if ((tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
3961 CF_MIN_3DB_150HZ) &&
3962 (tx_hpf_work[decimator - 1].tx_hpf_bypass != true)) {
3963
3964 schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
3965 msecs_to_jiffies(300));
3966 }
3967 /* apply the digital gain after the decimator is enabled*/
3968 if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
3969 snd_soc_write(codec,
3970 tx_digital_gain_reg[w->shift + offset],
3971 snd_soc_read(codec,
3972 tx_digital_gain_reg[w->shift + offset])
3973 );
3974
3975 break;
3976
3977 case SND_SOC_DAPM_PRE_PMD:
3978
3979 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
3980 cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
3981 break;
3982
3983 case SND_SOC_DAPM_POST_PMD:
3984
3985 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
3986 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
3987 (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
3988
3989 break;
3990 }
3991out:
3992 kfree(widget_name);
3993 return ret;
3994}
3995
3996static int tomtom_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
3997 struct snd_kcontrol *kcontrol, int event)
3998{
3999 int ret = 0;
4000 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4001 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
4002
4003 pr_debug("%s: %d %s\n", __func__, event, w->name);
4004
4005 WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
4006 WCD9XXX_VDD_SPKDRV_NAME);
4007 switch (event) {
4008 case SND_SOC_DAPM_PRE_PMU:
4009 if (priv->spkdrv_reg) {
4010 ret = regulator_enable(priv->spkdrv_reg);
4011 if (ret)
4012 pr_err("%s: Failed to enable spkdrv_reg %s\n",
4013 __func__, WCD9XXX_VDD_SPKDRV_NAME);
4014 }
4015 break;
4016 case SND_SOC_DAPM_POST_PMD:
4017 if (priv->spkdrv_reg) {
4018 ret = regulator_disable(priv->spkdrv_reg);
4019 if (ret)
4020 pr_err("%s: Failed to disable spkdrv_reg %s\n",
4021 __func__, WCD9XXX_VDD_SPKDRV_NAME);
4022 }
4023 break;
4024 }
4025
4026 return ret;
4027}
4028
4029static int tomtom_codec_enable_vdd_spkr2(struct snd_soc_dapm_widget *w,
4030 struct snd_kcontrol *kcontrol, int event)
4031{
4032 int ret = 0;
4033 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4034 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
4035
4036 pr_debug("%s: %d %s\n", __func__, event, w->name);
4037
4038 /*
4039 * If on-demand voltage regulators of spkr1 and spkr2 has been derived
4040 * from same power rail then same on-demand voltage regulator can be
4041 * used by both spkr1 and spkr2, if a separate device tree entry has
4042 * not been defined for on-demand voltage regulator for spkr2.
4043 */
4044 if (!priv->spkdrv2_reg) {
4045 if (priv->spkdrv_reg) {
4046 priv->spkdrv2_reg = priv->spkdrv_reg;
4047 } else {
4048 WARN_ONCE(!priv->spkdrv2_reg,
4049 "SPKDRV2 supply %s isn't defined\n",
4050 WCD9XXX_VDD_SPKDRV2_NAME);
4051 return 0;
4052 }
4053 }
4054
4055 switch (event) {
4056 case SND_SOC_DAPM_PRE_PMU:
4057 if (priv->spkdrv2_reg) {
4058 ret = regulator_enable(priv->spkdrv2_reg);
4059 if (ret)
4060 pr_err("%s: Failed to enable spkdrv2_reg %s ret:%d\n",
4061 __func__, WCD9XXX_VDD_SPKDRV2_NAME, ret);
4062 }
4063 break;
4064 case SND_SOC_DAPM_POST_PMD:
4065 if (priv->spkdrv2_reg) {
4066 ret = regulator_disable(priv->spkdrv2_reg);
4067 if (ret)
4068 pr_err("%s: Failed to disable spkdrv2_reg %s ret:%d\n",
4069 __func__, WCD9XXX_VDD_SPKDRV2_NAME, ret);
4070 }
4071 break;
4072 }
4073
4074 return ret;
4075}
4076
4077static int tomtom_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
4078 struct snd_kcontrol *kcontrol, int event)
4079{
4080 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4081
4082 pr_debug("%s %d %s\n", __func__, event, w->name);
4083
4084 switch (event) {
4085 case SND_SOC_DAPM_PRE_PMU:
4086 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_RX_RESET_CTL,
4087 1 << w->shift, 1 << w->shift);
4088 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_RX_RESET_CTL,
4089 1 << w->shift, 0x0);
4090 break;
4091 case SND_SOC_DAPM_POST_PMU:
4092 /* apply the digital gain after the interpolator is enabled*/
4093 if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
4094 snd_soc_write(codec,
4095 rx_digital_gain_reg[w->shift],
4096 snd_soc_read(codec,
4097 rx_digital_gain_reg[w->shift])
4098 );
4099 /* Check for Rx1 and Rx2 paths for uhqa mode update */
4100 if (w->shift == 0 || w->shift == 1)
4101 tomtom_update_uhqa_mode(codec, (1 << w->shift));
4102
4103 break;
4104 }
4105 return 0;
4106}
4107
4108/* called under codec_resource_lock acquisition */
4109static int __tomtom_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
4110 struct snd_kcontrol *kcontrol, int event)
4111{
4112 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4113 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
4114
4115 pr_debug("%s: enter\n", __func__);
4116 switch (event) {
4117 case SND_SOC_DAPM_PRE_PMU:
4118 /*
4119 * ldo_h_users is protected by tomtom->codec_mutex, don't need
4120 * additional mutex
4121 */
4122 if (++priv->ldo_h_users == 1) {
4123 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
4124 wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
4125 WCD9XXX_BANDGAP_AUDIO_MODE);
4126 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
4127 tomtom_codec_internal_rco_ctrl(codec, true);
4128 snd_soc_update_bits(codec, TOMTOM_A_LDO_H_MODE_1,
4129 1 << 7, 1 << 7);
4130 tomtom_codec_internal_rco_ctrl(codec, false);
4131 pr_debug("%s: ldo_h_users %d\n", __func__,
4132 priv->ldo_h_users);
4133 /* LDO enable requires 1ms to settle down */
4134 usleep_range(1000, 1100);
4135 }
4136 break;
4137 case SND_SOC_DAPM_POST_PMD:
4138 if (--priv->ldo_h_users == 0) {
4139 tomtom_codec_internal_rco_ctrl(codec, true);
4140 snd_soc_update_bits(codec, TOMTOM_A_LDO_H_MODE_1,
4141 1 << 7, 0);
4142 tomtom_codec_internal_rco_ctrl(codec, false);
4143 WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
4144 wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
4145 WCD9XXX_BANDGAP_AUDIO_MODE);
4146 WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
4147 pr_debug("%s: ldo_h_users %d\n", __func__,
4148 priv->ldo_h_users);
4149 }
4150 WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n",
4151 priv->ldo_h_users);
4152 break;
4153 }
4154 pr_debug("%s: leave\n", __func__);
4155 return 0;
4156}
4157
4158static int tomtom_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
4159 struct snd_kcontrol *kcontrol, int event)
4160{
4161 int rc;
4162
4163 rc = __tomtom_codec_enable_ldo_h(w, kcontrol, event);
4164 return rc;
4165}
4166
4167static int tomtom_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
4168 struct snd_kcontrol *kcontrol, int event)
4169{
4170 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4171 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
4172
4173 pr_debug("%s %d\n", __func__, event);
4174
4175 switch (event) {
4176 case SND_SOC_DAPM_PRE_PMU:
4177 wcd9xxx_resmgr_enable_rx_bias(&tomtom->resmgr, 1);
4178 break;
4179 case SND_SOC_DAPM_POST_PMD:
4180 wcd9xxx_resmgr_enable_rx_bias(&tomtom->resmgr, 0);
4181 break;
4182 }
4183 return 0;
4184}
4185
4186static int tomtom_codec_enable_anc(struct snd_soc_dapm_widget *w,
4187 struct snd_kcontrol *kcontrol, int event)
4188{
4189 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4190 const char *filename;
4191 const struct firmware *fw;
4192 int i;
4193 int ret = 0;
4194 int num_anc_slots;
4195 struct wcd9xxx_anc_header *anc_head;
4196 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
4197 struct firmware_cal *hwdep_cal = NULL;
4198 u32 anc_writes_size = 0;
4199 u32 anc_cal_size = 0;
4200 int anc_size_remaining;
4201 u32 *anc_ptr;
4202 u16 reg;
4203 u8 mask, val, old_val;
4204 size_t cal_size;
4205 const void *data;
4206
4207 if (tomtom->anc_func == 0)
4208 return 0;
4209
4210 switch (event) {
4211 case SND_SOC_DAPM_PRE_PMU:
4212 filename = "wcd9320/wcd9320_anc.bin";
4213
4214 hwdep_cal = wcdcal_get_fw_cal(tomtom->fw_data, WCD9XXX_ANC_CAL);
4215 if (hwdep_cal) {
4216 data = hwdep_cal->data;
4217 cal_size = hwdep_cal->size;
4218 dev_dbg(codec->dev, "%s: using hwdep calibration\n",
4219 __func__);
4220 } else {
4221 ret = request_firmware(&fw, filename, codec->dev);
4222 if (ret != 0) {
4223 dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
4224 ret);
4225 return -ENODEV;
4226 }
4227 if (!fw) {
4228 dev_err(codec->dev, "failed to get anc fw");
4229 return -ENODEV;
4230 }
4231 data = fw->data;
4232 cal_size = fw->size;
4233 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
4234 __func__);
4235 }
4236 if (cal_size < sizeof(struct wcd9xxx_anc_header)) {
4237 dev_err(codec->dev, "Not enough data\n");
4238 ret = -ENOMEM;
4239 goto err;
4240 }
4241 /* First number is the number of register writes */
4242 anc_head = (struct wcd9xxx_anc_header *)(data);
4243 anc_ptr = (u32 *)(data +
4244 sizeof(struct wcd9xxx_anc_header));
4245 anc_size_remaining = cal_size -
4246 sizeof(struct wcd9xxx_anc_header);
4247 num_anc_slots = anc_head->num_anc_slots;
4248
4249 if (tomtom->anc_slot >= num_anc_slots) {
4250 dev_err(codec->dev, "Invalid ANC slot selected\n");
4251 ret = -EINVAL;
4252 goto err;
4253 }
4254 for (i = 0; i < num_anc_slots; i++) {
4255 if (anc_size_remaining < TOMTOM_PACKED_REG_SIZE) {
4256 dev_err(codec->dev, "Invalid register format\n");
4257 ret = -EINVAL;
4258 goto err;
4259 }
4260 anc_writes_size = (u32)(*anc_ptr);
4261 anc_size_remaining -= sizeof(u32);
4262 anc_ptr += 1;
4263
4264 if (anc_writes_size * TOMTOM_PACKED_REG_SIZE
4265 > anc_size_remaining) {
4266 dev_err(codec->dev, "Invalid register format\n");
4267 ret = -EINVAL;
4268 goto err;
4269 }
4270
4271 if (tomtom->anc_slot == i)
4272 break;
4273
4274 anc_size_remaining -= (anc_writes_size *
4275 TOMTOM_PACKED_REG_SIZE);
4276 anc_ptr += anc_writes_size;
4277 }
4278 if (i == num_anc_slots) {
4279 dev_err(codec->dev, "Selected ANC slot not present\n");
4280 ret = -EINVAL;
4281 goto err;
4282 }
4283
4284 i = 0;
4285 anc_cal_size = anc_writes_size;
4286 if (w->reg == TOMTOM_A_RX_HPH_L_DAC_CTL) {
4287 snd_soc_update_bits(codec,
4288 TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x03, 0x03);
4289 anc_writes_size = (anc_cal_size/2);
4290 }
4291
4292 if (w->reg == TOMTOM_A_RX_HPH_R_DAC_CTL) {
4293 snd_soc_update_bits(codec,
4294 TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x0C, 0x0C);
4295 i = (anc_cal_size/2);
4296 anc_writes_size = anc_cal_size;
4297 }
4298
4299 for (; i < anc_writes_size; i++) {
4300 TOMTOM_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
4301 mask, val);
4302 /*
4303 * ANC Soft reset register is ignored from ACDB
4304 * because ANC left soft reset bits will be called
4305 * while enabling ANC HPH Right DAC.
4306 */
4307 if ((reg == TOMTOM_A_CDC_CLK_ANC_RESET_CTL) &&
4308 ((w->reg == TOMTOM_A_RX_HPH_L_DAC_CTL) ||
4309 (w->reg == TOMTOM_A_RX_HPH_R_DAC_CTL))) {
4310 continue;
4311 }
4312 old_val = snd_soc_read(codec, reg);
4313 snd_soc_write(codec, reg, (old_val & ~mask) |
4314 (val & mask));
4315 }
4316 if (w->reg == TOMTOM_A_RX_HPH_L_DAC_CTL)
4317 snd_soc_update_bits(codec,
4318 TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x03, 0x00);
4319
4320 if (w->reg == TOMTOM_A_RX_HPH_R_DAC_CTL)
4321 snd_soc_update_bits(codec,
4322 TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x0C, 0x00);
4323 if (!hwdep_cal)
4324 release_firmware(fw);
4325 txfe_clkdiv_update(codec);
4326 break;
4327 case SND_SOC_DAPM_PRE_PMD:
4328 msleep(40);
4329 snd_soc_update_bits(codec, TOMTOM_A_CDC_ANC1_B1_CTL, 0x01,
4330 0x00);
4331 snd_soc_update_bits(codec, TOMTOM_A_CDC_ANC2_B1_CTL, 0x02,
4332 0x00);
4333 msleep(20);
4334 snd_soc_write(codec, TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
4335 snd_soc_write(codec, TOMTOM_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
4336 snd_soc_write(codec, TOMTOM_A_CDC_CLK_ANC_RESET_CTL, 0x00);
4337 break;
4338 }
4339 return 0;
4340err:
4341 if (!hwdep_cal)
4342 release_firmware(fw);
4343 return ret;
4344}
4345
4346static int tomtom_hphl_dac_event(struct snd_soc_dapm_widget *w,
4347 struct snd_kcontrol *kcontrol, int event)
4348{
4349 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4350 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
4351 uint32_t impedl, impedr;
4352 int ret = 0;
4353
4354 pr_debug("%s %s %d\n", __func__, w->name, event);
4355
4356 switch (event) {
4357 case SND_SOC_DAPM_PRE_PMU:
4358 if (tomtom_p->anc_func) {
4359 tomtom_codec_enable_anc(w, kcontrol, event);
4360 msleep(50);
4361 }
4362
4363 if (!high_perf_mode && !tomtom_p->uhqa_mode) {
4364 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
4365 WCD9XXX_CLSH_STATE_HPHL,
4366 WCD9XXX_CLSH_REQ_ENABLE,
4367 WCD9XXX_CLSH_EVENT_PRE_DAC);
4368 } else {
4369 wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
4370 tomtom_p->uhqa_mode,
4371 WCD9XXX_CLSAB_STATE_HPHL,
4372 WCD9XXX_CLSAB_REQ_ENABLE);
4373 }
4374 ret = wcd9xxx_mbhc_get_impedance(&tomtom_p->mbhc,
4375 &impedl, &impedr);
4376 if (!ret)
4377 wcd9xxx_clsh_imped_config(codec, impedl);
4378 else
4379 dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
4380 __func__, ret);
4381 break;
4382 case SND_SOC_DAPM_POST_PMU:
4383 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX1_B3_CTL, 0xBC, 0x94);
4384 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX1_B4_CTL, 0x30, 0x10);
4385 break;
4386 case SND_SOC_DAPM_PRE_PMD:
4387 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX1_B3_CTL, 0xBC, 0x00);
4388 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX1_B4_CTL, 0x30, 0x00);
4389 break;
4390 case SND_SOC_DAPM_POST_PMD:
4391 if (!high_perf_mode && !tomtom_p->uhqa_mode) {
4392 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
4393 WCD9XXX_CLSH_STATE_HPHL,
4394 WCD9XXX_CLSH_REQ_DISABLE,
4395 WCD9XXX_CLSH_EVENT_POST_PA);
4396 } else {
4397 wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
4398 tomtom_p->uhqa_mode,
4399 WCD9XXX_CLSAB_STATE_HPHL,
4400 WCD9XXX_CLSAB_REQ_DISABLE);
4401 }
4402 break;
4403 }
4404 return 0;
4405}
4406
4407static int tomtom_hphr_dac_event(struct snd_soc_dapm_widget *w,
4408 struct snd_kcontrol *kcontrol, int event)
4409{
4410 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4411 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
4412
4413 pr_debug("%s %s %d\n", __func__, w->name, event);
4414
4415 switch (event) {
4416 case SND_SOC_DAPM_PRE_PMU:
4417 if (tomtom_p->anc_func) {
4418 tomtom_codec_enable_anc(w, kcontrol, event);
4419 msleep(50);
4420 }
4421
4422 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
4423 if (!high_perf_mode && !tomtom_p->uhqa_mode) {
4424 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
4425 WCD9XXX_CLSH_STATE_HPHR,
4426 WCD9XXX_CLSH_REQ_ENABLE,
4427 WCD9XXX_CLSH_EVENT_PRE_DAC);
4428 } else {
4429 wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
4430 tomtom_p->uhqa_mode,
4431 WCD9XXX_CLSAB_STATE_HPHR,
4432 WCD9XXX_CLSAB_REQ_ENABLE);
4433 }
4434 break;
4435 case SND_SOC_DAPM_POST_PMU:
4436 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX2_B3_CTL, 0xBC, 0x94);
4437 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX2_B4_CTL, 0x30, 0x10);
4438 break;
4439 case SND_SOC_DAPM_PRE_PMD:
4440 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX2_B3_CTL, 0xBC, 0x00);
4441 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX2_B4_CTL, 0x30, 0x00);
4442 break;
4443 case SND_SOC_DAPM_POST_PMD:
4444 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
4445 if (!high_perf_mode && !tomtom_p->uhqa_mode) {
4446 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
4447 WCD9XXX_CLSH_STATE_HPHR,
4448 WCD9XXX_CLSH_REQ_DISABLE,
4449 WCD9XXX_CLSH_EVENT_POST_PA);
4450 } else {
4451 wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
4452 tomtom_p->uhqa_mode,
4453 WCD9XXX_CLSAB_STATE_HPHR,
4454 WCD9XXX_CLSAB_REQ_DISABLE);
4455 }
4456 break;
4457 }
4458 return 0;
4459}
4460
4461static int tomtom_hph_pa_event(struct snd_soc_dapm_widget *w,
4462 struct snd_kcontrol *kcontrol, int event)
4463{
4464 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4465 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
4466 enum wcd9xxx_notify_event e_pre_on, e_post_off;
4467 u8 req_clsh_state;
4468 u32 pa_settle_time = TOMTOM_HPH_PA_SETTLE_COMP_OFF;
4469
4470 pr_debug("%s: %s event = %d\n", __func__, w->name, event);
4471 if (w->shift == 5) {
4472 e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
4473 e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
4474 req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
4475 } else if (w->shift == 4) {
4476 e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
4477 e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
4478 req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
4479 } else {
4480 pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
4481 return -EINVAL;
4482 }
4483
4484 if (tomtom->comp_enabled[COMPANDER_1])
4485 pa_settle_time = TOMTOM_HPH_PA_SETTLE_COMP_ON;
4486
4487 switch (event) {
4488 case SND_SOC_DAPM_PRE_PMU:
4489 set_bit(HPH_DELAY, &tomtom->status_mask);
4490 /* Let MBHC module know PA is turning on */
4491 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_pre_on);
4492 break;
4493
4494 case SND_SOC_DAPM_POST_PMU:
4495 if (test_bit(HPH_DELAY, &tomtom->status_mask)) {
4496 /*
4497 * Make sure to wait 10ms after enabling HPHR_HPHL
4498 * in register 0x1AB
4499 */
4500 usleep_range(pa_settle_time, pa_settle_time + 1000);
4501 clear_bit(HPH_DELAY, &tomtom->status_mask);
4502 pr_debug("%s: sleep %d us after %s PA enable\n",
4503 __func__, pa_settle_time, w->name);
4504 }
4505 if (!high_perf_mode && !tomtom->uhqa_mode) {
4506 wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
4507 req_clsh_state,
4508 WCD9XXX_CLSH_REQ_ENABLE,
4509 WCD9XXX_CLSH_EVENT_POST_PA);
4510 }
4511 break;
4512
4513 case SND_SOC_DAPM_PRE_PMD:
4514 set_bit(HPH_DELAY, &tomtom->status_mask);
4515 break;
4516
4517 case SND_SOC_DAPM_POST_PMD:
4518 /* Let MBHC module know PA turned off */
4519 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_post_off);
4520 if (test_bit(HPH_DELAY, &tomtom->status_mask)) {
4521 /*
4522 * Make sure to wait 10ms after disabling HPHR_HPHL
4523 * in register 0x1AB
4524 */
4525 usleep_range(pa_settle_time, pa_settle_time + 1000);
4526 clear_bit(HPH_DELAY, &tomtom->status_mask);
4527 pr_debug("%s: sleep %d us after %s PA disable\n",
4528 __func__, pa_settle_time, w->name);
4529 }
4530
4531 break;
4532 }
4533 return 0;
4534}
4535
4536static int tomtom_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
4537 struct snd_kcontrol *kcontrol, int event)
4538{
4539 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4540 int ret = 0;
4541
4542 switch (event) {
4543 case SND_SOC_DAPM_PRE_PMU:
4544 ret = tomtom_hph_pa_event(w, kcontrol, event);
4545 break;
4546 case SND_SOC_DAPM_POST_PMU:
4547 if ((snd_soc_read(codec, TOMTOM_A_RX_HPH_L_DAC_CTL) & 0x80) &&
4548 (snd_soc_read(codec, TOMTOM_A_RX_HPH_R_DAC_CTL)
4549 & 0x80)) {
4550 snd_soc_update_bits(codec,
4551 TOMTOM_A_RX_HPH_CNP_EN, 0x30, 0x30);
4552 msleep(30);
4553 }
4554 ret = tomtom_hph_pa_event(w, kcontrol, event);
4555 break;
4556 case SND_SOC_DAPM_PRE_PMD:
4557 if (w->shift == 5) {
4558 snd_soc_update_bits(codec,
4559 TOMTOM_A_RX_HPH_CNP_EN, 0x30, 0x00);
4560 msleep(40);
4561 snd_soc_update_bits(codec,
4562 TOMTOM_A_TX_7_MBHC_EN, 0x80, 00);
4563 ret |= tomtom_codec_enable_anc(w, kcontrol, event);
4564 }
4565 break;
4566 case SND_SOC_DAPM_POST_PMD:
4567 ret = tomtom_hph_pa_event(w, kcontrol, event);
4568 break;
4569 }
4570 return ret;
4571}
4572
4573static const struct snd_soc_dapm_widget tomtom_dapm_i2s_widgets[] = {
4574 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TOMTOM_A_CDC_CLK_RX_I2S_CTL,
4575 4, 0, NULL, 0),
4576 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TOMTOM_A_CDC_CLK_TX_I2S_CTL, 4,
4577 0, NULL, 0),
4578};
4579
4580static int tomtom_lineout_dac_event(struct snd_soc_dapm_widget *w,
4581 struct snd_kcontrol *kcontrol, int event)
4582{
4583 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4584 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
4585
4586 pr_debug("%s %s %d\n", __func__, w->name, event);
4587
4588 switch (event) {
4589 case SND_SOC_DAPM_PRE_PMU:
4590 wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
4591 WCD9XXX_CLSH_STATE_LO,
4592 WCD9XXX_CLSH_REQ_ENABLE,
4593 WCD9XXX_CLSH_EVENT_PRE_DAC);
4594 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
4595 break;
4596
4597 case SND_SOC_DAPM_POST_PMD:
4598 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
4599 wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
4600 WCD9XXX_CLSH_STATE_LO,
4601 WCD9XXX_CLSH_REQ_DISABLE,
4602 WCD9XXX_CLSH_EVENT_POST_PA);
4603 break;
4604 }
4605 return 0;
4606}
4607
4608static int tomtom_spk_dac_event(struct snd_soc_dapm_widget *w,
4609 struct snd_kcontrol *kcontrol, int event)
4610{
4611 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4612
4613 pr_debug("%s %s %d\n", __func__, w->name, event);
4614
4615 switch (event) {
4616 case SND_SOC_DAPM_PRE_PMU:
4617 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
4618 0x80, 0x80);
4619 break;
4620 case SND_SOC_DAPM_POST_PMD:
4621 if ((snd_soc_read(codec, w->reg) & 0x03) == 0)
4622 snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
4623 0x80, 0x00);
4624 break;
4625 }
4626 return 0;
4627}
4628
4629static const struct snd_soc_dapm_route audio_i2s_map[] = {
4630 {"SLIM RX1", NULL, "RX_I2S_CLK"},
4631 {"SLIM RX2", NULL, "RX_I2S_CLK"},
4632 {"SLIM RX3", NULL, "RX_I2S_CLK"},
4633 {"SLIM RX4", NULL, "RX_I2S_CLK"},
4634
4635 {"SLIM TX7 MUX", NULL, "TX_I2S_CLK"},
4636 {"SLIM TX8 MUX", NULL, "TX_I2S_CLK"},
4637 {"SLIM TX9 MUX", NULL, "TX_I2S_CLK"},
4638 {"SLIM TX10 MUX", NULL, "TX_I2S_CLK"},
4639
4640 {"RX_I2S_CLK", NULL, "CDC_I2S_RX_CONN"},
4641};
4642
4643static const struct snd_soc_dapm_route audio_map[] = {
4644 /* SLIMBUS Connections */
4645 {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
4646 {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
4647 {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
4648
4649 /* VI Feedback */
4650 {"AIF4 VI", NULL, "VIONOFF"},
4651 {"VIONOFF", "Switch", "VIINPUT"},
4652
4653 /* MAD */
4654 {"MAD_SEL MUX", "SPE", "MAD_CPE_INPUT"},
4655 {"MAD_SEL MUX", "MSM", "MADINPUT"},
4656 {"MADONOFF", "Switch", "MAD_SEL MUX"},
4657 {"AIF4 MAD", NULL, "MADONOFF"},
4658
4659 /* SLIM_MIXER("AIF1_CAP Mixer"),*/
4660 {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
4661 {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
4662 {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
4663 {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
4664 {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
4665 {"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
4666 {"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
4667 {"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
4668 {"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
4669 {"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
4670 /* SLIM_MIXER("AIF2_CAP Mixer"),*/
4671 {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
4672 {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
4673 {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
4674 {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
4675 {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
4676 {"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
4677 {"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
4678 {"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
4679 {"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
4680 {"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
4681 /* SLIM_MIXER("AIF3_CAP Mixer"),*/
4682 {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
4683 {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
4684 {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
4685 {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
4686 {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
4687 {"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
4688 {"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
4689 {"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
4690 {"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
4691 {"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
4692
4693 {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
4694 {"SLIM TX1 MUX", "RMIX1", "RX1 MIX1"},
4695 {"SLIM TX1 MUX", "RMIX2", "RX2 MIX1"},
4696 {"SLIM TX1 MUX", "RMIX3", "RX3 MIX1"},
4697 {"SLIM TX1 MUX", "RMIX4", "RX4 MIX1"},
4698 {"SLIM TX1 MUX", "RMIX5", "RX5 MIX1"},
4699 {"SLIM TX1 MUX", "RMIX6", "RX6 MIX1"},
4700 {"SLIM TX1 MUX", "RMIX7", "RX7 MIX1"},
4701 {"SLIM TX1 MUX", "RMIX8", "RX8 MIX1"},
4702
4703 {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
4704 {"SLIM TX2 MUX", "RMIX1", "RX1 MIX1"},
4705 {"SLIM TX2 MUX", "RMIX2", "RX2 MIX1"},
4706 {"SLIM TX2 MUX", "RMIX3", "RX3 MIX1"},
4707 {"SLIM TX2 MUX", "RMIX4", "RX4 MIX1"},
4708 {"SLIM TX2 MUX", "RMIX5", "RX5 MIX1"},
4709 {"SLIM TX2 MUX", "RMIX6", "RX6 MIX1"},
4710 {"SLIM TX2 MUX", "RMIX7", "RX7 MIX1"},
4711 {"SLIM TX2 MUX", "RMIX8", "RX8 MIX1"},
4712
4713 {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
4714 {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
4715 {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
4716 {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
4717 {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
4718 {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
4719 {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
4720 {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
4721 {"SLIM TX3 MUX", "RMIX8", "RX8 MIX1"},
4722
4723 {"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
4724 {"SLIM TX4 MUX", "RMIX1", "RX1 MIX1"},
4725 {"SLIM TX4 MUX", "RMIX2", "RX2 MIX1"},
4726 {"SLIM TX4 MUX", "RMIX3", "RX3 MIX1"},
4727 {"SLIM TX4 MUX", "RMIX4", "RX4 MIX1"},
4728 {"SLIM TX4 MUX", "RMIX5", "RX5 MIX1"},
4729 {"SLIM TX4 MUX", "RMIX6", "RX6 MIX1"},
4730 {"SLIM TX4 MUX", "RMIX7", "RX7 MIX1"},
4731 {"SLIM TX4 MUX", "RMIX8", "RX8 MIX1"},
4732
4733 {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
4734 {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
4735 {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
4736 {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
4737 {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
4738 {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
4739 {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
4740 {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
4741 {"SLIM TX5 MUX", "RMIX8", "RX8 MIX1"},
4742
4743 {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
4744
4745 {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
4746 {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
4747 {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
4748 {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
4749 {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
4750 {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
4751 {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
4752 {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
4753 {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
4754 {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
4755 {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
4756 {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
4757 {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
4758 {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
4759 {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
4760 {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
4761 {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
4762
4763 {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
4764 {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
4765 {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
4766 {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
4767 {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
4768 {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
4769 {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
4770 {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
4771 {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
4772 {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
4773
4774 {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
4775 {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
4776 {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
4777 {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
4778 {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
4779 {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
4780 {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
4781 {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
4782 {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
4783 {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
4784
4785 {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
4786 {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
4787 {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
4788 {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
4789 {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
4790 {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
4791 {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
4792 {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
4793 {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
4794 {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
4795
4796 /* Earpiece (RX MIX1) */
4797 {"EAR", NULL, "EAR PA"},
4798 {"EAR PA", NULL, "EAR_PA_MIXER"},
4799 {"EAR_PA_MIXER", NULL, "DAC1"},
4800 {"DAC1", NULL, "RX_BIAS"},
4801
4802 {"ANC EAR", NULL, "ANC EAR PA"},
4803 {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
4804 {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
4805 {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
4806
4807 /* Headset (RX MIX1 and RX MIX2) */
4808 {"HEADPHONE", NULL, "HPHL"},
4809 {"HEADPHONE", NULL, "HPHR"},
4810
4811 {"HPHL", NULL, "HPHL_PA_MIXER"},
4812 {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
4813 {"HPHL DAC", NULL, "RX_BIAS"},
4814
4815 {"HPHR", NULL, "HPHR_PA_MIXER"},
4816 {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
4817 {"HPHR DAC", NULL, "RX_BIAS"},
4818
4819 {"ANC HEADPHONE", NULL, "ANC HPHL"},
4820 {"ANC HEADPHONE", NULL, "ANC HPHR"},
4821
4822 {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
4823 {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
4824
4825 {"ANC1 MUX", "ADC1", "ADC1"},
4826 {"ANC1 MUX", "ADC2", "ADC2"},
4827 {"ANC1 MUX", "ADC3", "ADC3"},
4828 {"ANC1 MUX", "ADC4", "ADC4"},
4829 {"ANC1 MUX", "ADC5", "ADC5"},
4830 {"ANC1 MUX", "ADC6", "ADC6"},
4831 {"ANC1 MUX", "DMIC1", "DMIC1"},
4832 {"ANC1 MUX", "DMIC2", "DMIC2"},
4833 {"ANC1 MUX", "DMIC3", "DMIC3"},
4834 {"ANC1 MUX", "DMIC4", "DMIC4"},
4835 {"ANC1 MUX", "DMIC5", "DMIC5"},
4836 {"ANC1 MUX", "DMIC6", "DMIC6"},
4837 {"ANC2 MUX", "ADC1", "ADC1"},
4838 {"ANC2 MUX", "ADC2", "ADC2"},
4839 {"ANC2 MUX", "ADC3", "ADC3"},
4840 {"ANC2 MUX", "ADC4", "ADC4"},
4841 {"ANC2 MUX", "ADC5", "ADC5"},
4842 {"ANC2 MUX", "ADC6", "ADC6"},
4843 {"ANC2 MUX", "DMIC1", "DMIC1"},
4844 {"ANC2 MUX", "DMIC2", "DMIC2"},
4845 {"ANC2 MUX", "DMIC3", "DMIC3"},
4846 {"ANC2 MUX", "DMIC4", "DMIC4"},
4847 {"ANC2 MUX", "DMIC5", "DMIC5"},
4848 {"ANC2 MUX", "DMIC6", "DMIC6"},
4849
4850 {"ANC HPHR", NULL, "CDC_CONN"},
4851
4852 {"DAC1", "Switch", "CLASS_H_DSM MUX"},
4853 {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
4854 {"HPHR DAC", NULL, "RX2 CHAIN"},
4855
4856 {"LINEOUT1", NULL, "LINEOUT1 PA"},
4857 {"LINEOUT2", NULL, "LINEOUT2 PA"},
4858 {"LINEOUT3", NULL, "LINEOUT3 PA"},
4859 {"LINEOUT4", NULL, "LINEOUT4 PA"},
4860 {"SPK_OUT", NULL, "SPK PA"},
4861 {"SPK_OUT", NULL, "SPK2 PA"},
4862
4863 {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
4864 {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
4865
4866 {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
4867 {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
4868
4869 {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
4870 {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
4871
4872 {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
4873 {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
4874
4875 {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
4876
4877 {"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
4878 {"RDAC5 MUX", "DEM4", "RX4 MIX1"},
4879
4880 {"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
4881
4882 {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
4883
4884 {"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
4885 {"RDAC7 MUX", "DEM6", "RX6 MIX1"},
4886
4887 {"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
4888
4889 {"SPK PA", NULL, "SPK DAC"},
4890 {"SPK DAC", NULL, "RX7 MIX2"},
4891 {"SPK DAC", NULL, "VDD_SPKDRV"},
4892
4893 {"SPK2 PA", NULL, "SPK2 DAC"},
4894 {"SPK2 DAC", NULL, "RX8 MIX1"},
4895 {"SPK2 DAC", NULL, "VDD_SPKDRV2"},
4896
4897 {"CLASS_H_DSM MUX", "DSM_HPHL_RX1", "RX1 CHAIN"},
4898
4899 {"RX1 INTERP", NULL, "RX1 MIX2"},
4900 {"RX1 CHAIN", NULL, "RX1 INTERP"},
4901 {"RX2 INTERP", NULL, "RX2 MIX2"},
4902 {"RX2 CHAIN", NULL, "RX2 INTERP"},
4903 {"RX1 MIX2", NULL, "ANC1 MUX"},
4904 {"RX2 MIX2", NULL, "ANC2 MUX"},
4905
4906 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
4907 {"LINEOUT2 DAC", NULL, "RX_BIAS"},
4908 {"LINEOUT3 DAC", NULL, "RX_BIAS"},
4909 {"LINEOUT4 DAC", NULL, "RX_BIAS"},
4910 {"SPK DAC", NULL, "RX_BIAS"},
4911 {"SPK2 DAC", NULL, "RX_BIAS"},
4912
4913 {"RX7 MIX1", NULL, "COMP0_CLK"},
4914 {"RX8 MIX1", NULL, "COMP0_CLK"},
4915 {"RX1 MIX1", NULL, "COMP1_CLK"},
4916 {"RX2 MIX1", NULL, "COMP1_CLK"},
4917 {"RX3 MIX1", NULL, "COMP2_CLK"},
4918 {"RX5 MIX1", NULL, "COMP2_CLK"},
4919
4920 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
4921 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
4922 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
4923 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
4924 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
4925 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
4926 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
4927 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
4928 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
4929 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
4930 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
4931 {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
4932 {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
4933 {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
4934 {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
4935 {"RX8 MIX1", NULL, "RX8 MIX1 INP1"},
4936 {"RX8 MIX1", NULL, "RX8 MIX1 INP2"},
4937 {"RX1 MIX2", NULL, "RX1 MIX1"},
4938 {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
4939 {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
4940 {"RX2 MIX2", NULL, "RX2 MIX1"},
4941 {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
4942 {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
4943 {"RX7 MIX2", NULL, "RX7 MIX1"},
4944 {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
4945 {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
4946
4947 /* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
4948 {"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
4949 {"SLIM RX2 MUX", "AIF1_PB", "AIF1 PB"},
4950 {"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
4951 {"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
4952 {"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
4953 {"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
4954 {"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
4955 {"SLIM RX8 MUX", "AIF1_PB", "AIF1 PB"},
4956 /* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
4957 {"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
4958 {"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
4959 {"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
4960 {"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
4961 {"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
4962 {"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
4963 {"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
4964 {"SLIM RX8 MUX", "AIF2_PB", "AIF2 PB"},
4965 /* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
4966 {"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
4967 {"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
4968 {"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
4969 {"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
4970 {"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
4971 {"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
4972 {"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
4973 {"SLIM RX8 MUX", "AIF3_PB", "AIF3 PB"},
4974
4975 {"SLIM RX1", NULL, "SLIM RX1 MUX"},
4976 {"SLIM RX2", NULL, "SLIM RX2 MUX"},
4977 {"SLIM RX3", NULL, "SLIM RX3 MUX"},
4978 {"SLIM RX4", NULL, "SLIM RX4 MUX"},
4979 {"SLIM RX5", NULL, "SLIM RX5 MUX"},
4980 {"SLIM RX6", NULL, "SLIM RX6 MUX"},
4981 {"SLIM RX7", NULL, "SLIM RX7 MUX"},
4982 {"SLIM RX8", NULL, "SLIM RX8 MUX"},
4983
4984 {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
4985 {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
4986 {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
4987 {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
4988 {"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
4989 {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
4990 {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
4991 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
4992 {"RX1 MIX1 INP1", "IIR2", "IIR2"},
4993 {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
4994 {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
4995 {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
4996 {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
4997 {"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
4998 {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
4999 {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
5000 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
5001 {"RX1 MIX1 INP2", "IIR2", "IIR2"},
5002 {"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
5003 {"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
5004 {"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
5005 {"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
5006 {"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
5007 {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
5008 {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
5009 {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
5010 {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
5011 {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
5012 {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
5013 {"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
5014 {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
5015 {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
5016 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
5017 {"RX2 MIX1 INP1", "IIR2", "IIR2"},
5018 {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
5019 {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
5020 {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
5021 {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
5022 {"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
5023 {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
5024 {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
5025 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
5026 {"RX2 MIX1 INP2", "IIR2", "IIR2"},
5027 {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
5028 {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
5029 {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
5030 {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
5031 {"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
5032 {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
5033 {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
5034 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
5035 {"RX3 MIX1 INP1", "IIR2", "IIR2"},
5036 {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
5037 {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
5038 {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
5039 {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
5040 {"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
5041 {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
5042 {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
5043 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
5044 {"RX3 MIX1 INP2", "IIR2", "IIR2"},
5045 {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
5046 {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
5047 {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
5048 {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
5049 {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
5050 {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
5051 {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
5052 {"RX4 MIX1 INP1", "IIR1", "IIR1"},
5053 {"RX4 MIX1 INP1", "IIR2", "IIR2"},
5054 {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
5055 {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
5056 {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
5057 {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
5058 {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
5059 {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
5060 {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
5061 {"RX4 MIX1 INP2", "IIR1", "IIR1"},
5062 {"RX4 MIX1 INP2", "IIR2", "IIR2"},
5063 {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
5064 {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
5065 {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
5066 {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
5067 {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
5068 {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
5069 {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
5070 {"RX5 MIX1 INP1", "IIR1", "IIR1"},
5071 {"RX5 MIX1 INP1", "IIR2", "IIR2"},
5072 {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
5073 {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
5074 {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
5075 {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
5076 {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
5077 {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
5078 {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
5079 {"RX5 MIX1 INP2", "IIR1", "IIR1"},
5080 {"RX5 MIX1 INP2", "IIR2", "IIR2"},
5081 {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
5082 {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
5083 {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
5084 {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
5085 {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
5086 {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
5087 {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
5088 {"RX6 MIX1 INP1", "IIR1", "IIR1"},
5089 {"RX6 MIX1 INP1", "IIR2", "IIR2"},
5090 {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
5091 {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
5092 {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
5093 {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
5094 {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
5095 {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
5096 {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
5097 {"RX6 MIX1 INP2", "IIR1", "IIR1"},
5098 {"RX6 MIX1 INP2", "IIR2", "IIR2"},
5099 {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
5100 {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
5101 {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
5102 {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
5103 {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
5104 {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
5105 {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
5106 {"RX7 MIX1 INP1", "IIR1", "IIR1"},
5107 {"RX7 MIX1 INP1", "IIR2", "IIR2"},
5108 {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
5109 {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
5110 {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
5111 {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
5112 {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
5113 {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
5114 {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
5115 {"RX7 MIX1 INP2", "IIR1", "IIR1"},
5116 {"RX7 MIX1 INP2", "IIR2", "IIR2"},
5117 {"RX8 MIX1 INP1", "RX1", "SLIM RX1"},
5118 {"RX8 MIX1 INP1", "RX2", "SLIM RX2"},
5119 {"RX8 MIX1 INP1", "RX3", "SLIM RX3"},
5120 {"RX8 MIX1 INP1", "RX4", "SLIM RX4"},
5121 {"RX8 MIX1 INP1", "RX5", "SLIM RX5"},
5122 {"RX8 MIX1 INP1", "RX6", "SLIM RX6"},
5123 {"RX8 MIX1 INP1", "RX7", "SLIM RX7"},
5124 {"RX8 MIX1 INP1", "RX8", "SLIM RX8"},
5125 {"RX8 MIX1 INP1", "IIR1", "IIR1"},
5126 {"RX8 MIX1 INP1", "IIR2", "IIR2"},
5127 {"RX8 MIX1 INP2", "RX1", "SLIM RX1"},
5128 {"RX8 MIX1 INP2", "RX2", "SLIM RX2"},
5129 {"RX8 MIX1 INP2", "RX3", "SLIM RX3"},
5130 {"RX8 MIX1 INP2", "RX4", "SLIM RX4"},
5131 {"RX8 MIX1 INP2", "RX5", "SLIM RX5"},
5132 {"RX8 MIX1 INP2", "RX6", "SLIM RX6"},
5133 {"RX8 MIX1 INP2", "RX7", "SLIM RX7"},
5134 {"RX8 MIX1 INP2", "RX8", "SLIM RX8"},
5135 {"RX8 MIX1 INP2", "IIR1", "IIR1"},
5136 {"RX8 MIX1 INP2", "IIR2", "IIR2"},
5137
5138 /* IIR1, IIR2 inputs to Second RX Mixer on RX1, RX2 and RX7 chains. */
5139 {"RX1 MIX2 INP1", "IIR1", "IIR1"},
5140 {"RX1 MIX2 INP2", "IIR1", "IIR1"},
5141 {"RX2 MIX2 INP1", "IIR1", "IIR1"},
5142 {"RX2 MIX2 INP2", "IIR1", "IIR1"},
5143 {"RX7 MIX2 INP1", "IIR1", "IIR1"},
5144 {"RX7 MIX2 INP2", "IIR1", "IIR1"},
5145 {"RX1 MIX2 INP1", "IIR2", "IIR2"},
5146 {"RX1 MIX2 INP2", "IIR2", "IIR2"},
5147 {"RX2 MIX2 INP1", "IIR2", "IIR2"},
5148 {"RX2 MIX2 INP2", "IIR2", "IIR2"},
5149 {"RX7 MIX2 INP1", "IIR2", "IIR2"},
5150 {"RX7 MIX2 INP2", "IIR2", "IIR2"},
5151
5152 /* Decimator Inputs */
5153 {"DEC1 MUX", "DMIC1", "DMIC1"},
5154 {"DEC1 MUX", "ADC6", "ADC6"},
5155 {"DEC1 MUX", NULL, "CDC_CONN"},
5156 {"DEC2 MUX", "DMIC2", "DMIC2"},
5157 {"DEC2 MUX", "ADC5", "ADC5"},
5158 {"DEC2 MUX", NULL, "CDC_CONN"},
5159 {"DEC3 MUX", "DMIC3", "DMIC3"},
5160 {"DEC3 MUX", "ADC4", "ADC4"},
5161 {"DEC3 MUX", NULL, "CDC_CONN"},
5162 {"DEC4 MUX", "DMIC4", "DMIC4"},
5163 {"DEC4 MUX", "ADC3", "ADC3"},
5164 {"DEC4 MUX", NULL, "CDC_CONN"},
5165 {"DEC5 MUX", "DMIC5", "DMIC5"},
5166 {"DEC5 MUX", "ADC2", "ADC2"},
5167 {"DEC5 MUX", NULL, "CDC_CONN"},
5168 {"DEC6 MUX", "DMIC6", "DMIC6"},
5169 {"DEC6 MUX", "ADC1", "ADC1"},
5170 {"DEC6 MUX", NULL, "CDC_CONN"},
5171 {"DEC7 MUX", "DMIC1", "DMIC1"},
5172 {"DEC7 MUX", "DMIC6", "DMIC6"},
5173 {"DEC7 MUX", "ADC1", "ADC1"},
5174 {"DEC7 MUX", "ADC6", "ADC6"},
5175 {"DEC7 MUX", "ANC1_FB", "ANC1 MUX"},
5176 {"DEC7 MUX", "ANC2_FB", "ANC2 MUX"},
5177 {"DEC7 MUX", NULL, "CDC_CONN"},
5178 {"DEC8 MUX", "DMIC2", "DMIC2"},
5179 {"DEC8 MUX", "DMIC5", "DMIC5"},
5180 {"DEC8 MUX", "ADC2", "ADC2"},
5181 {"DEC8 MUX", "ADC5", "ADC5"},
5182 {"DEC8 MUX", "ANC1_FB", "ANC1 MUX"},
5183 {"DEC8 MUX", "ANC2_FB", "ANC2 MUX"},
5184 {"DEC8 MUX", NULL, "CDC_CONN"},
5185 {"DEC9 MUX", "DMIC4", "DMIC4"},
5186 {"DEC9 MUX", "DMIC5", "DMIC5"},
5187 {"DEC9 MUX", "ADC2", "ADC2"},
5188 {"DEC9 MUX", "ADC3", "ADC3"},
5189 {"DEC9 MUX", "ANC1_FB", "ANC1 MUX"},
5190 {"DEC9 MUX", "ANC2_FB", "ANC2 MUX"},
5191 {"DEC9 MUX", NULL, "CDC_CONN"},
5192 {"DEC10 MUX", "DMIC3", "DMIC3"},
5193 {"DEC10 MUX", "DMIC6", "DMIC6"},
5194 {"DEC10 MUX", "ADC1", "ADC1"},
5195 {"DEC10 MUX", "ADC4", "ADC4"},
5196 {"DEC10 MUX", "ANC1_FB", "ANC1 MUX"},
5197 {"DEC10 MUX", "ANC2_FB", "ANC2 MUX"},
5198 {"DEC10 MUX", NULL, "CDC_CONN"},
5199
5200 /* ADC Connections */
5201 {"ADC1", NULL, "AMIC1"},
5202 {"ADC2", NULL, "AMIC2"},
5203 {"ADC3", NULL, "AMIC3"},
5204 {"ADC4", NULL, "AMIC4"},
5205 {"ADC5", NULL, "AMIC5"},
5206 {"ADC6", NULL, "AMIC6"},
5207
5208 /* AUX PGA Connections */
5209 {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
5210 {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
5211 {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
5212 {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
5213 {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
5214 {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
5215 {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
5216 {"AUX_PGA_Left", NULL, "AMIC5"},
5217 {"AUX_PGA_Right", NULL, "AMIC6"},
5218
5219 {"IIR1", NULL, "IIR1 INP1 MUX"},
5220 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
5221 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
5222 {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
5223 {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
5224 {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
5225 {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
5226 {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
5227 {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
5228 {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
5229 {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
5230 {"IIR1 INP1 MUX", "RX1", "SLIM RX1"},
5231 {"IIR1 INP1 MUX", "RX2", "SLIM RX2"},
5232 {"IIR1 INP1 MUX", "RX3", "SLIM RX3"},
5233 {"IIR1 INP1 MUX", "RX4", "SLIM RX4"},
5234 {"IIR1 INP1 MUX", "RX5", "SLIM RX5"},
5235 {"IIR1 INP1 MUX", "RX6", "SLIM RX6"},
5236 {"IIR1 INP1 MUX", "RX7", "SLIM RX7"},
5237
5238 {"IIR2", NULL, "IIR2 INP1 MUX"},
5239 {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
5240 {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
5241 {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
5242 {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
5243 {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
5244 {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
5245 {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
5246 {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
5247 {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
5248 {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
5249 {"IIR2 INP1 MUX", "RX1", "SLIM RX1"},
5250 {"IIR2 INP1 MUX", "RX2", "SLIM RX2"},
5251 {"IIR2 INP1 MUX", "RX3", "SLIM RX3"},
5252 {"IIR2 INP1 MUX", "RX4", "SLIM RX4"},
5253 {"IIR2 INP1 MUX", "RX5", "SLIM RX5"},
5254 {"IIR2 INP1 MUX", "RX6", "SLIM RX6"},
5255 {"IIR2 INP1 MUX", "RX7", "SLIM RX7"},
5256
5257 {"IIR1", NULL, "IIR1 INP2 MUX"},
5258 {"IIR1 INP2 MUX", "DEC1", "DEC1 MUX"},
5259 {"IIR1 INP2 MUX", "DEC2", "DEC2 MUX"},
5260 {"IIR1 INP2 MUX", "DEC3", "DEC3 MUX"},
5261 {"IIR1 INP2 MUX", "DEC4", "DEC4 MUX"},
5262 {"IIR1 INP2 MUX", "DEC5", "DEC5 MUX"},
5263 {"IIR1 INP2 MUX", "DEC6", "DEC6 MUX"},
5264 {"IIR1 INP2 MUX", "DEC7", "DEC7 MUX"},
5265 {"IIR1 INP2 MUX", "DEC8", "DEC8 MUX"},
5266 {"IIR1 INP2 MUX", "DEC9", "DEC9 MUX"},
5267 {"IIR1 INP2 MUX", "DEC10", "DEC10 MUX"},
5268 {"IIR1 INP2 MUX", "RX1", "SLIM RX1"},
5269 {"IIR1 INP2 MUX", "RX2", "SLIM RX2"},
5270 {"IIR1 INP2 MUX", "RX3", "SLIM RX3"},
5271 {"IIR1 INP2 MUX", "RX4", "SLIM RX4"},
5272 {"IIR1 INP2 MUX", "RX5", "SLIM RX5"},
5273 {"IIR1 INP2 MUX", "RX6", "SLIM RX6"},
5274 {"IIR1 INP2 MUX", "RX7", "SLIM RX7"},
5275
5276 {"IIR2", NULL, "IIR2 INP2 MUX"},
5277 {"IIR2 INP2 MUX", "DEC1", "DEC1 MUX"},
5278 {"IIR2 INP2 MUX", "DEC2", "DEC2 MUX"},
5279 {"IIR2 INP2 MUX", "DEC3", "DEC3 MUX"},
5280 {"IIR2 INP2 MUX", "DEC4", "DEC4 MUX"},
5281 {"IIR2 INP2 MUX", "DEC5", "DEC5 MUX"},
5282 {"IIR2 INP2 MUX", "DEC6", "DEC6 MUX"},
5283 {"IIR2 INP2 MUX", "DEC7", "DEC7 MUX"},
5284 {"IIR2 INP2 MUX", "DEC8", "DEC8 MUX"},
5285 {"IIR2 INP2 MUX", "DEC9", "DEC9 MUX"},
5286 {"IIR2 INP2 MUX", "DEC10", "DEC10 MUX"},
5287 {"IIR2 INP2 MUX", "RX1", "SLIM RX1"},
5288 {"IIR2 INP2 MUX", "RX2", "SLIM RX2"},
5289 {"IIR2 INP2 MUX", "RX3", "SLIM RX3"},
5290 {"IIR2 INP2 MUX", "RX4", "SLIM RX4"},
5291 {"IIR2 INP2 MUX", "RX5", "SLIM RX5"},
5292 {"IIR2 INP2 MUX", "RX6", "SLIM RX6"},
5293 {"IIR2 INP2 MUX", "RX7", "SLIM RX7"},
5294
5295 {"IIR1", NULL, "IIR1 INP3 MUX"},
5296 {"IIR1 INP3 MUX", "DEC1", "DEC1 MUX"},
5297 {"IIR1 INP3 MUX", "DEC2", "DEC2 MUX"},
5298 {"IIR1 INP3 MUX", "DEC3", "DEC3 MUX"},
5299 {"IIR1 INP3 MUX", "DEC4", "DEC4 MUX"},
5300 {"IIR1 INP3 MUX", "DEC5", "DEC5 MUX"},
5301 {"IIR1 INP3 MUX", "DEC6", "DEC6 MUX"},
5302 {"IIR1 INP3 MUX", "DEC7", "DEC7 MUX"},
5303 {"IIR1 INP3 MUX", "DEC8", "DEC8 MUX"},
5304 {"IIR1 INP3 MUX", "DEC9", "DEC9 MUX"},
5305 {"IIR1 INP3 MUX", "DEC10", "DEC10 MUX"},
5306 {"IIR1 INP3 MUX", "RX1", "SLIM RX1"},
5307 {"IIR1 INP3 MUX", "RX2", "SLIM RX2"},
5308 {"IIR1 INP3 MUX", "RX3", "SLIM RX3"},
5309 {"IIR1 INP3 MUX", "RX4", "SLIM RX4"},
5310 {"IIR1 INP3 MUX", "RX5", "SLIM RX5"},
5311 {"IIR1 INP3 MUX", "RX6", "SLIM RX6"},
5312 {"IIR1 INP3 MUX", "RX7", "SLIM RX7"},
5313
5314 {"IIR2", NULL, "IIR2 INP3 MUX"},
5315 {"IIR2 INP3 MUX", "DEC1", "DEC1 MUX"},
5316 {"IIR2 INP3 MUX", "DEC2", "DEC2 MUX"},
5317 {"IIR2 INP3 MUX", "DEC3", "DEC3 MUX"},
5318 {"IIR2 INP3 MUX", "DEC4", "DEC4 MUX"},
5319 {"IIR2 INP3 MUX", "DEC5", "DEC5 MUX"},
5320 {"IIR2 INP3 MUX", "DEC6", "DEC6 MUX"},
5321 {"IIR2 INP3 MUX", "DEC7", "DEC7 MUX"},
5322 {"IIR2 INP3 MUX", "DEC8", "DEC8 MUX"},
5323 {"IIR2 INP3 MUX", "DEC9", "DEC9 MUX"},
5324 {"IIR2 INP3 MUX", "DEC10", "DEC10 MUX"},
5325 {"IIR2 INP3 MUX", "RX1", "SLIM RX1"},
5326 {"IIR2 INP3 MUX", "RX2", "SLIM RX2"},
5327 {"IIR2 INP3 MUX", "RX3", "SLIM RX3"},
5328 {"IIR2 INP3 MUX", "RX4", "SLIM RX4"},
5329 {"IIR2 INP3 MUX", "RX5", "SLIM RX5"},
5330 {"IIR2 INP3 MUX", "RX6", "SLIM RX6"},
5331 {"IIR2 INP3 MUX", "RX7", "SLIM RX7"},
5332
5333 {"IIR1", NULL, "IIR1 INP4 MUX"},
5334 {"IIR1 INP4 MUX", "DEC1", "DEC1 MUX"},
5335 {"IIR1 INP4 MUX", "DEC2", "DEC2 MUX"},
5336 {"IIR1 INP4 MUX", "DEC3", "DEC3 MUX"},
5337 {"IIR1 INP4 MUX", "DEC4", "DEC4 MUX"},
5338 {"IIR1 INP4 MUX", "DEC5", "DEC5 MUX"},
5339 {"IIR1 INP4 MUX", "DEC6", "DEC6 MUX"},
5340 {"IIR1 INP4 MUX", "DEC7", "DEC7 MUX"},
5341 {"IIR1 INP4 MUX", "DEC8", "DEC8 MUX"},
5342 {"IIR1 INP4 MUX", "DEC9", "DEC9 MUX"},
5343 {"IIR1 INP4 MUX", "DEC10", "DEC10 MUX"},
5344 {"IIR1 INP4 MUX", "RX1", "SLIM RX1"},
5345 {"IIR1 INP4 MUX", "RX2", "SLIM RX2"},
5346 {"IIR1 INP4 MUX", "RX3", "SLIM RX3"},
5347 {"IIR1 INP4 MUX", "RX4", "SLIM RX4"},
5348 {"IIR1 INP4 MUX", "RX5", "SLIM RX5"},
5349 {"IIR1 INP4 MUX", "RX6", "SLIM RX6"},
5350 {"IIR1 INP4 MUX", "RX7", "SLIM RX7"},
5351
5352 {"IIR2", NULL, "IIR2 INP4 MUX"},
5353 {"IIR2 INP4 MUX", "DEC1", "DEC1 MUX"},
5354 {"IIR2 INP4 MUX", "DEC2", "DEC2 MUX"},
5355 {"IIR2 INP4 MUX", "DEC3", "DEC3 MUX"},
5356 {"IIR2 INP4 MUX", "DEC4", "DEC4 MUX"},
5357 {"IIR2 INP4 MUX", "DEC5", "DEC5 MUX"},
5358 {"IIR2 INP4 MUX", "DEC6", "DEC6 MUX"},
5359 {"IIR2 INP4 MUX", "DEC7", "DEC7 MUX"},
5360 {"IIR2 INP4 MUX", "DEC8", "DEC8 MUX"},
5361 {"IIR2 INP4 MUX", "DEC9", "DEC9 MUX"},
5362 {"IIR2 INP4 MUX", "DEC10", "DEC10 MUX"},
5363 {"IIR2 INP4 MUX", "RX1", "SLIM RX1"},
5364 {"IIR2 INP4 MUX", "RX2", "SLIM RX2"},
5365 {"IIR2 INP4 MUX", "RX3", "SLIM RX3"},
5366 {"IIR2 INP4 MUX", "RX4", "SLIM RX4"},
5367 {"IIR2 INP4 MUX", "RX5", "SLIM RX5"},
5368 {"IIR2 INP4 MUX", "RX6", "SLIM RX6"},
5369 {"IIR2 INP4 MUX", "RX7", "SLIM RX7"},
5370
5371 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
5372 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
5373 {"MIC BIAS1 External", NULL, "LDO_H"},
5374 {"MIC BIAS2 Internal1", NULL, "LDO_H"},
5375 {"MIC BIAS2 Internal2", NULL, "LDO_H"},
5376 {"MIC BIAS2 Internal3", NULL, "LDO_H"},
5377 {"MIC BIAS2 External", NULL, "LDO_H"},
5378 {"MIC BIAS3 Internal1", NULL, "LDO_H"},
5379 {"MIC BIAS3 Internal2", NULL, "LDO_H"},
5380 {"MIC BIAS3 External", NULL, "LDO_H"},
5381 {"MIC BIAS4 External", NULL, "LDO_H"},
5382 {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"},
5383};
5384
5385static int tomtom_startup(struct snd_pcm_substream *substream,
5386 struct snd_soc_dai *dai)
5387{
5388 pr_debug("%s(): substream = %s stream = %d\n", __func__,
5389 substream->name, substream->stream);
5390
5391 return 0;
5392}
5393
5394static void tomtom_shutdown(struct snd_pcm_substream *substream,
5395 struct snd_soc_dai *dai)
5396{
5397 pr_debug("%s(): substream = %s stream = %d\n", __func__,
5398 substream->name, substream->stream);
5399}
5400
5401int tomtom_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
5402{
5403 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
5404
5405 pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
5406 dapm);
5407
5408 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
5409 if (mclk_enable) {
5410 wcd9xxx_resmgr_get_bandgap(&tomtom->resmgr,
5411 WCD9XXX_BANDGAP_AUDIO_MODE);
5412 wcd9xxx_resmgr_get_clk_block(&tomtom->resmgr, WCD9XXX_CLK_MCLK);
5413 } else {
5414 /* Put clock and BG */
5415 wcd9xxx_resmgr_put_clk_block(&tomtom->resmgr, WCD9XXX_CLK_MCLK);
5416 wcd9xxx_resmgr_put_bandgap(&tomtom->resmgr,
5417 WCD9XXX_BANDGAP_AUDIO_MODE);
5418 }
5419 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
5420
5421 return 0;
5422}
5423
5424static int tomtom_set_dai_sysclk(struct snd_soc_dai *dai,
5425 int clk_id, unsigned int freq, int dir)
5426{
5427 pr_debug("%s\n", __func__);
5428 return 0;
5429}
5430
5431static int tomtom_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
5432{
5433 u8 val = 0;
5434 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(dai->codec);
5435
5436 pr_debug("%s\n", __func__);
5437 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
5438 case SND_SOC_DAIFMT_CBS_CFS:
5439 /* CPU is master */
5440 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
5441 if (dai->id == AIF1_CAP)
5442 snd_soc_update_bits(dai->codec,
5443 TOMTOM_A_CDC_CLK_TX_I2S_CTL,
5444 TOMTOM_I2S_MASTER_MODE_MASK, 0);
5445 else if (dai->id == AIF1_PB)
5446 snd_soc_update_bits(dai->codec,
5447 TOMTOM_A_CDC_CLK_RX_I2S_CTL,
5448 TOMTOM_I2S_MASTER_MODE_MASK, 0);
5449 }
5450 break;
5451 case SND_SOC_DAIFMT_CBM_CFM:
5452 /* CPU is slave */
5453 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
5454 val = TOMTOM_I2S_MASTER_MODE_MASK;
5455 if (dai->id == AIF1_CAP)
5456 snd_soc_update_bits(dai->codec,
5457 TOMTOM_A_CDC_CLK_TX_I2S_CTL, val, val);
5458 else if (dai->id == AIF1_PB)
5459 snd_soc_update_bits(dai->codec,
5460 TOMTOM_A_CDC_CLK_RX_I2S_CTL, val, val);
5461 }
5462 break;
5463 default:
5464 return -EINVAL;
5465 }
5466 return 0;
5467}
5468
5469static int tomtom_set_channel_map(struct snd_soc_dai *dai,
5470 unsigned int tx_num, unsigned int *tx_slot,
5471 unsigned int rx_num, unsigned int *rx_slot)
5472
5473{
5474 struct wcd9xxx_codec_dai_data *dai_data = NULL;
5475 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(dai->codec);
5476 struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
5477
5478 if (!tx_slot || !rx_slot) {
5479 pr_err("%s: Invalid tx_slot=%pK, rx_slot=%pK\n",
5480 __func__, tx_slot, rx_slot);
5481 return -EINVAL;
5482 }
5483 pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n"
5484 "tomtom->intf_type %d\n",
5485 __func__, dai->name, dai->id, tx_num, rx_num,
5486 tomtom->intf_type);
5487
5488 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
5489 wcd9xxx_init_slimslave(core, core->slim->laddr,
5490 tx_num, tx_slot, rx_num, rx_slot);
5491 /*Reserve tx11 and tx12 for VI feedback path*/
5492 dai_data = &tomtom->dai[AIF4_VIFEED];
5493 if (dai_data) {
5494 list_add_tail(&core->tx_chs[TOMTOM_TX11].list,
5495 &dai_data->wcd9xxx_ch_list);
5496 list_add_tail(&core->tx_chs[TOMTOM_TX12].list,
5497 &dai_data->wcd9xxx_ch_list);
5498 }
5499
5500 /* Reserve TX13 for MAD data channel */
5501 dai_data = &tomtom->dai[AIF4_MAD_TX];
5502 if (dai_data)
5503 list_add_tail(&core->tx_chs[TOMTOM_TX13].list,
5504 &dai_data->wcd9xxx_ch_list);
5505 }
5506
5507 return 0;
5508}
5509
5510static int tomtom_get_channel_map(struct snd_soc_dai *dai,
5511 unsigned int *tx_num, unsigned int *tx_slot,
5512 unsigned int *rx_num, unsigned int *rx_slot)
5513
5514{
5515 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(dai->codec);
5516 u32 i = 0;
5517 struct wcd9xxx_ch *ch;
5518
5519 switch (dai->id) {
5520 case AIF1_PB:
5521 case AIF2_PB:
5522 case AIF3_PB:
5523 if (!rx_slot || !rx_num) {
5524 pr_err("%s: Invalid rx_slot %pK or rx_num %pK\n",
5525 __func__, rx_slot, rx_num);
5526 return -EINVAL;
5527 }
5528 list_for_each_entry(ch, &tomtom_p->dai[dai->id].wcd9xxx_ch_list,
5529 list) {
5530 pr_debug("%s: slot_num %u ch->ch_num %d\n",
5531 __func__, i, ch->ch_num);
5532 rx_slot[i++] = ch->ch_num;
5533 }
5534 pr_debug("%s: rx_num %d\n", __func__, i);
5535 *rx_num = i;
5536 break;
5537 case AIF1_CAP:
5538 case AIF2_CAP:
5539 case AIF3_CAP:
5540 case AIF4_VIFEED:
5541 case AIF4_MAD_TX:
5542 if (!tx_slot || !tx_num) {
5543 pr_err("%s: Invalid tx_slot %pK or tx_num %pK\n",
5544 __func__, tx_slot, tx_num);
5545 return -EINVAL;
5546 }
5547 list_for_each_entry(ch, &tomtom_p->dai[dai->id].wcd9xxx_ch_list,
5548 list) {
5549 pr_debug("%s: slot_num %u ch->ch_num %d\n",
5550 __func__, i, ch->ch_num);
5551 tx_slot[i++] = ch->ch_num;
5552 }
5553 pr_debug("%s: tx_num %d\n", __func__, i);
5554 *tx_num = i;
5555 break;
5556
5557 default:
5558 pr_err("%s: Invalid DAI ID %x\n", __func__, dai->id);
5559 break;
5560 }
5561
5562 return 0;
5563}
5564
5565static int tomtom_set_interpolator_rate(struct snd_soc_dai *dai,
5566 u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
5567{
5568 u32 j;
5569 u8 rx_mix1_inp, rx8_mix1_inp;
5570 u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
5571 u16 rx_fs_reg;
5572 u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
5573 struct snd_soc_codec *codec = dai->codec;
5574 struct wcd9xxx_ch *ch;
5575 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
5576 int port_rx_8 = TOMTOM_RX_PORT_START_NUMBER + NUM_INTERPOLATORS - 1;
5577
5578 list_for_each_entry(ch, &tomtom->dai[dai->id].wcd9xxx_ch_list, list) {
5579 /* for RX port starting from 16 instead of 10 like tabla */
5580 rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
5581 TOMTOM_TX_PORT_NUMBER;
5582 rx8_mix1_inp = ch->port + RX8_MIX1_INP_SEL_RX1 -
5583 TOMTOM_RX_PORT_START_NUMBER;
5584 if (((ch->port < port_rx_8) &&
5585 ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
5586 (rx_mix1_inp > RX_MIX1_INP_SEL_RX7))) ||
5587 ((rx8_mix1_inp < RX8_MIX1_INP_SEL_RX1) ||
5588 (rx8_mix1_inp > RX8_MIX1_INP_SEL_RX8))) {
5589 pr_err("%s: Invalid TOMTOM_RX%u port. Dai ID is %d\n",
5590 __func__, rx8_mix1_inp - 2,
5591 dai->id);
5592 return -EINVAL;
5593 }
5594
5595 rx_mix_1_reg_1 = TOMTOM_A_CDC_CONN_RX1_B1_CTL;
5596
5597 for (j = 0; j < NUM_INTERPOLATORS - 1; j++) {
5598 rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
5599
5600 rx_mix_1_reg_1_val = snd_soc_read(codec,
5601 rx_mix_1_reg_1);
5602 rx_mix_1_reg_2_val = snd_soc_read(codec,
5603 rx_mix_1_reg_2);
5604
5605 if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
5606 (((rx_mix_1_reg_1_val >> 4) & 0x0F)
5607 == rx_mix1_inp) ||
5608 ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
5609
5610 rx_fs_reg = TOMTOM_A_CDC_RX1_B5_CTL + 8 * j;
5611
5612 pr_debug("%s: AIF_PB DAI(%d) connected to RX%u\n",
5613 __func__, dai->id, j + 1);
5614
5615 pr_debug("%s: set RX%u sample rate to %u\n",
5616 __func__, j + 1, sample_rate);
5617
5618 snd_soc_update_bits(codec, rx_fs_reg,
5619 0xE0, rx_fs_rate_reg_val);
5620
5621 if (comp_rx_path[j] < COMPANDER_MAX)
5622 tomtom->comp_fs[comp_rx_path[j]]
5623 = compander_fs;
5624 }
5625 if (j < 2)
5626 rx_mix_1_reg_1 += 3;
5627 else
5628 rx_mix_1_reg_1 += 2;
5629 }
5630
5631 /* RX8 interpolator path */
5632 rx_mix_1_reg_1_val = snd_soc_read(codec,
5633 TOMTOM_A_CDC_CONN_RX8_B1_CTL);
5634 if (((rx_mix_1_reg_1_val & 0x0F) == rx8_mix1_inp) ||
5635 (((rx_mix_1_reg_1_val >> 4) & 0x0F) == rx8_mix1_inp)) {
5636 snd_soc_update_bits(codec, TOMTOM_A_CDC_RX8_B5_CTL,
5637 0xE0, rx_fs_rate_reg_val);
5638 pr_debug("%s: AIF_PB DAI(%d) connected to RX%u\n",
5639 __func__, dai->id, NUM_INTERPOLATORS);
5640
5641 pr_debug("%s: set RX%u sample rate to %u\n",
5642 __func__, NUM_INTERPOLATORS,
5643 sample_rate);
5644 if (comp_rx_path[NUM_INTERPOLATORS - 1] < COMPANDER_MAX)
5645 tomtom->comp_fs[comp_rx_path[j]] =
5646 compander_fs;
5647 }
5648 }
5649 return 0;
5650}
5651
5652static int tomtom_set_decimator_rate(struct snd_soc_dai *dai,
5653 u8 tx_fs_rate_reg_val, u32 sample_rate)
5654{
5655 struct snd_soc_codec *codec = dai->codec;
5656 struct wcd9xxx_ch *ch;
5657 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
5658 u32 tx_port;
5659 u16 tx_port_reg, tx_fs_reg;
5660 u8 tx_port_reg_val;
5661 s8 decimator;
5662
5663 list_for_each_entry(ch, &tomtom->dai[dai->id].wcd9xxx_ch_list, list) {
5664
5665 tx_port = ch->port + 1;
5666 pr_debug("%s: dai->id = %d, tx_port = %d",
5667 __func__, dai->id, tx_port);
5668
5669 if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
5670 pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
5671 __func__, tx_port, dai->id);
5672 return -EINVAL;
5673 }
5674
5675 tx_port_reg = TOMTOM_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
5676 tx_port_reg_val = snd_soc_read(codec, tx_port_reg);
5677
5678 decimator = 0;
5679
5680 if ((tx_port >= 1) && (tx_port <= 6)) {
5681
5682 tx_port_reg_val = tx_port_reg_val & 0x0F;
5683 if (tx_port_reg_val == 0x8)
5684 decimator = tx_port;
5685
5686 } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
5687
5688 tx_port_reg_val = tx_port_reg_val & 0x1F;
5689
5690 if ((tx_port_reg_val >= 0x8) &&
5691 (tx_port_reg_val <= 0x11)) {
5692
5693 decimator = (tx_port_reg_val - 0x8) + 1;
5694 }
5695 }
5696
5697 if (decimator) { /* SLIM_TX port has a DEC as input */
5698
5699 tx_fs_reg = TOMTOM_A_CDC_TX1_CLK_FS_CTL +
5700 8 * (decimator - 1);
5701
5702 pr_debug("%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
5703 __func__, decimator, tx_port, sample_rate);
5704
5705 snd_soc_update_bits(codec, tx_fs_reg, 0x07,
5706 tx_fs_rate_reg_val);
5707
5708 } else {
5709 if ((tx_port_reg_val >= 0x1) &&
5710 (tx_port_reg_val <= 0x7)) {
5711
5712 pr_debug("%s: RMIX%u going to SLIM TX%u\n",
5713 __func__, tx_port_reg_val, tx_port);
5714
5715 } else if ((tx_port_reg_val >= 0x8) &&
5716 (tx_port_reg_val <= 0x11)) {
5717
5718 pr_err("%s: ERROR: Should not be here\n",
5719 __func__);
5720 pr_err("%s: ERROR: DEC connected to SLIM TX%u\n",
5721 __func__, tx_port);
5722 return -EINVAL;
5723
5724 } else if (tx_port_reg_val == 0) {
5725 pr_debug("%s: no signal to SLIM TX%u\n",
5726 __func__, tx_port);
5727 } else {
5728 pr_err("%s: ERROR: wrong signal to SLIM TX%u\n",
5729 __func__, tx_port);
5730 pr_err("%s: ERROR: wrong signal = %u\n",
5731 __func__, tx_port_reg_val);
5732 return -EINVAL;
5733 }
5734 }
5735 }
5736 return 0;
5737}
5738
5739static void tomtom_set_rxsb_port_format(struct snd_pcm_hw_params *params,
5740 struct snd_soc_dai *dai)
5741{
5742 struct snd_soc_codec *codec = dai->codec;
5743 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
5744 struct wcd9xxx_codec_dai_data *cdc_dai;
5745 struct wcd9xxx_ch *ch;
5746 int port;
5747 u8 bit_sel;
5748 u16 sb_ctl_reg, field_shift;
5749
5750 switch (params_width(params)) {
5751 case 16:
5752 bit_sel = 0x2;
5753 tomtom_p->dai[dai->id].bit_width = 16;
5754 break;
5755 case 24:
5756 bit_sel = 0x0;
5757 tomtom_p->dai[dai->id].bit_width = 24;
5758 break;
5759 default:
5760 dev_err(codec->dev, "Invalid format\n");
5761 return;
5762 }
5763
5764 cdc_dai = &tomtom_p->dai[dai->id];
5765
5766 list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
5767 port = wcd9xxx_get_slave_port(ch->ch_num);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08005768 if (port < 0 ||
Banajit Goswamide8271c2017-01-18 00:28:59 -08005769 !TOMTOM_VALIDATE_RX_SBPORT_RANGE(port)) {
5770 dev_warn(codec->dev,
5771 "%s: invalid port ID %d returned for RX DAI\n",
5772 __func__, port);
5773 return;
5774 }
5775
5776 port = TOMTOM_CONVERT_RX_SBPORT_ID(port);
5777
5778 if (port <= 3) {
5779 sb_ctl_reg = TOMTOM_A_CDC_CONN_RX_SB_B1_CTL;
5780 field_shift = port << 1;
5781 } else if (port <= 7) {
5782 sb_ctl_reg = TOMTOM_A_CDC_CONN_RX_SB_B2_CTL;
5783 field_shift = (port - 4) << 1;
5784 } else { /* should not happen */
5785 dev_warn(codec->dev,
5786 "%s: bad port ID %d\n", __func__, port);
5787 return;
5788 }
5789
5790 dev_dbg(codec->dev, "%s: sb_ctl_reg %x field_shift %x\n",
5791 __func__, sb_ctl_reg, field_shift);
5792 snd_soc_update_bits(codec, sb_ctl_reg, 0x3 << field_shift,
5793 bit_sel << field_shift);
5794 }
5795}
5796
5797static void tomtom_set_tx_sb_port_format(struct snd_pcm_hw_params *params,
5798 struct snd_soc_dai *dai)
5799{
5800 struct snd_soc_codec *codec = dai->codec;
5801 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
5802 struct wcd9xxx_codec_dai_data *cdc_dai;
5803 struct wcd9xxx_ch *ch;
5804 int port;
5805 u8 bit_sel, bit_shift;
5806 u16 sb_ctl_reg;
5807
5808 switch (params_width(params)) {
5809 case 16:
5810 bit_sel = 0x2;
5811 tomtom_p->dai[dai->id].bit_width = 16;
5812 break;
5813 case 24:
5814 bit_sel = 0x0;
5815 tomtom_p->dai[dai->id].bit_width = 24;
5816 break;
5817 default:
5818 dev_err(codec->dev, "%s: Invalid format %d\n", __func__,
5819 params_width(params));
5820 return;
5821 }
5822
5823 cdc_dai = &tomtom_p->dai[dai->id];
5824
5825 list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
5826 port = wcd9xxx_get_slave_port(ch->ch_num);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08005827 if (port < 0 ||
Banajit Goswamide8271c2017-01-18 00:28:59 -08005828 !TOMTOM_VALIDATE_TX_SBPORT_RANGE(port)) {
5829 dev_warn(codec->dev,
5830 "%s: invalid port ID %d returned for TX DAI\n",
5831 __func__, port);
5832 return;
5833 }
5834
5835 if (port < 6) /* 6 = SLIMBUS TX7 */
5836 bit_shift = TOMTOM_BIT_ADJ_SHIFT_PORT1_6;
5837 else if (port < 10)
5838 bit_shift = TOMTOM_BIT_ADJ_SHIFT_PORT7_10;
5839 else {
5840 dev_warn(codec->dev,
5841 "%s: port ID %d bitwidth is fixed\n",
5842 __func__, port);
5843 return;
5844 }
5845
5846 sb_ctl_reg = (TOMTOM_A_CDC_CONN_TX_SB_B1_CTL + port);
5847
5848 dev_dbg(codec->dev, "%s: reg %x bit_sel %x bit_shift %x\n",
5849 __func__, sb_ctl_reg, bit_sel, bit_shift);
5850 snd_soc_update_bits(codec, sb_ctl_reg, 0x3 <<
5851 bit_shift, bit_sel << bit_shift);
5852 }
5853}
5854
5855static int tomtom_hw_params(struct snd_pcm_substream *substream,
5856 struct snd_pcm_hw_params *params,
5857 struct snd_soc_dai *dai)
5858{
5859 struct snd_soc_codec *codec = dai->codec;
5860 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(dai->codec);
5861 u8 tx_fs_rate, rx_fs_rate, i2s_bit_mode;
5862 u32 compander_fs;
5863 int ret;
5864
5865 pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
5866 dai->name, dai->id, params_rate(params),
5867 params_channels(params));
5868
5869 switch (params_rate(params)) {
5870 case 8000:
5871 tx_fs_rate = 0x00;
5872 rx_fs_rate = 0x00;
5873 compander_fs = COMPANDER_FS_8KHZ;
5874 break;
5875 case 16000:
5876 tx_fs_rate = 0x01;
5877 rx_fs_rate = 0x20;
5878 compander_fs = COMPANDER_FS_16KHZ;
5879 break;
5880 case 32000:
5881 tx_fs_rate = 0x02;
5882 rx_fs_rate = 0x40;
5883 compander_fs = COMPANDER_FS_32KHZ;
5884 break;
5885 case 48000:
5886 tx_fs_rate = 0x03;
5887 rx_fs_rate = 0x60;
5888 compander_fs = COMPANDER_FS_48KHZ;
5889 break;
5890 case 96000:
5891 tx_fs_rate = 0x04;
5892 rx_fs_rate = 0x80;
5893 compander_fs = COMPANDER_FS_96KHZ;
5894 break;
5895 case 192000:
5896 tx_fs_rate = 0x05;
5897 rx_fs_rate = 0xA0;
5898 compander_fs = COMPANDER_FS_192KHZ;
5899 break;
5900 default:
5901 pr_err("%s: Invalid sampling rate %d\n", __func__,
5902 params_rate(params));
5903 return -EINVAL;
5904 }
5905
5906 switch (substream->stream) {
5907 case SNDRV_PCM_STREAM_CAPTURE:
5908 if (dai->id != AIF4_VIFEED &&
5909 dai->id != AIF4_MAD_TX) {
5910 ret = tomtom_set_decimator_rate(dai, tx_fs_rate,
5911 params_rate(params));
5912 if (ret < 0) {
5913 pr_err("%s: set decimator rate failed %d\n",
5914 __func__, ret);
5915 return ret;
5916 }
5917 }
5918
5919 tomtom->dai[dai->id].rate = params_rate(params);
5920
5921 switch (params_format(params)) {
5922 case SNDRV_PCM_FORMAT_S16_LE:
5923 i2s_bit_mode = 0x01;
5924 tomtom->dai[dai->id].bit_width = 16;
5925 break;
5926 case SNDRV_PCM_FORMAT_S24_LE:
5927 tomtom->dai[dai->id].bit_width = 24;
5928 i2s_bit_mode = 0x00;
5929 break;
5930 case SNDRV_PCM_FORMAT_S32_LE:
5931 tomtom->dai[dai->id].bit_width = 32;
5932 i2s_bit_mode = 0x00;
5933 break;
5934 default:
5935 dev_err(codec->dev,
5936 "%s: Invalid format 0x%x\n",
5937 __func__, params_format(params));
5938 return -EINVAL;
5939 }
5940
5941 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
5942 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_TX_I2S_CTL,
5943 0x20, i2s_bit_mode << 5);
5944 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_TX_I2S_CTL,
5945 0x07, tx_fs_rate);
5946 } else {
5947 /* only generic ports can have sample bit adjustment */
5948 if (dai->id != AIF4_VIFEED &&
5949 dai->id != AIF4_MAD_TX)
5950 tomtom_set_tx_sb_port_format(params, dai);
5951 }
5952
5953 break;
5954
5955 case SNDRV_PCM_STREAM_PLAYBACK:
5956 ret = tomtom_set_interpolator_rate(dai, rx_fs_rate,
5957 compander_fs,
5958 params_rate(params));
5959 if (ret < 0) {
5960 pr_err("%s: set decimator rate failed %d\n", __func__,
5961 ret);
5962 return ret;
5963 }
5964 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
5965 switch (params_format(params)) {
5966 case SNDRV_PCM_FORMAT_S16_LE:
5967 snd_soc_update_bits(codec,
5968 TOMTOM_A_CDC_CLK_RX_I2S_CTL,
5969 0x20, 0x20);
5970 break;
5971 case SNDRV_PCM_FORMAT_S32_LE:
5972 snd_soc_update_bits(codec,
5973 TOMTOM_A_CDC_CLK_RX_I2S_CTL,
5974 0x20, 0x00);
5975 break;
5976 default:
5977 pr_err("invalid format\n");
5978 break;
5979 }
5980 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_RX_I2S_CTL,
5981 0x03, (rx_fs_rate >> 0x05));
5982 } else {
5983 tomtom_set_rxsb_port_format(params, dai);
5984 tomtom->dai[dai->id].rate = params_rate(params);
5985 }
5986 break;
5987 default:
5988 pr_err("%s: Invalid stream type %d\n", __func__,
5989 substream->stream);
5990 return -EINVAL;
5991 }
5992
5993 return 0;
5994}
5995
5996static struct snd_soc_dai_ops tomtom_dai_ops = {
5997 .startup = tomtom_startup,
5998 .shutdown = tomtom_shutdown,
5999 .hw_params = tomtom_hw_params,
6000 .set_sysclk = tomtom_set_dai_sysclk,
6001 .set_fmt = tomtom_set_dai_fmt,
6002 .set_channel_map = tomtom_set_channel_map,
6003 .get_channel_map = tomtom_get_channel_map,
6004};
6005
6006static struct snd_soc_dai_driver tomtom_dai[] = {
6007 {
6008 .name = "tomtom_rx1",
6009 .id = AIF1_PB,
6010 .playback = {
6011 .stream_name = "AIF1 Playback",
6012 .rates = WCD9330_RATES,
6013 .formats = TOMTOM_FORMATS_S16_S24_LE,
6014 .rate_max = 192000,
6015 .rate_min = 8000,
6016 .channels_min = 1,
6017 .channels_max = 2,
6018 },
6019 .ops = &tomtom_dai_ops,
6020 },
6021 {
6022 .name = "tomtom_tx1",
6023 .id = AIF1_CAP,
6024 .capture = {
6025 .stream_name = "AIF1 Capture",
6026 .rates = WCD9330_RATES,
6027 .formats = TOMTOM_FORMATS,
6028 .rate_max = 192000,
6029 .rate_min = 8000,
6030 .channels_min = 1,
6031 .channels_max = 4,
6032 },
6033 .ops = &tomtom_dai_ops,
6034 },
6035 {
6036 .name = "tomtom_rx2",
6037 .id = AIF2_PB,
6038 .playback = {
6039 .stream_name = "AIF2 Playback",
6040 .rates = WCD9330_RATES,
6041 .formats = TOMTOM_FORMATS_S16_S24_LE,
6042 .rate_min = 8000,
6043 .rate_max = 192000,
6044 .channels_min = 1,
6045 .channels_max = 2,
6046 },
6047 .ops = &tomtom_dai_ops,
6048 },
6049 {
6050 .name = "tomtom_tx2",
6051 .id = AIF2_CAP,
6052 .capture = {
6053 .stream_name = "AIF2 Capture",
6054 .rates = WCD9330_RATES,
6055 .formats = TOMTOM_FORMATS,
6056 .rate_max = 192000,
6057 .rate_min = 8000,
6058 .channels_min = 1,
6059 .channels_max = 8,
6060 },
6061 .ops = &tomtom_dai_ops,
6062 },
6063 {
6064 .name = "tomtom_rx3",
6065 .id = AIF3_PB,
6066 .playback = {
6067 .stream_name = "AIF3 Playback",
6068 .rates = WCD9330_RATES,
6069 .formats = TOMTOM_FORMATS_S16_S24_LE,
6070 .rate_min = 8000,
6071 .rate_max = 192000,
6072 .channels_min = 1,
6073 .channels_max = 2,
6074 },
6075 .ops = &tomtom_dai_ops,
6076 },
6077 {
6078 .name = "tomtom_tx3",
6079 .id = AIF3_CAP,
6080 .capture = {
6081 .stream_name = "AIF3 Capture",
6082 .rates = WCD9330_RATES,
6083 .formats = TOMTOM_FORMATS,
6084 .rate_max = 48000,
6085 .rate_min = 8000,
6086 .channels_min = 1,
6087 .channels_max = 2,
6088 },
6089 .ops = &tomtom_dai_ops,
6090 },
6091 {
6092 .name = "tomtom_vifeedback",
6093 .id = AIF4_VIFEED,
6094 .capture = {
6095 .stream_name = "VIfeed",
6096 .rates = SNDRV_PCM_RATE_48000,
6097 .formats = TOMTOM_FORMATS,
6098 .rate_max = 48000,
6099 .rate_min = 48000,
6100 .channels_min = 2,
6101 .channels_max = 2,
6102 },
6103 .ops = &tomtom_dai_ops,
6104 },
6105 {
6106 .name = "tomtom_mad1",
6107 .id = AIF4_MAD_TX,
6108 .capture = {
6109 .stream_name = "AIF4 MAD TX",
6110 .rates = SNDRV_PCM_RATE_16000,
6111 .formats = TOMTOM_FORMATS_S16_S24_LE,
6112 .rate_min = 16000,
6113 .rate_max = 16000,
6114 .channels_min = 1,
6115 .channels_max = 1,
6116 },
6117 .ops = &tomtom_dai_ops,
6118 },
6119};
6120
6121static struct snd_soc_dai_driver tomtom_i2s_dai[] = {
6122 {
6123 .name = "tomtom_i2s_rx1",
6124 .id = AIF1_PB,
6125 .playback = {
6126 .stream_name = "AIF1 Playback",
6127 .rates = WCD9330_RATES,
6128 .formats = TOMTOM_FORMATS,
6129 .rate_max = 192000,
6130 .rate_min = 8000,
6131 .channels_min = 1,
6132 .channels_max = 4,
6133 },
6134 .ops = &tomtom_dai_ops,
6135 },
6136 {
6137 .name = "tomtom_i2s_tx1",
6138 .id = AIF1_CAP,
6139 .capture = {
6140 .stream_name = "AIF1 Capture",
6141 .rates = WCD9330_RATES,
6142 .formats = TOMTOM_FORMATS,
6143 .rate_max = 192000,
6144 .rate_min = 8000,
6145 .channels_min = 1,
6146 .channels_max = 4,
6147 },
6148 .ops = &tomtom_dai_ops,
6149 },
6150 {
6151 .name = "tomtom_i2s_rx2",
6152 .id = AIF1_PB,
6153 .playback = {
6154 .stream_name = "AIF2 Playback",
6155 .rates = WCD9330_RATES,
6156 .formats = TOMTOM_FORMATS,
6157 .rate_max = 192000,
6158 .rate_min = 8000,
6159 .channels_min = 1,
6160 .channels_max = 4,
6161 },
6162 .ops = &tomtom_dai_ops,
6163 },
6164 {
6165 .name = "tomtom_i2s_tx2",
6166 .id = AIF1_CAP,
6167 .capture = {
6168 .stream_name = "AIF2 Capture",
6169 .rates = WCD9330_RATES,
6170 .formats = TOMTOM_FORMATS,
6171 .rate_max = 192000,
6172 .rate_min = 8000,
6173 .channels_min = 1,
6174 .channels_max = 4,
6175 },
6176 .ops = &tomtom_dai_ops,
6177 },
6178};
6179
6180static int tomtom_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
6181 bool up)
6182{
6183 int ret = 0;
6184 struct wcd9xxx_ch *ch;
6185
6186 if (up) {
6187 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
6188 ret = wcd9xxx_get_slave_port(ch->ch_num);
6189 if (ret < 0) {
6190 pr_err("%s: Invalid slave port ID: %d\n",
6191 __func__, ret);
6192 ret = -EINVAL;
6193 } else {
6194 set_bit(ret, &dai->ch_mask);
6195 }
6196 }
6197 } else {
6198 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
6199 msecs_to_jiffies(
6200 TOMTOM_SLIM_CLOSE_TIMEOUT));
6201 if (!ret) {
6202 pr_err("%s: Slim close tx/rx wait timeout\n", __func__);
6203 ret = -ETIMEDOUT;
6204 } else {
6205 ret = 0;
6206 }
6207 }
6208 return ret;
6209}
6210
6211static void tomtom_codec_enable_int_port(struct wcd9xxx_codec_dai_data *dai,
6212 struct snd_soc_codec *codec)
6213{
6214 struct wcd9xxx_ch *ch;
6215 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
6216 int port_num = 0;
6217 unsigned short reg = 0;
6218 u8 val = 0;
6219
6220 if (!dai || !codec) {
6221 pr_err("%s: Invalid params\n", __func__);
6222 return;
6223 }
6224 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
6225 if (ch->port >= TOMTOM_RX_PORT_START_NUMBER) {
6226 port_num = ch->port - TOMTOM_RX_PORT_START_NUMBER;
6227 reg = TOMTOM_SLIM_PGD_PORT_INT_EN0 + (port_num / 8);
6228 val = wcd9xxx_interface_reg_read(wcd9xxx,
6229 reg);
6230 if (!(val & (1 << (port_num % 8)))) {
6231 val |= (1 << (port_num % 8));
6232 wcd9xxx_interface_reg_write(
6233 wcd9xxx, reg, val);
6234 val = wcd9xxx_interface_reg_read(
6235 wcd9xxx, reg);
6236 }
6237 } else {
6238 port_num = ch->port;
6239 reg = TOMTOM_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
6240 val = wcd9xxx_interface_reg_read(wcd9xxx,
6241 reg);
6242 if (!(val & (1 << (port_num % 8)))) {
6243 val |= (1 << (port_num % 8));
6244 wcd9xxx_interface_reg_write(wcd9xxx,
6245 reg, val);
6246 val = wcd9xxx_interface_reg_read(
6247 wcd9xxx, reg);
6248 }
6249 }
6250 }
6251}
6252
6253static int tomtom_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
6254 struct snd_kcontrol *kcontrol,
6255 int event)
6256{
6257 struct wcd9xxx *core;
6258 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6259 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
6260 int ret = 0;
6261 struct wcd9xxx_codec_dai_data *dai;
6262
6263 core = dev_get_drvdata(codec->dev->parent);
6264
6265 pr_debug("%s: event called! codec name %s num_dai %d\n"
6266 "stream name %s event %d\n",
6267 __func__, codec->component.name,
6268 codec->component.num_dai, w->sname, event);
6269
6270 /* Execute the callback only if interface type is slimbus */
6271 if (tomtom_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
6272 return 0;
6273
6274 dai = &tomtom_p->dai[w->shift];
6275 pr_debug("%s: w->name %s w->shift %d event %d\n",
6276 __func__, w->name, w->shift, event);
6277
6278 switch (event) {
6279 case SND_SOC_DAPM_POST_PMU:
6280 dai->bus_down_in_recovery = false;
6281 tomtom_codec_enable_int_port(dai, codec);
6282 (void) tomtom_codec_enable_slim_chmask(dai, true);
6283 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
6284 dai->rate, dai->bit_width,
6285 &dai->grph);
6286 break;
6287 case SND_SOC_DAPM_POST_PMD:
6288 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
6289 dai->grph);
6290 if (!dai->bus_down_in_recovery)
6291 ret = tomtom_codec_enable_slim_chmask(dai, false);
6292 else
6293 pr_debug("%s: bus in recovery skip enable slim_chmask",
6294 __func__);
6295 if (ret < 0) {
6296 ret = wcd9xxx_disconnect_port(core,
6297 &dai->wcd9xxx_ch_list,
6298 dai->grph);
6299 pr_debug("%s: Disconnect RX port, ret = %d\n",
6300 __func__, ret);
6301 }
6302 break;
6303 }
6304 return ret;
6305}
6306
6307static int tomtom_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
6308 struct snd_kcontrol *kcontrol,
6309 int event)
6310{
6311 struct wcd9xxx *core = NULL;
6312 struct snd_soc_codec *codec = NULL;
6313 struct tomtom_priv *tomtom_p = NULL;
6314 u32 ret = 0;
6315 struct wcd9xxx_codec_dai_data *dai = NULL;
6316
6317 if (!w) {
6318 pr_err("%s invalid params\n", __func__);
6319 return -EINVAL;
6320 }
6321 codec = snd_soc_dapm_to_codec(w->dapm);
6322 tomtom_p = snd_soc_codec_get_drvdata(codec);
6323 core = dev_get_drvdata(codec->dev->parent);
6324
6325 pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
6326 __func__, codec->component.name,
6327 codec->component.num_dai, w->sname);
6328
6329 /* Execute the callback only if interface type is slimbus */
6330 if (tomtom_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
6331 pr_err("%s Interface is not correct", __func__);
6332 return 0;
6333 }
6334
6335 pr_debug("%s(): w->name %s event %d w->shift %d\n",
6336 __func__, w->name, event, w->shift);
6337 if (w->shift != AIF4_VIFEED) {
6338 pr_err("%s Error in enabling the tx path\n", __func__);
6339 ret = -EINVAL;
6340 goto out_vi;
6341 }
6342 dai = &tomtom_p->dai[w->shift];
6343 switch (event) {
6344 case SND_SOC_DAPM_POST_PMU:
6345 /*Enable V&I sensing*/
6346 snd_soc_update_bits(codec, TOMTOM_A_SPKR1_PROT_EN,
6347 0x88, 0x88);
6348 /*Enable spkr VI clocks*/
6349 snd_soc_update_bits(codec,
6350 TOMTOM_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
6351 dai->bus_down_in_recovery = false;
6352 tomtom_codec_enable_int_port(dai, codec);
6353 (void) tomtom_codec_enable_slim_chmask(dai, true);
6354 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
6355 dai->rate, dai->bit_width,
6356 &dai->grph);
6357 break;
6358 case SND_SOC_DAPM_POST_PMD:
6359 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
6360 dai->grph);
6361 if (ret)
6362 pr_err("%s error in close_slim_sch_tx %d\n",
6363 __func__, ret);
6364 if (!dai->bus_down_in_recovery)
6365 ret = tomtom_codec_enable_slim_chmask(dai, false);
6366 if (ret < 0) {
6367 ret = wcd9xxx_disconnect_port(core,
6368 &dai->wcd9xxx_ch_list,
6369 dai->grph);
6370 pr_debug("%s: Disconnect TX port, ret = %d\n",
6371 __func__, ret);
6372 }
6373
6374 snd_soc_update_bits(codec, TOMTOM_A_CDC_CLK_TX_CLK_EN_B2_CTL,
6375 0xC, 0x0);
6376 /*Disable V&I sensing*/
6377 snd_soc_update_bits(codec, TOMTOM_A_SPKR1_PROT_EN,
6378 0x88, 0x00);
6379 break;
6380 }
6381out_vi:
6382 return ret;
6383}
6384
6385/* __tomtom_codec_enable_slimtx: Enable the slimbus slave port
6386 * for TX path
6387 * @codec: Handle to the codec for which the slave port is to be
6388 * enabled.
6389 * @dai_data: The dai specific data for dai which is enabled.
6390 */
6391static int __tomtom_codec_enable_slimtx(struct snd_soc_codec *codec,
6392 int event, struct wcd9xxx_codec_dai_data *dai_data)
6393{
6394 struct wcd9xxx *core;
6395 int ret = 0;
6396
6397 core = dev_get_drvdata(codec->dev->parent);
6398
6399 switch (event) {
6400 case SND_SOC_DAPM_POST_PMU:
6401 dai_data->bus_down_in_recovery = false;
6402 tomtom_codec_enable_int_port(dai_data, codec);
6403 (void) tomtom_codec_enable_slim_chmask(dai_data, true);
6404 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai_data->wcd9xxx_ch_list,
6405 dai_data->rate,
6406 dai_data->bit_width,
6407 &dai_data->grph);
6408 break;
6409 case SND_SOC_DAPM_POST_PMD:
6410 ret = wcd9xxx_close_slim_sch_tx(core,
6411 &dai_data->wcd9xxx_ch_list,
6412 dai_data->grph);
6413 if (!dai_data->bus_down_in_recovery)
6414 ret = tomtom_codec_enable_slim_chmask(dai_data, false);
6415 if (ret < 0) {
6416 ret = wcd9xxx_disconnect_port(core,
6417 &dai_data->wcd9xxx_ch_list,
6418 dai_data->grph);
6419 dev_dbg(codec->dev,
6420 "%s: Disconnect TX port, ret = %d\n",
6421 __func__, ret);
6422 }
6423 break;
6424 }
6425
6426 return ret;
6427}
6428
6429/*
6430 * tomtom_codec_enable_slimtx_mad: Callback function that will be invoked
6431 * to setup the slave port for MAD.
6432 * @codec: Handle to the codec
6433 * @event: Indicates whether to enable or disable the slave port
6434 */
6435static int tomtom_codec_enable_slimtx_mad(struct snd_soc_codec *codec,
6436 u8 event)
6437{
6438 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
6439 struct wcd9xxx_codec_dai_data *dai;
6440 int dapm_event = SND_SOC_DAPM_POST_PMU;
6441
6442 dai = &tomtom_p->dai[AIF4_MAD_TX];
6443
6444 if (event == 0)
6445 dapm_event = SND_SOC_DAPM_POST_PMD;
6446
6447 dev_dbg(codec->dev,
6448 "%s: mad_channel, event = 0x%x\n",
6449 __func__, event);
6450 return __tomtom_codec_enable_slimtx(codec, dapm_event, dai);
6451}
6452
6453/*
6454 * tomtom_codec_enable_slimtx: DAPM widget allback for TX widgets
6455 * @w: widget for which this callback is invoked
6456 * @kcontrol: kcontrol associated with this widget
6457 * @event: DAPM supplied event indicating enable/disable
6458 */
6459static int tomtom_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
6460 struct snd_kcontrol *kcontrol,
6461 int event)
6462{
6463 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6464 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
6465 struct wcd9xxx_codec_dai_data *dai;
6466
6467 dev_dbg(codec->dev, "%s: event called! codec name %s num_dai %d stream name %s\n",
6468 __func__, codec->component.name,
6469 codec->component.num_dai, w->sname);
6470
6471 /* Execute the callback only if interface type is slimbus */
6472 if (tomtom_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
6473 return 0;
6474
6475 dev_dbg(codec->dev,
6476 "%s(): w->name %s event %d w->shift %d\n",
6477 __func__, w->name, event, w->shift);
6478
6479 dai = &tomtom_p->dai[w->shift];
6480 return __tomtom_codec_enable_slimtx(codec, event, dai);
6481}
6482
6483static int tomtom_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
6484 struct snd_kcontrol *kcontrol, int event)
6485{
6486 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6487 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
6488
6489 pr_debug("%s %s %d\n", __func__, w->name, event);
6490
6491 switch (event) {
6492 case SND_SOC_DAPM_POST_PMU:
6493 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
6494 WCD9XXX_CLSH_STATE_EAR,
6495 WCD9XXX_CLSH_REQ_ENABLE,
6496 WCD9XXX_CLSH_EVENT_POST_PA);
6497
6498 usleep_range(5000, 5100);
6499 break;
6500 }
6501 return 0;
6502}
6503
6504static int tomtom_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
6505 struct snd_kcontrol *kcontrol, int event)
6506{
6507 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6508 struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);
6509
6510 pr_debug("%s %s %d\n", __func__, w->name, event);
6511
6512 switch (event) {
6513 case SND_SOC_DAPM_PRE_PMU:
6514 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
6515 WCD9XXX_CLSH_STATE_EAR,
6516 WCD9XXX_CLSH_REQ_ENABLE,
6517 WCD9XXX_CLSH_EVENT_PRE_DAC);
6518 break;
6519 case SND_SOC_DAPM_POST_PMD:
6520 wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
6521 WCD9XXX_CLSH_STATE_EAR,
6522 WCD9XXX_CLSH_REQ_DISABLE,
6523 WCD9XXX_CLSH_EVENT_POST_PA);
6524 usleep_range(5000, 5100);
6525 break;
6526 default:
6527 break;
6528 }
6529 return 0;
6530}
6531
6532static int tomtom_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
6533 struct snd_kcontrol *kcontrol, int event)
6534{
6535 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6536
6537 pr_debug("%s: event = %d\n", __func__, event);
6538
6539 switch (event) {
6540 case SND_SOC_DAPM_POST_PMU: /* fall through */
6541 case SND_SOC_DAPM_PRE_PMD:
6542 if (strnstr(w->name, "IIR1", sizeof("IIR1"))) {
6543 snd_soc_write(codec, TOMTOM_A_CDC_IIR1_GAIN_B1_CTL,
6544 snd_soc_read(codec,
6545 TOMTOM_A_CDC_IIR1_GAIN_B1_CTL));
6546 snd_soc_write(codec, TOMTOM_A_CDC_IIR1_GAIN_B2_CTL,
6547 snd_soc_read(codec,
6548 TOMTOM_A_CDC_IIR1_GAIN_B2_CTL));
6549 snd_soc_write(codec, TOMTOM_A_CDC_IIR1_GAIN_B3_CTL,
6550 snd_soc_read(codec,
6551 TOMTOM_A_CDC_IIR1_GAIN_B3_CTL));
6552 snd_soc_write(codec, TOMTOM_A_CDC_IIR1_GAIN_B4_CTL,
6553 snd_soc_read(codec,
6554 TOMTOM_A_CDC_IIR1_GAIN_B4_CTL));
6555 } else {
6556 snd_soc_write(codec, TOMTOM_A_CDC_IIR2_GAIN_B1_CTL,
6557 snd_soc_read(codec,
6558 TOMTOM_A_CDC_IIR2_GAIN_B1_CTL));
6559 snd_soc_write(codec, TOMTOM_A_CDC_IIR2_GAIN_B2_CTL,
6560 snd_soc_read(codec,
6561 TOMTOM_A_CDC_IIR2_GAIN_B2_CTL));
6562 snd_soc_write(codec, TOMTOM_A_CDC_IIR2_GAIN_B3_CTL,
6563 snd_soc_read(codec,
6564 TOMTOM_A_CDC_IIR2_GAIN_B3_CTL));
6565 snd_soc_write(codec, TOMTOM_A_CDC_IIR2_GAIN_B4_CTL,
6566 snd_soc_read(codec,
6567 TOMTOM_A_CDC_IIR2_GAIN_B4_CTL));
6568 }
6569 break;
6570 }
6571 return 0;
6572}
6573
6574static int tomtom_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
6575 struct snd_kcontrol *kcontrol, int event)
6576{
6577 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6578 u8 reg_val, zoh_mux_val = 0x00;
6579
6580 pr_debug("%s: event = %d\n", __func__, event);
6581
6582 switch (event) {
6583 case SND_SOC_DAPM_POST_PMU:
6584 reg_val = snd_soc_read(codec, TOMTOM_A_CDC_CONN_CLSH_CTL);
6585
6586 if ((reg_val & 0x30) == 0x10)
6587 zoh_mux_val = 0x04;
6588 else if ((reg_val & 0x30) == 0x20)
6589 zoh_mux_val = 0x08;
6590
6591 if (zoh_mux_val != 0x00)
6592 snd_soc_update_bits(codec,
6593 TOMTOM_A_CDC_CONN_CLSH_CTL,
6594 0x0C, zoh_mux_val);
6595 break;
6596
6597 case SND_SOC_DAPM_POST_PMD:
6598 snd_soc_update_bits(codec, TOMTOM_A_CDC_CONN_CLSH_CTL,
6599 0x0C, 0x00);
6600 break;
6601 }
6602 return 0;
6603}
6604
6605static int tomtom_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
6606 struct snd_kcontrol *kcontrol, int event)
6607{
6608 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
6609 int ret = 0;
6610
6611 switch (event) {
6612 case SND_SOC_DAPM_PRE_PMU:
6613 ret = tomtom_codec_enable_anc(w, kcontrol, event);
6614 msleep(50);
6615 snd_soc_update_bits(codec, TOMTOM_A_RX_EAR_EN, 0x10, 0x10);
6616 break;
6617 case SND_SOC_DAPM_POST_PMU:
6618 ret = tomtom_codec_enable_ear_pa(w, kcontrol, event);
6619 break;
6620 case SND_SOC_DAPM_PRE_PMD:
6621 snd_soc_update_bits(codec, TOMTOM_A_RX_EAR_EN, 0x10, 0x00);
6622 msleep(40);
6623 ret |= tomtom_codec_enable_anc(w, kcontrol, event);
6624 break;
6625 case SND_SOC_DAPM_POST_PMD:
6626 ret = tomtom_codec_enable_ear_pa(w, kcontrol, event);
6627 break;
6628 }
6629 return ret;
6630}
6631
6632/* Todo: Have separate dapm widgets for I2S and Slimbus.
6633 * Might Need to have callbacks registered only for slimbus
6634 */
6635static const struct snd_soc_dapm_widget tomtom_dapm_widgets[] = {
6636 /*RX stuff */
6637 SND_SOC_DAPM_OUTPUT("EAR"),
6638
6639 SND_SOC_DAPM_PGA_E("EAR PA", TOMTOM_A_RX_EAR_EN, 4, 0, NULL, 0,
6640 tomtom_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
6641
6642 SND_SOC_DAPM_MIXER_E("DAC1", TOMTOM_A_RX_EAR_EN, 6, 0, dac1_switch,
6643 ARRAY_SIZE(dac1_switch), tomtom_codec_ear_dac_event,
6644 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6645
6646 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
6647 AIF1_PB, 0, tomtom_codec_enable_slimrx,
6648 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6649 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
6650 AIF2_PB, 0, tomtom_codec_enable_slimrx,
6651 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6652 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
6653 AIF3_PB, 0, tomtom_codec_enable_slimrx,
6654 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6655
6656 SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, TOMTOM_RX1, 0,
6657 &slim_rx_mux[TOMTOM_RX1]),
6658 SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, TOMTOM_RX2, 0,
6659 &slim_rx_mux[TOMTOM_RX2]),
6660 SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, TOMTOM_RX3, 0,
6661 &slim_rx_mux[TOMTOM_RX3]),
6662 SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, TOMTOM_RX4, 0,
6663 &slim_rx_mux[TOMTOM_RX4]),
6664 SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, TOMTOM_RX5, 0,
6665 &slim_rx_mux[TOMTOM_RX5]),
6666 SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, TOMTOM_RX6, 0,
6667 &slim_rx_mux[TOMTOM_RX6]),
6668 SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, TOMTOM_RX7, 0,
6669 &slim_rx_mux[TOMTOM_RX7]),
6670 SND_SOC_DAPM_MUX("SLIM RX8 MUX", SND_SOC_NOPM, TOMTOM_RX8, 0,
6671 &slim_rx_mux[TOMTOM_RX8]),
6672
6673 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6674 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6675 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
6676 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
6677 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
6678 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
6679 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
6680 SND_SOC_DAPM_MIXER("SLIM RX8", SND_SOC_NOPM, 0, 0, NULL, 0),
6681
6682 /* Headphone */
6683 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
6684 SND_SOC_DAPM_PGA_E("HPHL", TOMTOM_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
6685 tomtom_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
6686 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
6687 SND_SOC_DAPM_POST_PMD),
6688 SND_SOC_DAPM_MIXER_E("HPHL DAC", TOMTOM_A_RX_HPH_L_DAC_CTL, 7, 0,
6689 hphl_switch, ARRAY_SIZE(hphl_switch), tomtom_hphl_dac_event,
6690 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6691 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6692
6693 SND_SOC_DAPM_PGA_E("HPHR", TOMTOM_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
6694 tomtom_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
6695 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD |
6696 SND_SOC_DAPM_POST_PMD),
6697
6698 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TOMTOM_A_RX_HPH_R_DAC_CTL, 7, 0,
6699 tomtom_hphr_dac_event,
6700 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6701 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6702
6703 /* Speaker */
6704 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
6705 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
6706 SND_SOC_DAPM_OUTPUT("LINEOUT3"),
6707 SND_SOC_DAPM_OUTPUT("LINEOUT4"),
6708 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
6709
6710 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TOMTOM_A_RX_LINE_CNP_EN, 0, 0, NULL,
6711 0, tomtom_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
6712 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6713 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TOMTOM_A_RX_LINE_CNP_EN, 1, 0, NULL,
6714 0, tomtom_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
6715 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6716 SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TOMTOM_A_RX_LINE_CNP_EN, 2, 0, NULL,
6717 0, tomtom_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
6718 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6719 SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TOMTOM_A_RX_LINE_CNP_EN, 3, 0, NULL,
6720 0, tomtom_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
6721 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6722 SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0, NULL,
6723 0, tomtom_codec_enable_spk_pa,
6724 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6725 SND_SOC_DAPM_PGA_E("SPK2 PA", SND_SOC_NOPM, 0, 0, NULL,
6726 0, tomtom_codec_enable_spk_pa,
6727 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6728
6729 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TOMTOM_A_RX_LINE_1_DAC_CTL, 7,
6730 0, tomtom_lineout_dac_event,
6731 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6732 SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TOMTOM_A_RX_LINE_2_DAC_CTL, 7,
6733 0, tomtom_lineout_dac_event,
6734 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6735 SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TOMTOM_A_RX_LINE_3_DAC_CTL, 7,
6736 0, tomtom_lineout_dac_event,
6737 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6738 SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
6739 &lineout3_ground_switch),
6740 SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TOMTOM_A_RX_LINE_4_DAC_CTL, 7,
6741 0, tomtom_lineout_dac_event,
6742 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6743 SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
6744 &lineout4_ground_switch),
6745
6746 SND_SOC_DAPM_DAC_E("SPK DAC", NULL, TOMTOM_A_CDC_BOOST_TRGR_EN, 0, 0,
6747 tomtom_spk_dac_event,
6748 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6749 SND_SOC_DAPM_DAC_E("SPK2 DAC", NULL, TOMTOM_A_CDC_BOOST_TRGR_EN, 1, 0,
6750 tomtom_spk_dac_event,
6751 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6752
6753 SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
6754 tomtom_codec_enable_vdd_spkr,
6755 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6756
6757 SND_SOC_DAPM_SUPPLY("VDD_SPKDRV2", SND_SOC_NOPM, 0, 0,
6758 tomtom_codec_enable_vdd_spkr2,
6759 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6760
6761 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6762 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6763 SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6764
6765 SND_SOC_DAPM_MIXER("RX1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6766 SND_SOC_DAPM_MIXER("RX2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6767
6768 SND_SOC_DAPM_MIXER_E("RX3 MIX1", TOMTOM_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
6769 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6770 SND_SOC_DAPM_POST_PMU),
6771 SND_SOC_DAPM_MIXER_E("RX4 MIX1", TOMTOM_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
6772 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6773 SND_SOC_DAPM_POST_PMU),
6774 SND_SOC_DAPM_MIXER_E("RX5 MIX1", TOMTOM_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
6775 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6776 SND_SOC_DAPM_POST_PMU),
6777 SND_SOC_DAPM_MIXER_E("RX6 MIX1", TOMTOM_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
6778 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6779 SND_SOC_DAPM_POST_PMU),
6780 SND_SOC_DAPM_MIXER_E("RX7 MIX2", TOMTOM_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
6781 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6782 SND_SOC_DAPM_POST_PMU),
6783 SND_SOC_DAPM_MIXER_E("RX8 MIX1", TOMTOM_A_CDC_CLK_RX_B1_CTL, 7, 0, NULL,
6784 0, tomtom_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
6785 SND_SOC_DAPM_POST_PMU),
6786
6787 SND_SOC_DAPM_MUX_E("RX1 INTERP", TOMTOM_A_CDC_CLK_RX_B1_CTL, 0, 0,
6788 &rx1_interp_mux, tomtom_codec_enable_interpolator,
6789 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
6790 SND_SOC_DAPM_MUX_E("RX2 INTERP", TOMTOM_A_CDC_CLK_RX_B1_CTL, 1, 0,
6791 &rx2_interp_mux, tomtom_codec_enable_interpolator,
6792 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
6793
6794
6795 SND_SOC_DAPM_MIXER("RX1 CHAIN", TOMTOM_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
6796 SND_SOC_DAPM_MIXER("RX2 CHAIN", TOMTOM_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
6797
6798 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6799 &rx_mix1_inp1_mux),
6800 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6801 &rx_mix1_inp2_mux),
6802 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
6803 &rx_mix1_inp3_mux),
6804 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6805 &rx2_mix1_inp1_mux),
6806 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6807 &rx2_mix1_inp2_mux),
6808 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6809 &rx3_mix1_inp1_mux),
6810 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6811 &rx3_mix1_inp2_mux),
6812 SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6813 &rx4_mix1_inp1_mux),
6814 SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6815 &rx4_mix1_inp2_mux),
6816 SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6817 &rx5_mix1_inp1_mux),
6818 SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6819 &rx5_mix1_inp2_mux),
6820 SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6821 &rx6_mix1_inp1_mux),
6822 SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6823 &rx6_mix1_inp2_mux),
6824 SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6825 &rx7_mix1_inp1_mux),
6826 SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6827 &rx7_mix1_inp2_mux),
6828 SND_SOC_DAPM_MUX("RX8 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6829 &rx8_mix1_inp1_mux),
6830 SND_SOC_DAPM_MUX("RX8 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6831 &rx8_mix1_inp2_mux),
6832 SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
6833 &rx1_mix2_inp1_mux),
6834 SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
6835 &rx1_mix2_inp2_mux),
6836 SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
6837 &rx2_mix2_inp1_mux),
6838 SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
6839 &rx2_mix2_inp2_mux),
6840 SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
6841 &rx7_mix2_inp1_mux),
6842 SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
6843 &rx7_mix2_inp2_mux),
6844
6845 SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
6846 &rx_dac5_mux),
6847 SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
6848 &rx_dac7_mux),
6849
6850 SND_SOC_DAPM_MUX("MAD_SEL MUX", SND_SOC_NOPM, 0, 0,
6851 &mad_sel_mux),
6852
6853 SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
6854 &class_h_dsm_mux, tomtom_codec_dsm_mux_event,
6855 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6856
6857 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
6858 tomtom_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
6859 SND_SOC_DAPM_POST_PMD),
6860
6861 SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 5, 0,
6862 NULL, 0),
6863
6864 /* TX */
6865
6866 SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
6867 0),
6868
6869 SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0,
6870 tomtom_codec_enable_ldo_h,
6871 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6872 /*
6873 * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after
6874 * acquring codec_resource lock.
6875 * So call __tomtom_codec_enable_ldo_h instead and avoid deadlock.
6876 */
6877 SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0,
6878 __tomtom_codec_enable_ldo_h,
6879 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6880
6881 SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
6882 tomtom_config_compander, SND_SOC_DAPM_PRE_PMU |
6883 SND_SOC_DAPM_PRE_PMD),
6884 SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
6885 tomtom_config_compander, SND_SOC_DAPM_PRE_PMU |
6886 SND_SOC_DAPM_PRE_PMD),
6887 SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
6888 tomtom_config_compander, SND_SOC_DAPM_PRE_PMU |
6889 SND_SOC_DAPM_PRE_PMD),
6890
6891
6892 SND_SOC_DAPM_INPUT("AMIC1"),
6893 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
6894 tomtom_codec_enable_micbias,
6895 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6896 SND_SOC_DAPM_POST_PMD),
6897 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
6898 tomtom_codec_enable_micbias,
6899 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6900 SND_SOC_DAPM_POST_PMD),
6901 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
6902 tomtom_codec_enable_micbias,
6903 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6904 SND_SOC_DAPM_POST_PMD),
6905
6906 SND_SOC_DAPM_INPUT("AMIC3"),
6907
6908 SND_SOC_DAPM_INPUT("AMIC4"),
6909
6910 SND_SOC_DAPM_INPUT("AMIC5"),
6911
6912 SND_SOC_DAPM_INPUT("AMIC6"),
6913
6914 SND_SOC_DAPM_MUX_E("DEC1 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
6915 &dec1_mux, tomtom_codec_enable_dec,
6916 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6917 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6918
6919 SND_SOC_DAPM_MUX_E("DEC2 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
6920 &dec2_mux, tomtom_codec_enable_dec,
6921 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6922 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6923
6924 SND_SOC_DAPM_MUX_E("DEC3 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
6925 &dec3_mux, tomtom_codec_enable_dec,
6926 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6927 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6928
6929 SND_SOC_DAPM_MUX_E("DEC4 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
6930 &dec4_mux, tomtom_codec_enable_dec,
6931 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6932 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6933
6934 SND_SOC_DAPM_MUX_E("DEC5 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
6935 &dec5_mux, tomtom_codec_enable_dec,
6936 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6937 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6938
6939 SND_SOC_DAPM_MUX_E("DEC6 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
6940 &dec6_mux, tomtom_codec_enable_dec,
6941 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6942 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6943
6944 SND_SOC_DAPM_MUX_E("DEC7 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
6945 &dec7_mux, tomtom_codec_enable_dec,
6946 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6947 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6948
6949 SND_SOC_DAPM_MUX_E("DEC8 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
6950 &dec8_mux, tomtom_codec_enable_dec,
6951 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6952 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6953
6954 SND_SOC_DAPM_MUX_E("DEC9 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
6955 &dec9_mux, tomtom_codec_enable_dec,
6956 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6957 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6958
6959 SND_SOC_DAPM_MUX_E("DEC10 MUX", TOMTOM_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
6960 &dec10_mux, tomtom_codec_enable_dec,
6961 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6962 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6963
6964 SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
6965 SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
6966
6967 SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
6968 SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
6969 tomtom_codec_enable_anc_hph,
6970 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
6971 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
6972 SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
6973 tomtom_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
6974 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
6975 SND_SOC_DAPM_POST_PMU),
6976 SND_SOC_DAPM_OUTPUT("ANC EAR"),
6977 SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
6978 tomtom_codec_enable_anc_ear,
6979 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
6980 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6981 SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
6982
6983 SND_SOC_DAPM_INPUT("AMIC2"),
6984 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM,
6985 7, 0, tomtom_codec_enable_micbias,
6986 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6987 SND_SOC_DAPM_POST_PMD),
6988 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
6989 tomtom_codec_enable_micbias,
6990 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6991 SND_SOC_DAPM_POST_PMD),
6992 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
6993 tomtom_codec_enable_micbias,
6994 SND_SOC_DAPM_PRE_PMU |
6995 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6996 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
6997 tomtom_codec_enable_micbias,
6998 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6999 SND_SOC_DAPM_POST_PMD),
7000 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
7001 tomtom_codec_enable_micbias,
7002 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7003 SND_SOC_DAPM_POST_PMD),
7004 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
7005 tomtom_codec_enable_micbias,
7006 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7007 SND_SOC_DAPM_POST_PMD),
7008 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
7009 tomtom_codec_enable_micbias,
7010 SND_SOC_DAPM_PRE_PMU |
7011 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7012 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
7013 tomtom_codec_enable_micbias,
7014 SND_SOC_DAPM_PRE_PMU |
7015 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7016 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", SND_SOC_NOPM, 7,
7017 0, tomtom_codec_enable_micbias,
7018 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7019 SND_SOC_DAPM_POST_PMD),
7020
7021 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
7022 AIF1_CAP, 0, tomtom_codec_enable_slimtx,
7023 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7024
7025 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
7026 AIF2_CAP, 0, tomtom_codec_enable_slimtx,
7027 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7028
7029 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
7030 AIF3_CAP, 0, tomtom_codec_enable_slimtx,
7031 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7032
7033 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
7034 AIF4_VIFEED, 0, tomtom_codec_enable_slimvi_feedback,
7035 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7036 SND_SOC_DAPM_AIF_OUT_E("AIF4 MAD", "AIF4 MAD TX", 0,
7037 SND_SOC_NOPM, 0, 0,
7038 tomtom_codec_enable_mad,
7039 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7040 SND_SOC_DAPM_SWITCH("MADONOFF", SND_SOC_NOPM, 0, 0,
7041 &aif4_mad_switch),
7042 SND_SOC_DAPM_INPUT("MADINPUT"),
7043 SND_SOC_DAPM_INPUT("MAD_CPE_INPUT"),
7044
7045 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
7046 aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
7047
7048 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
7049 aif2_cap_mixer, ARRAY_SIZE(aif2_cap_mixer)),
7050
7051 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
7052 aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),
7053
7054 SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TOMTOM_TX1, 0,
7055 &sb_tx1_mux),
7056 SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TOMTOM_TX2, 0,
7057 &sb_tx2_mux),
7058 SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TOMTOM_TX3, 0,
7059 &sb_tx3_mux),
7060 SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TOMTOM_TX4, 0,
7061 &sb_tx4_mux),
7062 SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TOMTOM_TX5, 0,
7063 &sb_tx5_mux),
7064 SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, TOMTOM_TX6, 0,
7065 &sb_tx6_mux),
7066 SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, TOMTOM_TX7, 0,
7067 &sb_tx7_mux),
7068 SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, TOMTOM_TX8, 0,
7069 &sb_tx8_mux),
7070 SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, TOMTOM_TX9, 0,
7071 &sb_tx9_mux),
7072 SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, TOMTOM_TX10, 0,
7073 &sb_tx10_mux),
7074
7075 /* Digital Mic Inputs */
7076 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
7077 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7078 SND_SOC_DAPM_POST_PMD),
7079
7080 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
7081 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7082 SND_SOC_DAPM_POST_PMD),
7083
7084 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
7085 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7086 SND_SOC_DAPM_POST_PMD),
7087
7088 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
7089 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7090 SND_SOC_DAPM_POST_PMD),
7091
7092 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
7093 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7094 SND_SOC_DAPM_POST_PMD),
7095 SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
7096 tomtom_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
7097 SND_SOC_DAPM_POST_PMD),
7098
7099 /* Sidetone */
7100 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
7101
7102 SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux),
7103
7104 SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux),
7105
7106 SND_SOC_DAPM_MUX("IIR1 INP4 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp4_mux),
7107
7108 SND_SOC_DAPM_MIXER_E("IIR1", TOMTOM_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0,
7109 tomtom_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU |
7110 SND_SOC_DAPM_PRE_PMD),
7111
7112 SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
7113
7114 SND_SOC_DAPM_MUX("IIR2 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp2_mux),
7115
7116 SND_SOC_DAPM_MUX("IIR2 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp3_mux),
7117
7118 SND_SOC_DAPM_MUX("IIR2 INP4 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp4_mux),
7119
7120 SND_SOC_DAPM_MIXER_E("IIR2", TOMTOM_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0,
7121 tomtom_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU |
7122 SND_SOC_DAPM_PRE_PMD),
7123
7124 /* AUX PGA */
7125 SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TOMTOM_A_RX_AUX_SW_CTL, 7, 0,
7126 tomtom_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
7127 SND_SOC_DAPM_POST_PMD),
7128
7129 SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TOMTOM_A_RX_AUX_SW_CTL, 6, 0,
7130 tomtom_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
7131 SND_SOC_DAPM_POST_PMD),
7132
7133 /* Lineout, ear and HPH PA Mixers */
7134
7135 SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
7136 ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
7137
7138 SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
7139 hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
7140
7141 SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
7142 hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
7143
7144 SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
7145 lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
7146
7147 SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
7148 lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
7149
7150 SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
7151 lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
7152
7153 SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
7154 lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
7155
7156 SND_SOC_DAPM_SWITCH("VIONOFF", SND_SOC_NOPM, 0, 0,
7157 &aif4_vi_switch),
7158
7159 SND_SOC_DAPM_INPUT("VIINPUT"),
7160};
7161
7162static irqreturn_t tomtom_slimbus_irq(int irq, void *data)
7163{
7164 struct tomtom_priv *priv = data;
7165 struct snd_soc_codec *codec = priv->codec;
7166 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
7167 unsigned long status = 0;
7168 int i, j, port_id, k;
7169 u32 bit;
7170 u8 val, int_val = 0;
7171 bool tx, cleared;
7172 unsigned short reg = 0;
7173
7174 for (i = TOMTOM_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
7175 i <= TOMTOM_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
7176 val = wcd9xxx_interface_reg_read(wcd9xxx, i);
7177 status |= ((u32)val << (8 * j));
7178 }
7179
7180 for_each_set_bit(j, &status, 32) {
7181 tx = (j >= 16 ? true : false);
7182 port_id = (tx ? j - 16 : j);
7183 val = wcd9xxx_interface_reg_read(wcd9xxx,
7184 TOMTOM_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
7185 if (val) {
7186 if (!tx)
7187 reg = TOMTOM_SLIM_PGD_PORT_INT_EN0 +
7188 (port_id / 8);
7189 else
7190 reg = TOMTOM_SLIM_PGD_PORT_INT_TX_EN0 +
7191 (port_id / 8);
7192 int_val = wcd9xxx_interface_reg_read(
7193 wcd9xxx, reg);
7194 /*
7195 * Ignore interrupts for ports for which the
7196 * interrupts are not specifically enabled.
7197 */
7198 if (!(int_val & (1 << (port_id % 8))))
7199 continue;
7200 }
7201 if (val & TOMTOM_SLIM_IRQ_OVERFLOW)
7202 pr_err_ratelimited(
7203 "%s: overflow error on %s port %d, value %x\n",
7204 __func__, (tx ? "TX" : "RX"), port_id, val);
7205 if (val & TOMTOM_SLIM_IRQ_UNDERFLOW)
7206 pr_err_ratelimited(
7207 "%s: underflow error on %s port %d, value %x\n",
7208 __func__, (tx ? "TX" : "RX"), port_id, val);
7209 if ((val & TOMTOM_SLIM_IRQ_OVERFLOW) ||
7210 (val & TOMTOM_SLIM_IRQ_UNDERFLOW)) {
7211 if (!tx)
7212 reg = TOMTOM_SLIM_PGD_PORT_INT_EN0 +
7213 (port_id / 8);
7214 else
7215 reg = TOMTOM_SLIM_PGD_PORT_INT_TX_EN0 +
7216 (port_id / 8);
7217 int_val = wcd9xxx_interface_reg_read(wcd9xxx, reg);
7218 if (int_val & (1 << (port_id % 8))) {
7219 int_val = int_val ^ (1 << (port_id % 8));
7220 wcd9xxx_interface_reg_write(wcd9xxx, reg,
7221 int_val);
7222 }
7223 }
7224 if (val & TOMTOM_SLIM_IRQ_PORT_CLOSED) {
7225 /*
7226 * INT SOURCE register starts from RX to TX
7227 * but port number in the ch_mask is in opposite way
7228 */
7229 bit = (tx ? j - 16 : j + 16);
7230 pr_debug("%s: %s port %d closed value %x, bit %u\n",
7231 __func__, (tx ? "TX" : "RX"), port_id, val,
7232 bit);
7233 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
7234 pr_debug("%s: priv->dai[%d].ch_mask = 0x%lx\n",
7235 __func__, k, priv->dai[k].ch_mask);
7236 if (test_and_clear_bit(bit,
7237 &priv->dai[k].ch_mask)) {
7238 cleared = true;
7239 if (!priv->dai[k].ch_mask)
7240 wake_up(&priv->dai[k].dai_wait);
7241 /*
7242 * There are cases when multiple DAIs
7243 * might be using the same slimbus
7244 * channel. Hence don't break here.
7245 */
7246 }
7247 }
7248 WARN(!cleared,
7249 "Couldn't find slimbus %s port %d for closing\n",
7250 (tx ? "TX" : "RX"), port_id);
7251 }
7252 wcd9xxx_interface_reg_write(wcd9xxx,
7253 TOMTOM_SLIM_PGD_PORT_INT_CLR_RX_0 +
7254 (j / 8),
7255 1 << (j % 8));
7256 }
7257
7258 return IRQ_HANDLED;
7259}
7260
7261static int tomtom_handle_pdata(struct tomtom_priv *tomtom)
7262{
7263 struct snd_soc_codec *codec = tomtom->codec;
7264 struct wcd9xxx_pdata *pdata = tomtom->resmgr.pdata;
7265 int k1, k2, k3, dec, rc = 0;
7266 u8 leg_mode, txfe_bypass, txfe_buff, flag;
7267 u8 i = 0, j = 0;
7268 u8 val_txfe = 0, value = 0;
7269 u8 dmic_ctl_val, mad_dmic_ctl_val;
7270 u8 anc_ctl_value = 0;
7271 u32 def_dmic_rate;
7272 u16 tx_dmic_ctl_reg;
7273
7274 if (!pdata) {
7275 pr_err("%s: NULL pdata\n", __func__);
7276 rc = -ENODEV;
7277 goto done;
7278 }
7279
7280 leg_mode = pdata->amic_settings.legacy_mode;
7281 txfe_bypass = pdata->amic_settings.txfe_enable;
7282 txfe_buff = pdata->amic_settings.txfe_buff;
7283 flag = pdata->amic_settings.use_pdata;
7284
7285 /* Make sure settings are correct */
7286 if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
7287 (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
7288 (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
7289 (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
7290 (pdata->micbias.bias4_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
7291 rc = -EINVAL;
7292 goto done;
7293 }
7294 /* figure out k value */
7295 k1 = wcd9xxx_resmgr_get_k_val(&tomtom->resmgr,
7296 pdata->micbias.cfilt1_mv);
7297 k2 = wcd9xxx_resmgr_get_k_val(&tomtom->resmgr,
7298 pdata->micbias.cfilt2_mv);
7299 k3 = wcd9xxx_resmgr_get_k_val(&tomtom->resmgr,
7300 pdata->micbias.cfilt3_mv);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08007301 if (k1 < 0 || k2 < 0 || k3 < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08007302 rc = -EINVAL;
7303 goto done;
7304 }
7305 /* Set voltage level and always use LDO */
7306 snd_soc_update_bits(codec, TOMTOM_A_LDO_H_MODE_1, 0x0C,
7307 (pdata->micbias.ldoh_v << 2));
7308
7309 snd_soc_update_bits(codec, TOMTOM_A_MICB_CFILT_1_VAL, 0xFC, (k1 << 2));
7310 snd_soc_update_bits(codec, TOMTOM_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
7311 snd_soc_update_bits(codec, TOMTOM_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
7312
7313 snd_soc_update_bits(codec, TOMTOM_A_MICB_1_CTL, 0x60,
7314 (pdata->micbias.bias1_cfilt_sel << 5));
7315 snd_soc_update_bits(codec, TOMTOM_A_MICB_2_CTL, 0x60,
7316 (pdata->micbias.bias2_cfilt_sel << 5));
7317 snd_soc_update_bits(codec, TOMTOM_A_MICB_3_CTL, 0x60,
7318 (pdata->micbias.bias3_cfilt_sel << 5));
7319 snd_soc_update_bits(codec, tomtom->resmgr.reg_addr->micb_4_ctl, 0x60,
7320 (pdata->micbias.bias4_cfilt_sel << 5));
7321
7322 for (i = 0; i < 6; j++, i += 2) {
7323 if (flag & (0x01 << i)) {
7324 val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
7325 val_txfe = val_txfe |
7326 ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
7327 snd_soc_update_bits(codec,
7328 TOMTOM_A_TX_1_2_TEST_EN + j * 10,
7329 0x30, val_txfe);
7330 }
7331 if (flag & (0x01 << (i + 1))) {
7332 val_txfe = (txfe_bypass &
7333 (0x01 << (i + 1))) ? 0x02 : 0x00;
7334 val_txfe |= (txfe_buff &
7335 (0x01 << (i + 1))) ? 0x01 : 0x00;
7336 snd_soc_update_bits(codec,
7337 TOMTOM_A_TX_1_2_TEST_EN + j * 10,
7338 0x03, val_txfe);
7339 }
7340 }
7341 if (flag & 0x40) {
7342 value = (leg_mode & 0x40) ? 0x10 : 0x00;
7343 value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
7344 value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
7345 snd_soc_update_bits(codec, TOMTOM_A_TX_7_MBHC_EN,
7346 0x13, value);
7347 }
7348
7349 if (pdata->ocp.use_pdata) {
7350 /* not defined in CODEC specification */
7351 if (pdata->ocp.hph_ocp_limit == 1 ||
7352 pdata->ocp.hph_ocp_limit == 5) {
7353 rc = -EINVAL;
7354 goto done;
7355 }
7356 snd_soc_update_bits(codec, TOMTOM_A_RX_COM_OCP_CTL,
7357 0x0F, pdata->ocp.num_attempts);
7358 snd_soc_write(codec, TOMTOM_A_RX_COM_OCP_COUNT,
7359 ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
7360 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_OCP_CTL,
7361 0xE0, (pdata->ocp.hph_ocp_limit << 5));
7362 }
7363
7364 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
7365 if (pdata->regulator[i].name &&
7366 !strcmp(pdata->regulator[i].name, "CDC_VDDA_RX")) {
7367 if (pdata->regulator[i].min_uV == 1800000 &&
7368 pdata->regulator[i].max_uV == 1800000) {
7369 snd_soc_write(codec, TOMTOM_A_BIAS_REF_CTL,
7370 0x1C);
7371 } else if (pdata->regulator[i].min_uV == 2200000 &&
7372 pdata->regulator[i].max_uV == 2200000) {
7373 snd_soc_write(codec, TOMTOM_A_BIAS_REF_CTL,
7374 0x1E);
7375 } else {
7376 pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
7377 "min %d, max %d\n", __func__,
7378 pdata->regulator[i].min_uV,
7379 pdata->regulator[i].max_uV);
7380 rc = -EINVAL;
7381 }
7382 break;
7383 }
7384 }
7385
7386 /* Set micbias capless mode with tail current */
7387 value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
7388 0x00 : 0x16);
7389 snd_soc_update_bits(codec, TOMTOM_A_MICB_1_CTL, 0x1E, value);
7390 value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
7391 0x00 : 0x16);
7392 snd_soc_update_bits(codec, TOMTOM_A_MICB_2_CTL, 0x1E, value);
7393 value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
7394 0x00 : 0x16);
7395 snd_soc_update_bits(codec, TOMTOM_A_MICB_3_CTL, 0x1E, value);
7396 value = (pdata->micbias.bias4_cap_mode == MICBIAS_EXT_BYP_CAP ?
7397 0x00 : 0x16);
7398 snd_soc_update_bits(codec, TOMTOM_A_MICB_4_CTL, 0x1E, value);
7399
7400 /* Set the DMIC sample rate */
7401 switch (pdata->mclk_rate) {
7402 case TOMTOM_MCLK_CLK_9P6MHZ:
7403 def_dmic_rate =
7404 WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
7405 break;
7406 case TOMTOM_MCLK_CLK_12P288MHZ:
7407 def_dmic_rate =
7408 WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ;
7409 break;
7410 default:
7411 /* should never happen */
7412 pr_err("%s: Invalid mclk_rate %d\n",
7413 __func__, pdata->mclk_rate);
7414 rc = -EINVAL;
7415 goto done;
7416 }
7417
7418 if (pdata->dmic_sample_rate ==
7419 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
7420 pr_info("%s: dmic_rate invalid default = %d\n",
7421 __func__, def_dmic_rate);
7422 pdata->dmic_sample_rate = def_dmic_rate;
7423 }
7424
7425 if (pdata->mad_dmic_sample_rate ==
7426 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
7427 pr_info("%s: mad_dmic_rate invalid default = %d\n",
7428 __func__, def_dmic_rate);
7429 /*
7430 * use dmic_sample_rate as the default for MAD
7431 * if mad dmic sample rate is undefined
7432 */
7433 pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
7434 }
7435
7436 /*
7437 * Default the DMIC clk rates to mad_dmic_sample_rate,
7438 * whereas, the anc/txfe dmic rates to dmic_sample_rate
7439 * since the anc/txfe are independent of mad block.
7440 */
7441 mad_dmic_ctl_val = tomtom_get_dmic_clk_val(tomtom->codec,
7442 pdata->mclk_rate,
7443 pdata->mad_dmic_sample_rate);
7444 snd_soc_update_bits(codec, TOMTOM_A_DMIC_B1_CTL,
7445 0xE0, mad_dmic_ctl_val << 5);
7446 snd_soc_update_bits(codec, TOMTOM_A_DMIC_B2_CTL,
7447 0x70, mad_dmic_ctl_val << 4);
7448 snd_soc_update_bits(codec, TOMTOM_A_DMIC_B2_CTL,
7449 0x0E, mad_dmic_ctl_val << 1);
7450
7451 dmic_ctl_val = tomtom_get_dmic_clk_val(tomtom->codec,
7452 pdata->mclk_rate,
7453 pdata->dmic_sample_rate);
7454
7455 if (dmic_ctl_val == WCD9330_DMIC_CLK_DIV_2)
7456 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
7457 else
7458 anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
7459
7460 for (dec = 0; dec < NUM_DECIMATORS; dec++) {
7461 tx_dmic_ctl_reg =
7462 TOMTOM_A_CDC_TX1_DMIC_CTL + (8 * dec);
7463 snd_soc_update_bits(codec, tx_dmic_ctl_reg,
7464 0x07, dmic_ctl_val);
7465 }
7466 snd_soc_update_bits(codec, TOMTOM_A_CDC_ANC1_B2_CTL,
7467 0x1, anc_ctl_value);
7468 snd_soc_update_bits(codec, TOMTOM_A_CDC_ANC2_B2_CTL,
7469 0x1, anc_ctl_value);
7470done:
7471 return rc;
7472}
7473
7474static const struct wcd9xxx_reg_mask_val tomtom_reg_defaults[] = {
7475
7476 /* set MCLk to 9.6 */
7477 TOMTOM_REG_VAL(TOMTOM_A_CHIP_CTL, 0x02),
7478
7479 /* EAR PA deafults */
7480 TOMTOM_REG_VAL(TOMTOM_A_RX_EAR_CMBUFF, 0x05),
7481
7482 /* RX deafults */
7483 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX1_B5_CTL, 0x79),
7484 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX2_B5_CTL, 0x79),
7485 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX3_B5_CTL, 0x79),
7486 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX4_B5_CTL, 0x79),
7487 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX5_B5_CTL, 0x79),
7488 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX6_B5_CTL, 0x79),
7489 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX7_B5_CTL, 0x79),
7490 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX8_B5_CTL, 0x79),
7491
7492 /* RX1 and RX2 defaults */
7493 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX1_B6_CTL, 0xA0),
7494 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX2_B6_CTL, 0xA0),
7495
7496 /* RX3 to RX7 defaults */
7497 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX3_B6_CTL, 0x80),
7498 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX4_B6_CTL, 0x80),
7499 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX5_B6_CTL, 0x80),
7500 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX6_B6_CTL, 0x80),
7501 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX7_B6_CTL, 0x80),
7502 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX8_B6_CTL, 0x80),
7503
7504 /* MAD registers */
7505 TOMTOM_REG_VAL(TOMTOM_A_MAD_ANA_CTRL, 0xF1),
7506 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_MAIN_CTL_1, 0x00),
7507 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_MAIN_CTL_2, 0x00),
7508 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_1, 0x00),
7509 /* Set SAMPLE_TX_EN bit */
7510 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_2, 0x03),
7511 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_3, 0x00),
7512 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_4, 0x00),
7513 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_5, 0x00),
7514 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_6, 0x00),
7515 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_7, 0x00),
7516 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_CTL_8, 0x00),
7517 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_IIR_CTL_PTR, 0x00),
7518 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_AUDIO_IIR_CTL_VAL, 0x40),
7519 TOMTOM_REG_VAL(TOMTOM_A_CDC_DEBUG_B7_CTL, 0x00),
7520 TOMTOM_REG_VAL(TOMTOM_A_CDC_CLK_OTHR_RESET_B1_CTL, 0x00),
7521 TOMTOM_REG_VAL(TOMTOM_A_CDC_CLK_OTHR_CTL, 0x00),
7522 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_INP_SEL, 0x01),
7523
7524 /* Set HPH Path to low power mode */
7525 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_BIAS_PA, 0x57),
7526
7527 /* BUCK default */
7528 TOMTOM_REG_VAL(TOMTOM_A_BUCK_CTRL_CCL_4, 0x51),
7529 TOMTOM_REG_VAL(TOMTOM_A_BUCK_CTRL_CCL_1, 0x5B),
7530};
7531
7532/*
7533 * Don't update TOMTOM_A_CHIP_CTL, TOMTOM_A_BUCK_CTRL_CCL_1 and
7534 * TOMTOM_A_RX_EAR_CMBUFF as those are updated in tomtom_reg_defaults
7535 */
7536static const struct wcd9xxx_reg_mask_val tomtom_1_0_reg_defaults[] = {
7537 TOMTOM_REG_VAL(TOMTOM_A_TX_1_GAIN, 0x2),
7538 TOMTOM_REG_VAL(TOMTOM_A_TX_2_GAIN, 0x2),
7539 TOMTOM_REG_VAL(TOMTOM_A_TX_1_2_ADC_IB, 0x44),
7540 TOMTOM_REG_VAL(TOMTOM_A_TX_3_GAIN, 0x2),
7541 TOMTOM_REG_VAL(TOMTOM_A_TX_4_GAIN, 0x2),
7542 TOMTOM_REG_VAL(TOMTOM_A_TX_3_4_ADC_IB, 0x44),
7543 TOMTOM_REG_VAL(TOMTOM_A_TX_5_GAIN, 0x2),
7544 TOMTOM_REG_VAL(TOMTOM_A_TX_6_GAIN, 0x2),
7545 TOMTOM_REG_VAL(TOMTOM_A_TX_5_6_ADC_IB, 0x44),
7546 TOMTOM_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
7547 TOMTOM_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
7548 TOMTOM_REG_VAL(TOMTOM_A_BUCK_CTRL_CCL_4, 0x51),
7549 TOMTOM_REG_VAL(TOMTOM_A_NCP_DTEST, 0x10),
7550 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_CHOP_CTL, 0xA4),
7551 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_OCP_CTL, 0x69),
7552 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_CNP_WG_CTL, 0xDA),
7553 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_CNP_WG_TIME, 0x15),
7554 TOMTOM_REG_VAL(TOMTOM_A_RX_EAR_BIAS_PA, 0x76),
7555 TOMTOM_REG_VAL(TOMTOM_A_RX_EAR_CNP, 0xC0),
7556 TOMTOM_REG_VAL(TOMTOM_A_RX_LINE_BIAS_PA, 0x78),
7557 TOMTOM_REG_VAL(TOMTOM_A_RX_LINE_1_TEST, 0x2),
7558 TOMTOM_REG_VAL(TOMTOM_A_RX_LINE_2_TEST, 0x2),
7559 TOMTOM_REG_VAL(TOMTOM_A_RX_LINE_3_TEST, 0x2),
7560 TOMTOM_REG_VAL(TOMTOM_A_RX_LINE_4_TEST, 0x2),
7561 TOMTOM_REG_VAL(TOMTOM_A_SPKR_DRV1_OCP_CTL, 0x97),
7562 TOMTOM_REG_VAL(TOMTOM_A_SPKR_DRV1_CLIP_DET, 0x1),
7563 TOMTOM_REG_VAL(TOMTOM_A_SPKR_DRV1_IEC, 0x0),
7564 TOMTOM_REG_VAL(TOMTOM_A_SPKR_DRV2_OCP_CTL, 0x97),
7565 TOMTOM_REG_VAL(TOMTOM_A_SPKR_DRV2_CLIP_DET, 0x1),
7566 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX1_MUX_CTL, 0x4A),
7567 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX2_MUX_CTL, 0x4A),
7568 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX3_MUX_CTL, 0x4A),
7569 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX4_MUX_CTL, 0x4A),
7570 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX5_MUX_CTL, 0x4A),
7571 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX6_MUX_CTL, 0x4A),
7572 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX7_MUX_CTL, 0x4A),
7573 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX8_MUX_CTL, 0x4A),
7574 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX9_MUX_CTL, 0x4A),
7575 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX10_MUX_CTL, 0x4A),
7576 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX1_B4_CTL, 0xB),
7577 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX2_B4_CTL, 0xB),
7578 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX3_B4_CTL, 0xB),
7579 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX4_B4_CTL, 0xB),
7580 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX5_B4_CTL, 0xB),
7581 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX6_B4_CTL, 0xB),
7582 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX7_B4_CTL, 0xB),
7583 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX8_B4_CTL, 0xB),
7584 TOMTOM_REG_VAL(TOMTOM_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
7585 TOMTOM_REG_VAL(TOMTOM_A_CDC_PA_RAMP_B1_CTL, 0x0),
7586 TOMTOM_REG_VAL(TOMTOM_A_CDC_PA_RAMP_B2_CTL, 0x0),
7587 TOMTOM_REG_VAL(TOMTOM_A_CDC_PA_RAMP_B3_CTL, 0x0),
7588 TOMTOM_REG_VAL(TOMTOM_A_CDC_PA_RAMP_B4_CTL, 0x0),
7589 TOMTOM_REG_VAL(TOMTOM_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
7590 TOMTOM_REG_VAL(TOMTOM_A_CDC_SPKR2_CLIPDET_B1_CTL, 0x0),
7591 TOMTOM_REG_VAL(TOMTOM_A_CDC_COMP0_B4_CTL, 0x37),
7592 TOMTOM_REG_VAL(TOMTOM_A_CDC_COMP0_B5_CTL, 0x7f),
7593 TOMTOM_REG_VAL(TOMTOM_A_CDC_COMP0_B5_CTL, 0x7f),
7594};
7595
7596static const struct wcd9xxx_reg_mask_val tomtom_2_0_reg_defaults[] = {
7597 TOMTOM_REG_VAL(TOMTOM_A_CDC_MAD_MAIN_CTL_2, 0x32),
7598 TOMTOM_REG_VAL(TOMTOM_A_RCO_CTRL, 0x10),
7599 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_L_TEST, 0x0A),
7600 TOMTOM_REG_VAL(TOMTOM_A_RX_HPH_R_TEST, 0x0A),
7601 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE0, 0xC3),
7602 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_DATA0, 0x00),
7603 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX_I2S_SCK_MODE, 0x04),
7604 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX_I2S_WS_MODE, 0x04),
7605 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX_I2S_SCK_MODE, 0x04),
7606 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX_I2S_WS_MODE, 0x04),
7607 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE1, 0xE0),
7608 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE2, 0x03),
7609 TOMTOM_REG_VAL(TOMTOM_A_CDC_JTCK_MODE, 0x04),
7610 TOMTOM_REG_VAL(TOMTOM_A_CDC_JTDI_MODE, 0x04),
7611 TOMTOM_REG_VAL(TOMTOM_A_CDC_JTMS_MODE, 0x04),
7612 TOMTOM_REG_VAL(TOMTOM_A_CDC_JTDO_MODE, 0x04),
7613 TOMTOM_REG_VAL(TOMTOM_A_CDC_JTRST_MODE, 0x04),
7614};
7615
7616static const struct wcd9xxx_reg_mask_val tomtom_2_0_reg_i2c_defaults[] = {
7617 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE0, 0x00),
7618 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX_I2S_SCK_MODE, 0x0),
7619 TOMTOM_REG_VAL(TOMTOM_A_CDC_TX_I2S_WS_MODE, 0x0),
7620 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX_I2S_SCK_MODE, 0x0),
7621 TOMTOM_REG_VAL(TOMTOM_A_CDC_RX_I2S_WS_MODE, 0x0),
7622 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE1, 0x0),
7623 TOMTOM_REG_VAL(TOMTOM_A_PIN_CTL_OE2, 0x0),
7624};
7625
7626static void tomtom_update_reg_defaults(struct snd_soc_codec *codec)
7627{
7628 u32 i;
7629 struct wcd9xxx *tomtom_core = dev_get_drvdata(codec->dev->parent);
7630 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
7631
7632 for (i = 0; i < ARRAY_SIZE(tomtom_reg_defaults); i++)
7633 snd_soc_write(codec, tomtom_reg_defaults[i].reg,
7634 tomtom_reg_defaults[i].val);
7635
7636 for (i = 0; i < ARRAY_SIZE(tomtom_1_0_reg_defaults); i++)
7637 snd_soc_write(codec, tomtom_1_0_reg_defaults[i].reg,
7638 tomtom_1_0_reg_defaults[i].val);
7639
7640 if (!TOMTOM_IS_1_0(tomtom_core->version)) {
7641 for (i = 0; i < ARRAY_SIZE(tomtom_2_0_reg_defaults); i++)
7642 snd_soc_write(codec, tomtom_2_0_reg_defaults[i].reg,
7643 tomtom_2_0_reg_defaults[i].val);
7644
7645 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
7646 for (i = 0; i < ARRAY_SIZE(tomtom_2_0_reg_i2c_defaults);
7647 i++)
7648 snd_soc_write(codec,
7649 tomtom_2_0_reg_i2c_defaults[i].reg,
7650 tomtom_2_0_reg_i2c_defaults[i].val);
7651 }
7652 }
7653}
7654
7655static const struct wcd9xxx_reg_mask_val tomtom_codec_reg_init_val[] = {
7656 /* Initialize current threshold to 350MA
7657 * number of wait and run cycles to 4096
7658 */
7659 {TOMTOM_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
7660 {TOMTOM_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
7661 {TOMTOM_A_RX_HPH_L_TEST, 0x01, 0x01},
7662 {TOMTOM_A_RX_HPH_R_TEST, 0x01, 0x01},
7663
7664 /* Initialize gain registers to use register gain */
7665 {TOMTOM_A_RX_HPH_L_GAIN, 0x20, 0x20},
7666 {TOMTOM_A_RX_HPH_R_GAIN, 0x20, 0x20},
7667 {TOMTOM_A_RX_LINE_1_GAIN, 0x20, 0x20},
7668 {TOMTOM_A_RX_LINE_2_GAIN, 0x20, 0x20},
7669 {TOMTOM_A_RX_LINE_3_GAIN, 0x20, 0x20},
7670 {TOMTOM_A_RX_LINE_4_GAIN, 0x20, 0x20},
7671 {TOMTOM_A_SPKR_DRV1_GAIN, 0x04, 0x04},
7672 {TOMTOM_A_SPKR_DRV2_GAIN, 0x04, 0x04},
7673
7674 /* Use 16 bit sample size for TX1 to TX6 */
7675 {TOMTOM_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
7676 {TOMTOM_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
7677 {TOMTOM_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
7678 {TOMTOM_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
7679 {TOMTOM_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
7680 {TOMTOM_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
7681
7682 /* Use 16 bit sample size for TX7 to TX10 */
7683 {TOMTOM_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
7684 {TOMTOM_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
7685 {TOMTOM_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
7686 {TOMTOM_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
7687
7688 /*enable HPF filter for TX paths */
7689 {TOMTOM_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
7690 {TOMTOM_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
7691 {TOMTOM_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
7692 {TOMTOM_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
7693 {TOMTOM_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
7694 {TOMTOM_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
7695 {TOMTOM_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
7696 {TOMTOM_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
7697 {TOMTOM_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
7698 {TOMTOM_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
7699
7700 /* Compander zone selection */
7701 {TOMTOM_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
7702 {TOMTOM_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
7703 {TOMTOM_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
7704 {TOMTOM_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
7705 {TOMTOM_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
7706 {TOMTOM_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
7707
7708 /*
7709 * Setup wavegen timer to 20msec and disable chopper
7710 * as default. This corresponds to Compander OFF
7711 */
7712 {TOMTOM_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
7713 {TOMTOM_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x58},
7714 {TOMTOM_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
7715 {TOMTOM_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
7716
7717 /* Choose max non-overlap time for NCP */
7718 {TOMTOM_A_NCP_CLK, 0xFF, 0xFC},
7719
7720 /* Program the 0.85 volt VBG_REFERENCE */
7721 {TOMTOM_A_BIAS_CURR_CTL_2, 0xFF, 0x04},
7722
7723 /* set MAD input MIC to DMIC1 */
7724 {TOMTOM_A_CDC_MAD_INP_SEL, 0x0F, 0x08},
7725
7726 {TOMTOM_A_INTR_MODE, 0x04, 0x04},
7727};
7728
7729static const struct wcd9xxx_reg_mask_val tomtom_codec_2_0_reg_init_val[] = {
7730 {TOMTOM_A_RX_HPH_L_TEST, 0x08, 0x00},
7731 {TOMTOM_A_RX_HPH_R_TEST, 0x08, 0x00},
7732 {TOMTOM_A_CDC_CLIP_ADJ_SPKR_MIN_CLIP_THRESHOLD, 0xFF, 0x00},
7733 {TOMTOM_A_CDC_CLIP_ADJ_SPKR2_MIN_CLIP_THRESHOLD, 0xFF, 0x00},
7734 {TOMTOM_A_CDC_CLIP_ADJ_SPKR_BOOST_GATING, 0x01, 0x01},
7735 {TOMTOM_A_CDC_CLIP_ADJ_SPKR2_BOOST_GATING, 0x01, 0x01},
7736 {TOMTOM_A_CDC_CLIP_ADJ_SPKR_B1_CTL, 0x01, 0x00},
7737 {TOMTOM_A_CDC_CLIP_ADJ_SPKR2_B1_CTL, 0x01, 0x00},
7738};
7739
7740static void tomtom_codec_init_reg(struct snd_soc_codec *codec)
7741{
7742 u32 i;
7743 struct wcd9xxx *tomtom_core = dev_get_drvdata(codec->dev->parent);
7744
7745 for (i = 0; i < ARRAY_SIZE(tomtom_codec_reg_init_val); i++)
7746 snd_soc_update_bits(codec, tomtom_codec_reg_init_val[i].reg,
7747 tomtom_codec_reg_init_val[i].mask,
7748 tomtom_codec_reg_init_val[i].val);
7749
7750 if (!TOMTOM_IS_1_0(tomtom_core->version)) {
7751 for (i = 0; i < ARRAY_SIZE(tomtom_codec_2_0_reg_init_val); i++)
7752 snd_soc_update_bits(codec,
7753 tomtom_codec_2_0_reg_init_val[i].reg,
7754 tomtom_codec_2_0_reg_init_val[i].mask,
7755 tomtom_codec_2_0_reg_init_val[i].val);
7756 }
7757
7758}
7759
7760static void tomtom_slim_interface_init_reg(struct snd_soc_codec *codec)
7761{
7762 int i;
7763 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
7764
7765 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
7766 wcd9xxx_interface_reg_write(wcd9xxx,
7767 TOMTOM_SLIM_PGD_PORT_INT_EN0 + i,
7768 0xFF);
7769}
7770
7771static int tomtom_setup_irqs(struct tomtom_priv *tomtom)
7772{
7773 int ret = 0;
7774 struct snd_soc_codec *codec = tomtom->codec;
7775 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
7776 struct wcd9xxx_core_resource *core_res =
7777 &wcd9xxx->core_res;
7778
7779 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
7780 tomtom_slimbus_irq, "SLIMBUS Slave", tomtom);
7781 if (ret)
7782 pr_err("%s: Failed to request irq %d\n", __func__,
7783 WCD9XXX_IRQ_SLIMBUS);
7784 else
7785 tomtom_slim_interface_init_reg(codec);
7786
7787 return ret;
7788}
7789
7790static void tomtom_cleanup_irqs(struct tomtom_priv *tomtom)
7791{
7792 struct snd_soc_codec *codec = tomtom->codec;
7793 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
7794 struct wcd9xxx_core_resource *core_res =
7795 &wcd9xxx->core_res;
7796
7797 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tomtom);
7798}
7799
7800static
7801struct firmware_cal *tomtom_get_hwdep_fw_cal(struct snd_soc_codec *codec,
7802 enum wcd_cal_type type)
7803{
7804 struct tomtom_priv *tomtom;
7805 struct firmware_cal *hwdep_cal;
7806
7807 if (!codec) {
7808 pr_err("%s: NULL codec pointer\n", __func__);
7809 return NULL;
7810 }
7811 tomtom = snd_soc_codec_get_drvdata(codec);
7812 hwdep_cal = wcdcal_get_fw_cal(tomtom->fw_data, type);
7813 if (!hwdep_cal) {
7814 dev_err(codec->dev, "%s: cal not sent by %d\n",
7815 __func__, type);
7816 return NULL;
7817 } else {
7818 return hwdep_cal;
7819 }
7820}
7821
7822int tomtom_hs_detect(struct snd_soc_codec *codec,
7823 struct wcd9xxx_mbhc_config *mbhc_cfg)
7824{
7825 int rc;
7826 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
7827
7828 if (mbhc_cfg->insert_detect) {
7829 rc = wcd9xxx_mbhc_start(&tomtom->mbhc, mbhc_cfg);
7830 if (!rc)
7831 tomtom->mbhc_started = true;
7832 } else {
7833 /* MBHC is disabled, so disable Auto pulldown */
7834 snd_soc_update_bits(codec, TOMTOM_A_MBHC_INSERT_DETECT2, 0xC0,
7835 0x00);
7836 snd_soc_update_bits(codec, TOMTOM_A_MICB_CFILT_2_CTL, 0x01,
7837 0x00);
7838 tomtom->mbhc.mbhc_cfg = NULL;
7839 rc = 0;
7840 }
7841 return rc;
7842}
7843EXPORT_SYMBOL(tomtom_hs_detect);
7844
7845void tomtom_hs_detect_exit(struct snd_soc_codec *codec)
7846{
7847 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
7848
7849 wcd9xxx_mbhc_stop(&tomtom->mbhc);
7850 tomtom->mbhc_started = false;
7851}
7852EXPORT_SYMBOL(tomtom_hs_detect_exit);
7853
7854void tomtom_event_register(
7855 int (*machine_event_cb)(struct snd_soc_codec *codec,
7856 enum wcd9xxx_codec_event),
7857 struct snd_soc_codec *codec)
7858{
7859 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
7860
7861 tomtom->machine_codec_event_cb = machine_event_cb;
7862}
7863EXPORT_SYMBOL(tomtom_event_register);
7864
7865void tomtom_register_ext_clk_cb(
7866 int (*codec_ext_clk_en)(struct snd_soc_codec *codec,
7867 int enable, bool dapm),
7868 int (*get_ext_clk_cnt)(void),
7869 struct snd_soc_codec *codec)
7870{
7871 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
7872
7873 tomtom->codec_ext_clk_en_cb = codec_ext_clk_en;
7874 tomtom->codec_get_ext_clk_cnt = get_ext_clk_cnt;
7875}
7876EXPORT_SYMBOL(tomtom_register_ext_clk_cb);
7877
7878static void tomtom_init_slim_slave_cfg(struct snd_soc_codec *codec)
7879{
7880 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
7881 struct afe_param_cdc_slimbus_slave_cfg *cfg;
7882 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
7883 uint64_t eaddr = 0;
7884
7885 cfg = &priv->slimbus_slave_cfg;
7886 cfg->minor_version = 1;
7887 cfg->tx_slave_port_offset = 0;
7888 cfg->rx_slave_port_offset = 16;
7889
7890 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
7891 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
7892 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
7893 cfg->device_enum_addr_msw = eaddr >> 32;
7894
7895 pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
7896}
7897
7898static int tomtom_device_down(struct wcd9xxx *wcd9xxx)
7899{
7900 int count;
7901 struct snd_soc_codec *codec;
7902 struct tomtom_priv *priv;
7903
7904 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
7905 priv = snd_soc_codec_get_drvdata(codec);
7906 wcd_cpe_ssr_event(priv->cpe_core, WCD_CPE_BUS_DOWN_EVENT);
7907 snd_soc_card_change_online_state(codec->component.card, 0);
7908 set_bit(BUS_DOWN, &priv->status_mask);
7909
7910 for (count = 0; count < NUM_CODEC_DAIS; count++)
7911 priv->dai[count].bus_down_in_recovery = true;
7912 return 0;
7913}
7914
7915static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
7916 struct list_head *lh)
7917{
7918 int i;
7919 struct snd_soc_codec *codec = mbhc->codec;
7920 u32 delay;
7921
7922 const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
7923 {TOMTOM_A_TX_COM_BIAS, 0xff, 0xF0},
7924 {WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
7925 {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
7926 {WCD9XXX_A_BUCK_MODE_2, 0xff, 0xEF},
7927 {WCD9XXX_A_BUCK_MODE_2, 0xff, 0xEE},
7928 {TOMTOM_A_NCP_DTEST, 0xff, 0x20},
7929 {WCD9XXX_A_CDC_CLK_OTHR_CTL, 0xff, 0x21},
7930 {WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
7931 {WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
7932
7933 {WCD9XXX_A_BUCK_MODE_2, 0xff, 0xAE},
7934 {WCD9XXX_A_BUCK_MODE_2, 0xff, 0xAA},
7935 {WCD9XXX_A_NCP_CLK, 0xff, 0x9C},
7936 {WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
7937 {WCD9XXX_A_RX_COM_BIAS, 0xff, 0xA0},
7938 {WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
7939 {WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
7940 {WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
7941 {WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
7942 /* Add a delay of 1ms after this reg write */
7943
7944 {WCD9XXX_A_NCP_STATIC, 0xff, 0x28},
7945 {WCD9XXX_A_NCP_EN, 0xff, 0xFF},
7946 /* Add a delay of 1ms after this reg write */
7947
7948 /* set HPHL */
7949 {WCD9XXX_A_RX_HPH_L_TEST, 0xff, 0x00},
7950 {TOMTOM_A_RX_HPH_L_PA_CTL, 0xff, 0x42},
7951 {TOMTOM_A_RX_HPH_BIAS_LDO, 0xff, 0x8C},
7952 {TOMTOM_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
7953 {WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0xE0},
7954 {WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0xEC},
7955
7956 /* set HPHR */
7957 {WCD9XXX_A_RX_HPH_R_TEST, 0xff, 0x00},
7958 {TOMTOM_A_RX_HPH_R_PA_CTL, 0xff, 0x42},
7959 {WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x20},
7960 {WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
7961
7962 /* set HPH PAs */
7963 {WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x2A},
7964 {WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDA},
7965 {WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
7966 {WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
7967 {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0x40},
7968 {WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
7969 {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0x40},
7970 {WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
7971
7972 {TOMTOM_A_RX_HPH_L_ATEST, 0xff, 0x00},
7973 {TOMTOM_A_RX_HPH_R_ATEST, 0xff, 0x00},
7974 };
7975
7976 for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++) {
7977 /*
7978 * Some of the codec registers like BUCK_MODE_1
7979 * and NCP_EN requires 1ms wait time for them
7980 * to take effect. Other register writes for
7981 * PA configuration do not require any wait time.
7982 */
7983 if (reg_set_paon[i].reg == WCD9XXX_A_BUCK_MODE_1 ||
7984 reg_set_paon[i].reg == WCD9XXX_A_NCP_EN)
7985 delay = 1000;
7986 else
7987 delay = 0;
7988 wcd9xxx_soc_update_bits_push(codec, lh,
7989 reg_set_paon[i].reg,
7990 reg_set_paon[i].mask,
7991 reg_set_paon[i].val, delay);
7992 }
7993 pr_debug("%s: PAs are prepared\n", __func__);
7994
7995 return 0;
7996}
7997
7998static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable,
7999 u8 hph_pa)
8000{
8001 struct snd_soc_codec *codec = mbhc->codec;
8002 const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
8003 TOMTOM_WG_TIME_FACTOR_US;
8004 u8 mask = (hph_pa << 4);
8005 u8 pa_en = enable ? mask : ~mask;
8006
8007 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, mask, pa_en);
8008 /* Wait for wave gen time to avoid pop noise */
8009 usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8010 pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
8011 enable ? "enabled" : "disabled", wg_time);
8012 return 0;
8013}
8014
8015static int tomtom_setup_zdet(struct wcd9xxx_mbhc *mbhc,
8016 enum mbhc_impedance_detect_stages stage)
8017{
8018 int ret = 0;
8019 struct snd_soc_codec *codec = mbhc->codec;
8020 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
8021
8022#define __wr(reg, mask, value) \
8023 do { \
8024 ret = wcd9xxx_soc_update_bits_push(codec, \
8025 &tomtom->reg_save_restore, \
8026 reg, mask, value, 0); \
8027 if (ret < 0) \
8028 return ret; \
8029 } while (0)
8030
8031 switch (stage) {
8032
8033 case MBHC_ZDET_PRE_MEASURE:
8034 INIT_LIST_HEAD(&tomtom->reg_save_restore);
8035 wcd9xxx_prepare_static_pa(mbhc, &tomtom->reg_save_restore);
8036 /* Set HPH_MBHC for zdet */
8037 __wr(WCD9XXX_A_MBHC_HPH, 0xff, 0xC4);
8038 usleep_range(10, 10 + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8039 wcd9xxx_enable_static_pa(mbhc, HPH_PA_ENABLE, HPH_PA_L_R);
8040
8041 /* save old value of registers and write the new value */
8042 __wr(WCD9XXX_A_RX_HPH_OCP_CTL, 0xff, 0x69);
8043 __wr(WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x80);
8044 __wr(WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x80);
8045 /* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
8046 __wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xff, 0xC0);
8047 __wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xff, 0xF0);
8048 __wr(TOMTOM_A_TX_7_TXFE_CLKDIV, 0xff, 0x8B);
8049 __wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xff, 0x78);
8050 __wr(WCD9XXX_A_TX_7_MBHC_EN, 0xff, 0x8C);
8051 __wr(WCD9XXX_A_CDC_MBHC_B1_CTL, 0xff, 0xDC);
8052 /* Reset MBHC and set it up for STA */
8053 __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xff, 0x0A);
8054 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x00);
8055 __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xff, 0x02);
8056 __wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xff, 0x80);
8057 __wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0xff, 0x25);
8058 /* Wait for ~50us to let MBHC hardware settle down */
8059 usleep_range(50, 50 + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8060 break;
8061 case MBHC_ZDET_POST_MEASURE:
8062 /* 0x69 for 105 number of samples for PA RAMP */
8063 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0x69);
8064 /* Program the PA Ramp to FS_16K, L shift 1 */
8065 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
8066 0x1 << 4 | 0x6);
8067 /* Reset the PA Ramp */
8068 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
8069 /*
8070 * Connect the PA Ramp to PA chain and release reset with
8071 * keep it connected.
8072 */
8073 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
8074 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
8075
8076 /* Start the PA ramp on HPH L and R */
8077 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
8078 /* Ramp generator takes ~30ms */
8079 usleep_range(TOMTOM_HPH_PA_RAMP_DELAY,
8080 TOMTOM_HPH_PA_RAMP_DELAY +
8081 WCD9XXX_USLEEP_RANGE_MARGIN_US);
8082
8083 /*
8084 * Set the multiplication factor for zdet calculation
8085 * based on the Ramp voltage and Gain used
8086 */
8087 tomtom->zdet_gain_mul_fact = TOMTOM_ZDET_MUL_FACTOR_1X;
8088 break;
8089 case MBHC_ZDET_GAIN_0:
8090 /* Set Gain at 1x */
8091 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_ATEST, 0x00);
8092 snd_soc_write(codec, TOMTOM_A_RX_HPH_R_ATEST, 0x00);
8093 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_PA_CTL, 0x42);
8094 /* Allow 100us for gain registers to settle */
8095 usleep_range(100,
8096 100 + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8097 break;
8098 case MBHC_ZDET_GAIN_UPDATE_1X:
8099 /*
8100 * Set the multiplication factor for zdet calculation
8101 * based on the Gain value used
8102 */
8103 tomtom->zdet_gain_mul_fact = TOMTOM_ZDET_MUL_FACTOR_1X;
8104 break;
8105 case MBHC_ZDET_GAIN_1:
8106 /* Set Gain at 10x */
8107 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_ATEST, 0x10);
8108 snd_soc_write(codec, TOMTOM_A_RX_HPH_R_ATEST, 0x00);
8109 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_PA_CTL, 0x42);
8110 /* Allow 100us for gain registers to settle */
8111 usleep_range(100,
8112 100 + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8113
8114 /*
8115 * Set the multiplication factor for zdet calculation
8116 * based on the Gain value used
8117 */
8118 tomtom->zdet_gain_mul_fact = TOMTOM_ZDET_MUL_FACTOR_10X;
8119 break;
8120 case MBHC_ZDET_GAIN_2:
8121 /* Set Gain at 100x */
8122 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_ATEST, 0x00);
8123 snd_soc_write(codec, TOMTOM_A_RX_HPH_R_ATEST, 0x10);
8124 snd_soc_write(codec, TOMTOM_A_RX_HPH_L_PA_CTL, 0x43);
8125 /* Allow 100us for gain registers to settle */
8126 usleep_range(100,
8127 100 + WCD9XXX_USLEEP_RANGE_MARGIN_US);
8128
8129 /*
8130 * Set the multiplication factor for zdet calculation
8131 * based on the Gain value used
8132 */
8133 tomtom->zdet_gain_mul_fact = TOMTOM_ZDET_MUL_FACTOR_100X;
8134 break;
8135 case MBHC_ZDET_RAMP_DISABLE:
8136 /* Ramp HPH L & R back to Zero */
8137 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
8138 /* 0x69 for 105 number of samples for PA RAMP */
8139 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0x69);
8140 /* Program the PA Ramp to FS_16K, L shift 1 */
8141 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
8142 0x1 << 4 | 0x6);
8143 /* Reset the PA Ramp */
8144 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x17);
8145 /*
8146 * Connect the PA Ramp to PA chain and release reset with
8147 * keep it connected.
8148 */
8149 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
8150 /* Start the PA ramp on HPH L and R */
8151 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
8152 /* Ramp generator takes ~30ms to settle down */
8153 usleep_range(TOMTOM_HPH_PA_RAMP_DELAY,
8154 TOMTOM_HPH_PA_RAMP_DELAY +
8155 WCD9XXX_USLEEP_RANGE_MARGIN_US);
8156 break;
8157 case MBHC_ZDET_HPHR_RAMP_DISABLE:
8158 /* Ramp HPHR back to Zero */
8159 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
8160 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0x69);
8161 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
8162 0x1 << 4 | 0x6);
8163 /* Reset the PA Ramp */
8164 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x17);
8165 /*
8166 * Connect the PA Ramp to PA chain and release reset with
8167 * keep it connected.
8168 */
8169 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
8170 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x08);
8171 /* Ramp generator takes ~30ms to settle down */
8172 usleep_range(TOMTOM_HPH_PA_RAMP_DELAY,
8173 TOMTOM_HPH_PA_RAMP_DELAY +
8174 WCD9XXX_USLEEP_RANGE_MARGIN_US);
8175 break;
8176 case MBHC_ZDET_HPHL_RAMP_DISABLE:
8177 /* Ramp back to Zero */
8178 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
8179 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0x69);
8180 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
8181 0x1 << 4 | 0x6);
8182 /* Reset the PA Ramp */
8183 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x17);
8184 /*
8185 * Connect the PA Ramp to PA chain and release reset with
8186 * keep it connected.
8187 */
8188 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
8189 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x02);
8190 /* Ramp generator takes ~30ms to settle down */
8191 usleep_range(TOMTOM_HPH_PA_RAMP_DELAY,
8192 TOMTOM_HPH_PA_RAMP_DELAY +
8193 WCD9XXX_USLEEP_RANGE_MARGIN_US);
8194 break;
8195 case MBHC_ZDET_HPHR_PA_DISABLE:
8196 /* Disable PA */
8197 wcd9xxx_enable_static_pa(mbhc, HPH_PA_DISABLE, HPH_PA_R);
8198 break;
8199 case MBHC_ZDET_PA_DISABLE:
8200 /* Disable PA */
8201 if (!mbhc->hph_pa_dac_state &&
8202 (!(test_bit(MBHC_EVENT_PA_HPHL, &mbhc->event_state) ||
8203 test_bit(MBHC_EVENT_PA_HPHR, &mbhc->event_state))))
8204 wcd9xxx_enable_static_pa(mbhc, HPH_PA_DISABLE,
8205 HPH_PA_L_R);
8206 else if (!(snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_EN) & 0x10))
8207 wcd9xxx_enable_static_pa(mbhc, HPH_PA_ENABLE, HPH_PA_R);
8208
8209 /* Turn off PA ramp generator */
8210 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x00);
8211 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
8212 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL, 0x00);
8213 snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0x00);
8214
8215 /* Restore registers */
8216 wcd9xxx_restore_registers(codec, &tomtom->reg_save_restore);
8217 break;
8218 }
8219#undef __wr
8220
8221 return ret;
8222}
8223
8224/* Calculate final impedance values for HPH left and right based on formulae */
8225static void tomtom_compute_impedance(struct wcd9xxx_mbhc *mbhc, s16 *l, s16 *r,
8226 uint32_t *zl, uint32_t *zr)
8227{
8228 s64 zln, zrn;
8229 int zld, zrd;
8230 s64 rl = 0, rr = 0;
8231 struct snd_soc_codec *codec;
8232 struct tomtom_priv *tomtom;
8233
8234 if (!mbhc) {
8235 pr_err("%s: Invalid parameters mbhc = %pK\n",
8236 __func__, mbhc);
8237 return;
8238 }
8239 codec = mbhc->codec;
8240 tomtom = snd_soc_codec_get_drvdata(codec);
8241
8242 if (l && zl) {
8243 zln = (s64) (l[1] - l[0]) * tomtom->zdet_gain_mul_fact;
8244 zld = (l[2] - l[0]);
8245 if (zld)
8246 rl = div_s64(zln, zld);
8247 else
8248 /* If L0 and L2 are same, Z has to be on Zone 3.
8249 * Assign a default value so that atleast the value
8250 * is read again with Ramp-up
8251 */
8252 rl = TOMTOM_ZDET_ZONE_3_DEFAULT_VAL;
8253
8254 /* 32-bit LSBs are enough to hold Impedance values */
8255 *zl = (u32) rl;
8256 }
8257 if (r && zr) {
8258 zrn = (s64) (r[1] - r[0]) * tomtom->zdet_gain_mul_fact;
8259 zrd = (r[2] - r[0]);
8260 if (zrd)
8261 rr = div_s64(zrn, zrd);
8262 else
8263 /* If R0 and R2 are same, Z has to be on Zone 3.
8264 * Assign a default value so that atleast the value
8265 * is read again with Ramp-up
8266 */
8267 rr = TOMTOM_ZDET_ZONE_3_DEFAULT_VAL;
8268
8269 /* 32-bit LSBs are enough to hold Impedance values */
8270 *zr = (u32) rr;
8271 }
8272}
8273
8274/*
8275 * Calculate error approximation of impedance values for HPH left
8276 * and HPH right based on QFuse values
8277 */
8278static void tomtom_zdet_error_approx(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
8279 uint32_t *zr)
8280{
8281 struct snd_soc_codec *codec;
8282 struct tomtom_priv *tomtom;
8283 s8 q1_t, q2_t;
8284 s8 q1_m, q2_m;
8285 s8 q1, q2;
8286 u8 div_shift;
8287 int rl_alpha = 0, rr_alpha = 0;
8288 int rl_beta = 0, rr_beta = 0;
8289 u64 rl = 0, rr = 0;
8290 const int mult_factor = TOMTOM_ZDET_ERROR_APPROX_MUL_FACTOR;
8291 const int shift = TOMTOM_ZDET_ERROR_APPROX_SHIFT;
8292
8293 if (!zl || !zr || !mbhc) {
8294 pr_err("%s: Invalid parameters zl = %pK zr = %pK, mbhc = %pK\n",
8295 __func__, zl, zr, mbhc);
8296 return;
8297 }
8298 codec = mbhc->codec;
8299 tomtom = snd_soc_codec_get_drvdata(codec);
8300
8301 if ((tomtom->zdet_gain_mul_fact == TOMTOM_ZDET_MUL_FACTOR_1X) ||
8302 (tomtom->zdet_gain_mul_fact == TOMTOM_ZDET_MUL_FACTOR_10X)) {
8303 q1_t = ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT0) &
8304 0x3) << 0x5);
8305 q1_t |= ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT1) &
8306 0xF8) >> 0x3);
8307 q2_t = ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT1) &
8308 0x7) << 0x4);
8309 q2_t |= ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT2) &
8310 0xF0) >> 0x4);
8311 /* Take out the numeric part of the Qfuse value */
8312 q1_m = q1_t & 0x3F;
8313 q2_m = q2_t & 0x3F;
8314 /* Check the sign part of the Qfuse and adjust value */
8315 q1 = (q1_t & 0x40) ? -q1_m : q1_m;
8316 q2 = (q2_t & 0x40) ? -q2_m : q2_m;
8317 div_shift = 1;
8318 } else {
8319 q1_t = ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT2) &
8320 0xF) << 0x2);
8321 q1_t |= ((snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT3) &
8322 0xC0) >> 0x6);
8323 q2_t = (snd_soc_read(codec, TOMTOM_A_QFUSE_DATA_OUT3) & 0x3F);
8324 /* Take out the numeric part of the Qfuse value */
8325 q1_m = q1_t & 0x1F;
8326 q2_m = q2_t & 0x1F;
8327 /* Check the sign part of the Qfuse and adjust value */
8328 q1 = (q1_t & 0x20) ? -q1_m : q1_m;
8329 q2 = (q2_t & 0x20) ? -q2_m : q2_m;
8330 div_shift = 0;
8331 }
8332
8333 dev_dbg(codec->dev, "%s: qfuse1 = %d, qfuse2 = %d\n",
8334 __func__, q1, q2);
8335 if (!q1 && !q2) {
8336 dev_dbg(codec->dev, "%s: qfuse1 and qfuse2 are 0. Exiting\n",
8337 __func__);
8338 return;
8339 }
8340
8341 /*
8342 * Use multiplication and shift to avoid floating point math
8343 * The Z value is calculated with the below formulae using
8344 * the Qfuse value-
8345 * zl = zl * [1 - {(Q1 / div) / 100}] (Include sign for Q1)
8346 * zr = zr * [1 - {(Q2 / div) / 100}] (Include sign for Q2)
8347 * We multiply by 65536 and shift 16 times to get the approx result
8348 * div = 4 for 1x gain, div = 2 for 10x/100x gain
8349 */
8350 /* Q1/4 */
8351 rl_alpha = q1 >> div_shift;
8352 rl_alpha = 100 - rl_alpha;
8353 /* {rl_alpha/100} * 65536 */
8354 rl_beta = rl_alpha * mult_factor;
8355 rl = (u64) *zl * rl_beta;
8356 /* rl/65536 */
8357 rl = (u64) rl >> shift;
8358
8359 rr_alpha = q2 >> div_shift;
8360 rr_alpha = 100 - rr_alpha;
8361 rr_beta = rr_alpha * mult_factor;
8362 rr = (u64) *zr * rr_beta;
8363 rr = (u64) rr >> shift;
8364
8365 dev_dbg(codec->dev, "%s: rl = 0x%llx (%lld) \t rr = 0x%llx (%lld)\n",
8366 __func__, rl, rl, rr, rr);
8367
8368 *zl = (u32) rl;
8369 *zr = (u32) rr;
8370}
8371
8372static enum wcd9xxx_cdc_type tomtom_get_cdc_type(void)
8373{
8374 return WCD9XXX_CDC_TYPE_TOMTOM;
8375}
8376
8377static bool tomtom_mbhc_ins_rem_status(struct snd_soc_codec *codec)
8378{
8379 return !(snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DET_STATUS) &
8380 (1 << 4));
8381}
8382
8383static void tomtom_mbhc_micb_pulldown_ctrl(struct wcd9xxx_mbhc *mbhc,
8384 bool enable)
8385{
8386 struct snd_soc_codec *codec = mbhc->codec;
8387
8388 if (!enable) {
8389 /* Remove automatic pulldown on micbias */
8390 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
8391 0x01, 0x00);
8392 } else {
8393 /* Enable automatic pulldown on micbias */
8394 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
8395 0x01, 0x01);
8396 }
8397}
8398
8399static void tomtom_codec_hph_auto_pull_down(struct snd_soc_codec *codec,
8400 bool enable)
8401{
8402 struct wcd9xxx *tomtom_core = dev_get_drvdata(codec->dev->parent);
8403
8404 if (TOMTOM_IS_1_0(tomtom_core->version))
8405 return;
8406
8407 dev_dbg(codec->dev, "%s: %s auto pull down\n", __func__,
8408 enable ? "enable" : "disable");
8409 if (enable) {
8410 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_L_TEST, 0x08, 0x08);
8411 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_R_TEST, 0x08, 0x08);
8412 } else {
8413 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_L_TEST, 0x08, 0x00);
8414 snd_soc_update_bits(codec, TOMTOM_A_RX_HPH_R_TEST, 0x08, 0x00);
8415 }
8416}
8417
8418static const struct wcd9xxx_mbhc_cb mbhc_cb = {
8419 .get_cdc_type = tomtom_get_cdc_type,
8420 .setup_zdet = tomtom_setup_zdet,
8421 .compute_impedance = tomtom_compute_impedance,
8422 .zdet_error_approx = tomtom_zdet_error_approx,
8423 .insert_rem_status = tomtom_mbhc_ins_rem_status,
8424 .micbias_pulldown_ctrl = tomtom_mbhc_micb_pulldown_ctrl,
8425 .codec_rco_ctrl = tomtom_codec_internal_rco_ctrl,
8426 .hph_auto_pulldown_ctrl = tomtom_codec_hph_auto_pull_down,
8427 .get_hwdep_fw_cal = tomtom_get_hwdep_fw_cal,
8428};
8429
8430static const struct wcd9xxx_mbhc_intr cdc_intr_ids = {
8431 .poll_plug_rem = WCD9XXX_IRQ_MBHC_REMOVAL,
8432 .shortavg_complete = WCD9XXX_IRQ_MBHC_SHORT_TERM,
8433 .potential_button_press = WCD9XXX_IRQ_MBHC_PRESS,
8434 .button_release = WCD9XXX_IRQ_MBHC_RELEASE,
8435 .dce_est_complete = WCD9XXX_IRQ_MBHC_POTENTIAL,
8436 .insertion = WCD9XXX_IRQ_MBHC_INSERTION,
8437 .hph_left_ocp = WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
8438 .hph_right_ocp = WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
8439 .hs_jack_switch = WCD9330_IRQ_MBHC_JACK_SWITCH,
8440};
8441
8442static int tomtom_post_reset_cb(struct wcd9xxx *wcd9xxx)
8443{
8444 int ret = 0;
8445 struct snd_soc_codec *codec;
8446 struct tomtom_priv *tomtom;
8447 int rco_clk_rate;
8448
8449 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
8450 tomtom = snd_soc_codec_get_drvdata(codec);
8451
8452 snd_soc_card_change_online_state(codec->component.card, 1);
8453 clear_bit(BUS_DOWN, &tomtom->status_mask);
8454
8455 mutex_lock(&tomtom->codec_mutex);
8456
8457 tomtom_update_reg_defaults(codec);
8458 if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_12P288MHZ)
8459 snd_soc_update_bits(codec, TOMTOM_A_CHIP_CTL, 0x06, 0x0);
8460 else if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_9P6MHZ)
8461 snd_soc_update_bits(codec, TOMTOM_A_CHIP_CTL, 0x06, 0x2);
8462 tomtom_codec_init_reg(codec);
8463
8464 snd_soc_cache_sync(codec);
8465
8466 ret = tomtom_handle_pdata(tomtom);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08008467 if (ret < 0)
Banajit Goswamide8271c2017-01-18 00:28:59 -08008468 pr_err("%s: bad pdata\n", __func__);
8469
8470 tomtom_init_slim_slave_cfg(codec);
8471 tomtom_slim_interface_init_reg(codec);
8472 wcd_cpe_ssr_event(tomtom->cpe_core, WCD_CPE_BUS_UP_EVENT);
8473 wcd9xxx_resmgr_post_ssr(&tomtom->resmgr);
8474
8475 if (tomtom->mbhc_started) {
8476 wcd9xxx_mbhc_deinit(&tomtom->mbhc);
8477 tomtom->mbhc_started = false;
8478
8479 if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_12P288MHZ)
8480 rco_clk_rate = TOMTOM_MCLK_CLK_12P288MHZ;
8481 else
8482 rco_clk_rate = TOMTOM_MCLK_CLK_9P6MHZ;
8483
8484 ret = wcd9xxx_mbhc_init(&tomtom->mbhc, &tomtom->resmgr, codec,
8485 tomtom_enable_mbhc_micbias,
8486 &mbhc_cb, &cdc_intr_ids,
8487 rco_clk_rate, TOMTOM_ZDET_SUPPORTED);
8488 if (ret)
8489 pr_err("%s: mbhc init failed %d\n", __func__, ret);
8490 else
8491 tomtom_hs_detect(codec, tomtom->mbhc.mbhc_cfg);
8492 }
8493
8494 if (tomtom->machine_codec_event_cb)
8495 tomtom->machine_codec_event_cb(codec,
8496 WCD9XXX_CODEC_EVENT_CODEC_UP);
8497
8498 tomtom_cleanup_irqs(tomtom);
8499 ret = tomtom_setup_irqs(tomtom);
8500 if (ret)
8501 pr_err("%s: Failed to setup irq: %d\n", __func__, ret);
8502
8503 /*
8504 * After SSR, the qfuse sensing is lost.
8505 * Perform qfuse sensing again after SSR
8506 * handling is finished.
8507 */
8508 tomtom_enable_qfuse_sensing(codec);
8509 mutex_unlock(&tomtom->codec_mutex);
8510 return ret;
8511}
8512
8513void *tomtom_get_afe_config(struct snd_soc_codec *codec,
8514 enum afe_config_type config_type)
8515{
8516 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
8517
8518 switch (config_type) {
8519 case AFE_SLIMBUS_SLAVE_CONFIG:
8520 return &priv->slimbus_slave_cfg;
8521 case AFE_CDC_REGISTERS_CONFIG:
8522 return &tomtom_audio_reg_cfg;
8523 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
8524 return &tomtom_slimbus_slave_port_cfg;
8525 case AFE_AANC_VERSION:
8526 return &tomtom_cdc_aanc_version;
8527 case AFE_CLIP_BANK_SEL:
8528 return &clip_bank_sel;
8529 case AFE_CDC_CLIP_REGISTERS_CONFIG:
8530 return &tomtom_clip_reg_cfg;
8531 default:
8532 pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
8533 return NULL;
8534 }
8535}
8536
8537static struct wcd9xxx_reg_address tomtom_reg_address = {
8538 .micb_4_mbhc = TOMTOM_A_MICB_4_MBHC,
8539 .micb_4_int_rbias = TOMTOM_A_MICB_4_INT_RBIAS,
8540 .micb_4_ctl = TOMTOM_A_MICB_4_CTL,
8541};
8542
8543static int wcd9xxx_ssr_register(struct wcd9xxx *control,
8544 int (*device_down_cb)(struct wcd9xxx *wcd9xxx),
8545 int (*device_up_cb)(struct wcd9xxx *wcd9xxx),
8546 void *priv)
8547{
8548 control->dev_down = device_down_cb;
8549 control->post_reset = device_up_cb;
8550 control->ssr_priv = priv;
8551 return 0;
8552}
8553
8554static const struct snd_soc_dapm_widget tomtom_1_dapm_widgets[] = {
8555 SND_SOC_DAPM_ADC_E("ADC1", NULL, TOMTOM_A_TX_1_GAIN, 7, 0,
8556 tomtom_codec_enable_adc,
8557 SND_SOC_DAPM_PRE_PMU |
8558 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
8559 SND_SOC_DAPM_ADC_E("ADC2", NULL, TOMTOM_A_TX_2_GAIN, 7, 0,
8560 tomtom_codec_enable_adc,
8561 SND_SOC_DAPM_PRE_PMU |
8562 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
8563 SND_SOC_DAPM_ADC_E("ADC3", NULL, TOMTOM_A_TX_3_GAIN, 7, 0,
8564 tomtom_codec_enable_adc,
8565 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
8566 SND_SOC_DAPM_POST_PMD),
8567 SND_SOC_DAPM_ADC_E("ADC4", NULL, TOMTOM_A_TX_4_GAIN, 7, 0,
8568 tomtom_codec_enable_adc,
8569 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
8570 SND_SOC_DAPM_POST_PMD),
8571 SND_SOC_DAPM_ADC_E("ADC5", NULL, TOMTOM_A_TX_5_GAIN, 7, 0,
8572 tomtom_codec_enable_adc,
8573 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
8574 SND_SOC_DAPM_POST_PMD),
8575 SND_SOC_DAPM_ADC_E("ADC6", NULL, TOMTOM_A_TX_6_GAIN, 7, 0,
8576 tomtom_codec_enable_adc,
8577 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
8578 SND_SOC_DAPM_POST_PMD),
8579};
8580
8581static struct regulator *tomtom_codec_find_regulator(struct snd_soc_codec *cdc,
8582 const char *name)
8583{
8584 int i;
8585 struct wcd9xxx *core = dev_get_drvdata(cdc->dev->parent);
8586
8587 for (i = 0; i < core->num_of_supplies; i++) {
8588 if (core->supplies[i].supply &&
8589 !strcmp(core->supplies[i].supply, name))
8590 return core->supplies[i].consumer;
8591 }
8592
8593 return NULL;
8594}
8595
8596static struct wcd_cpe_core *tomtom_codec_get_cpe_core(
8597 struct snd_soc_codec *codec)
8598{
8599 struct tomtom_priv *priv = snd_soc_codec_get_drvdata(codec);
8600
8601 return priv->cpe_core;
8602}
8603
8604static int tomtom_codec_fll_enable(struct snd_soc_codec *codec,
8605 bool enable)
8606{
8607 struct wcd9xxx *wcd9xxx;
8608
8609 if (!codec || !codec->control_data) {
8610 pr_err("%s: Invalid codec handle, %pK\n",
8611 __func__, codec);
8612 return -EINVAL;
8613 }
8614
8615 wcd9xxx = codec->control_data;
8616
8617 dev_dbg(codec->dev, "%s: %s, mclk_rate = %d\n",
8618 __func__, (enable ? "enable" : "disable"),
8619 wcd9xxx->mclk_rate);
8620
8621 switch (wcd9xxx->mclk_rate) {
8622 case TOMTOM_MCLK_CLK_9P6MHZ:
8623 snd_soc_update_bits(codec, TOMTOM_A_FLL_NREF,
8624 0x1F, 0x15);
8625 snd_soc_update_bits(codec, TOMTOM_A_FLL_KDCO_TUNE,
8626 0x07, 0x06);
8627 snd_soc_write(codec, TOMTOM_A_FLL_LOCK_THRESH, 0xD1);
8628 snd_soc_write(codec, TOMTOM_A_FLL_LOCK_DET_COUNT,
8629 0x40);
8630 break;
8631 case TOMTOM_MCLK_CLK_12P288MHZ:
8632 snd_soc_update_bits(codec, TOMTOM_A_FLL_NREF,
8633 0x1F, 0x11);
8634 snd_soc_update_bits(codec, TOMTOM_A_FLL_KDCO_TUNE,
8635 0x07, 0x05);
8636 snd_soc_write(codec, TOMTOM_A_FLL_LOCK_THRESH, 0xB1);
8637 snd_soc_write(codec, TOMTOM_A_FLL_LOCK_DET_COUNT,
8638 0x40);
8639 break;
8640 }
8641
8642 return 0;
8643}
8644
8645static int tomtom_codec_slim_reserve_bw(struct snd_soc_codec *codec,
8646 u32 bw_ops, bool commit)
8647{
8648 struct wcd9xxx *wcd9xxx;
8649
8650 if (!codec) {
8651 pr_err("%s: Invalid handle to codec\n",
8652 __func__);
8653 return -EINVAL;
8654 }
8655
8656 wcd9xxx = dev_get_drvdata(codec->dev->parent);
8657
8658 if (!wcd9xxx) {
8659 dev_err(codec->dev, "%s: Invalid parent drv_data\n",
8660 __func__);
8661 return -EINVAL;
8662 }
8663
8664 return wcd9xxx_slim_reserve_bw(wcd9xxx, bw_ops, commit);
8665}
8666
8667static int tomtom_codec_vote_max_bw(struct snd_soc_codec *codec,
8668 bool vote)
8669{
8670 u32 bw_ops;
8671
8672 if (vote)
8673 bw_ops = SLIM_BW_CLK_GEAR_9;
8674 else
8675 bw_ops = SLIM_BW_UNVOTE;
8676
8677 return tomtom_codec_slim_reserve_bw(codec,
8678 bw_ops, true);
8679}
8680
8681static const struct wcd9xxx_resmgr_cb resmgr_cb = {
8682 .cdc_rco_ctrl = tomtom_codec_internal_rco_ctrl,
8683};
8684
8685static int tomtom_cpe_err_irq_control(struct snd_soc_codec *codec,
8686 enum cpe_err_irq_cntl_type cntl_type, u8 *status)
8687{
8688 switch (cntl_type) {
8689 case CPE_ERR_IRQ_MASK:
8690 snd_soc_update_bits(codec,
8691 TOMTOM_A_SVASS_INT_MASK,
8692 0x3F, 0x3F);
8693 break;
8694 case CPE_ERR_IRQ_UNMASK:
8695 snd_soc_update_bits(codec,
8696 TOMTOM_A_SVASS_INT_MASK,
8697 0x3F, 0x0C);
8698 break;
8699 case CPE_ERR_IRQ_CLEAR:
8700 snd_soc_update_bits(codec,
8701 TOMTOM_A_SVASS_INT_CLR,
8702 0x3F, 0x3F);
8703 break;
8704 case CPE_ERR_IRQ_STATUS:
8705 if (!status)
8706 return -EINVAL;
8707 *status = snd_soc_read(codec,
8708 TOMTOM_A_SVASS_INT_STATUS);
8709 break;
8710 }
8711
8712 return 0;
8713}
8714
8715static const struct wcd_cpe_cdc_cb cpe_cb = {
8716 .cdc_clk_en = tomtom_codec_internal_rco_ctrl,
8717 .cpe_clk_en = tomtom_codec_fll_enable,
8718 .lab_cdc_ch_ctl = tomtom_codec_enable_slimtx_mad,
8719 .cdc_ext_clk = tomtom_codec_ext_clk_en,
8720 .bus_vote_bw = tomtom_codec_vote_max_bw,
8721 .cpe_err_irq_control = tomtom_cpe_err_irq_control,
8722};
8723
8724static struct cpe_svc_init_param cpe_svc_params = {
8725 .version = 0,
8726 .query_freq_plans_cb = NULL,
8727 .change_freq_plan_cb = NULL,
8728};
8729
8730static int tomtom_cpe_initialize(struct snd_soc_codec *codec)
8731{
8732 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
8733 struct wcd_cpe_params cpe_params;
8734
8735 memset(&cpe_params, 0,
8736 sizeof(struct wcd_cpe_params));
8737 cpe_params.codec = codec;
8738 cpe_params.get_cpe_core = tomtom_codec_get_cpe_core;
8739 cpe_params.cdc_cb = &cpe_cb;
8740 cpe_params.dbg_mode = cpe_debug_mode;
8741 cpe_params.cdc_major_ver = CPE_SVC_CODEC_TOMTOM;
8742 cpe_params.cdc_minor_ver = CPE_SVC_CODEC_V1P0;
8743 cpe_params.cdc_id = CPE_SVC_CODEC_TOMTOM;
8744
8745 cpe_params.cdc_irq_info.cpe_engine_irq =
8746 WCD9330_IRQ_SVASS_ENGINE;
8747 cpe_params.cdc_irq_info.cpe_err_irq =
8748 WCD9330_IRQ_SVASS_ERR_EXCEPTION;
8749 cpe_params.cdc_irq_info.cpe_fatal_irqs =
8750 TOMTOM_CPE_FATAL_IRQS;
8751
8752 cpe_svc_params.context = codec;
8753 cpe_params.cpe_svc_params = &cpe_svc_params;
8754
8755 tomtom->cpe_core = wcd_cpe_init("cpe", codec,
8756 &cpe_params);
8757 if (IS_ERR_OR_NULL(tomtom->cpe_core)) {
8758 dev_err(codec->dev,
8759 "%s: Failed to enable CPE\n",
8760 __func__);
8761 return -EINVAL;
8762 }
8763
8764 return 0;
8765}
8766
Banajit Goswami2be7b482017-02-03 23:32:37 -08008767static int tomtom_codec_probe(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08008768{
8769 struct wcd9xxx *control;
8770 struct tomtom_priv *tomtom;
8771 struct wcd9xxx_pdata *pdata;
8772 struct wcd9xxx *wcd9xxx;
8773 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
8774 int ret = 0;
8775 int i, rco_clk_rate;
8776 void *ptr = NULL;
8777 struct wcd9xxx_core_resource *core_res;
8778 struct clk *wcd_ext_clk = NULL;
8779
8780 dev_info(codec->dev, "%s()\n", __func__);
8781
8782 control = dev_get_drvdata(codec->dev->parent);
8783
8784 tomtom = snd_soc_codec_get_drvdata(codec);
8785
8786 wcd9xxx_ssr_register(control, tomtom_device_down,
8787 tomtom_post_reset_cb, (void *)codec);
8788
8789 for (i = 0; i < NUM_DECIMATORS; i++) {
8790 tx_hpf_work[i].tomtom = tomtom;
8791 tx_hpf_work[i].decimator = i + 1;
8792 tx_hpf_work[i].tx_hpf_bypass = false;
8793 INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
8794 tx_hpf_corner_freq_callback);
8795 }
8796
8797 wcd9xxx = control;
8798 if (!of_find_property(wcd9xxx->dev->of_node, "clock-names", NULL)) {
8799 dev_dbg(wcd9xxx->dev, "%s: codec not using audio-ext-clk driver\n",
8800 __func__);
8801 } else {
8802 wcd_ext_clk = clk_get(wcd9xxx->dev, "wcd_clk");
8803 if (IS_ERR(wcd_ext_clk)) {
8804 dev_err(codec->dev, "%s: clk get %s failed\n",
8805 __func__, "wcd_ext_clk");
8806 goto err_nomem_slimch;
8807 }
8808 }
8809 tomtom->wcd_ext_clk = wcd_ext_clk;
8810 core_res = &wcd9xxx->core_res;
8811 pdata = dev_get_platdata(codec->dev->parent);
8812 /* codec resmgr module init */
8813 ret = wcd9xxx_resmgr_init(&tomtom->resmgr, codec, core_res, pdata,
8814 &pdata->micbias, &tomtom_reg_address,
8815 &resmgr_cb, WCD9XXX_CDC_TYPE_TOMTOM);
8816 if (ret) {
8817 pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
8818 goto err_nomem_slimch;
8819 }
8820
8821 tomtom->clsh_d.buck_mv = tomtom_codec_get_buck_mv(codec);
8822 /* TomTom does not support dynamic switching of vdd_cp */
8823 tomtom->clsh_d.is_dynamic_vdd_cp = false;
8824 wcd9xxx_clsh_init(&tomtom->clsh_d, &tomtom->resmgr);
8825
8826 if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_12P288MHZ)
8827 rco_clk_rate = TOMTOM_MCLK_CLK_12P288MHZ;
8828 else
8829 rco_clk_rate = TOMTOM_MCLK_CLK_9P6MHZ;
8830
8831 tomtom->fw_data = kzalloc(sizeof(*(tomtom->fw_data)), GFP_KERNEL);
8832 if (!tomtom->fw_data)
8833 goto err_nomem_slimch;
8834 set_bit(WCD9XXX_ANC_CAL, tomtom->fw_data->cal_bit);
8835 set_bit(WCD9XXX_MAD_CAL, tomtom->fw_data->cal_bit);
8836 set_bit(WCD9XXX_MBHC_CAL, tomtom->fw_data->cal_bit);
8837 ret = wcd_cal_create_hwdep(tomtom->fw_data,
8838 WCD9XXX_CODEC_HWDEP_NODE, codec);
8839 if (ret < 0) {
8840 dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
8841 goto err_hwdep;
8842 }
8843
8844 /* init and start mbhc */
8845 ret = wcd9xxx_mbhc_init(&tomtom->mbhc, &tomtom->resmgr, codec,
8846 tomtom_enable_mbhc_micbias,
8847 &mbhc_cb, &cdc_intr_ids,
8848 rco_clk_rate, TOMTOM_ZDET_SUPPORTED);
8849 if (ret) {
8850 pr_err("%s: mbhc init failed %d\n", __func__, ret);
8851 goto err_hwdep;
8852 }
8853
8854 tomtom->codec = codec;
8855 for (i = 0; i < COMPANDER_MAX; i++) {
8856 tomtom->comp_enabled[i] = 0;
8857 tomtom->comp_fs[i] = COMPANDER_FS_48KHZ;
8858 }
8859 tomtom->intf_type = wcd9xxx_get_intf_type();
8860 tomtom->aux_pga_cnt = 0;
8861 tomtom->aux_l_gain = 0x1F;
8862 tomtom->aux_r_gain = 0x1F;
8863 tomtom->ldo_h_users = 0;
8864 tomtom->micb_2_users = 0;
8865 tomtom_update_reg_defaults(codec);
8866 pr_debug("%s: MCLK Rate = %x\n", __func__, wcd9xxx->mclk_rate);
8867 if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_12P288MHZ)
8868 snd_soc_update_bits(codec, TOMTOM_A_CHIP_CTL, 0x06, 0x0);
8869 else if (wcd9xxx->mclk_rate == TOMTOM_MCLK_CLK_9P6MHZ)
8870 snd_soc_update_bits(codec, TOMTOM_A_CHIP_CTL, 0x06, 0x2);
8871 tomtom_codec_init_reg(codec);
8872
8873 ret = tomtom_handle_pdata(tomtom);
Xiaoyu Ye1a2d8bd92017-01-31 18:54:15 -08008874 if (ret < 0) {
Banajit Goswamide8271c2017-01-18 00:28:59 -08008875 pr_err("%s: bad pdata\n", __func__);
8876 goto err_hwdep;
8877 }
8878
8879 tomtom->spkdrv_reg = tomtom_codec_find_regulator(codec,
8880 WCD9XXX_VDD_SPKDRV_NAME);
8881 tomtom->spkdrv2_reg = tomtom_codec_find_regulator(codec,
8882 WCD9XXX_VDD_SPKDRV2_NAME);
8883
8884 ptr = kmalloc((sizeof(tomtom_rx_chs) +
8885 sizeof(tomtom_tx_chs)), GFP_KERNEL);
8886 if (!ptr) {
8887 ret = -ENOMEM;
8888 goto err_hwdep;
8889 }
8890
8891 if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
8892 snd_soc_dapm_new_controls(dapm, tomtom_dapm_i2s_widgets,
8893 ARRAY_SIZE(tomtom_dapm_i2s_widgets));
8894 snd_soc_dapm_add_routes(dapm, audio_i2s_map,
8895 ARRAY_SIZE(audio_i2s_map));
8896 for (i = 0; i < ARRAY_SIZE(tomtom_i2s_dai); i++)
8897 INIT_LIST_HEAD(&tomtom->dai[i].wcd9xxx_ch_list);
8898 } else if (tomtom->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
8899 for (i = 0; i < NUM_CODEC_DAIS; i++) {
8900 INIT_LIST_HEAD(&tomtom->dai[i].wcd9xxx_ch_list);
8901 init_waitqueue_head(&tomtom->dai[i].dai_wait);
8902 }
8903 tomtom_slimbus_slave_port_cfg.slave_dev_intfdev_la =
8904 control->slim_slave->laddr;
8905 tomtom_slimbus_slave_port_cfg.slave_dev_pgd_la =
8906 control->slim->laddr;
8907 tomtom_slimbus_slave_port_cfg.slave_port_mapping[0] =
8908 TOMTOM_MAD_SLIMBUS_TX_PORT;
8909
8910 tomtom_init_slim_slave_cfg(codec);
8911 }
8912
8913 snd_soc_dapm_new_controls(dapm, tomtom_1_dapm_widgets,
8914 ARRAY_SIZE(tomtom_1_dapm_widgets));
8915 snd_soc_add_codec_controls(codec,
8916 tomtom_1_x_analog_gain_controls,
8917 ARRAY_SIZE(tomtom_1_x_analog_gain_controls));
8918
8919 snd_soc_add_codec_controls(codec, impedance_detect_controls,
8920 ARRAY_SIZE(impedance_detect_controls));
8921 snd_soc_add_codec_controls(codec, hph_type_detect_controls,
8922 ARRAY_SIZE(hph_type_detect_controls));
8923
8924 control->num_rx_port = TOMTOM_RX_MAX;
8925 control->rx_chs = ptr;
8926 memcpy(control->rx_chs, tomtom_rx_chs, sizeof(tomtom_rx_chs));
8927 control->num_tx_port = TOMTOM_TX_MAX;
8928 control->tx_chs = ptr + sizeof(tomtom_rx_chs);
8929 memcpy(control->tx_chs, tomtom_tx_chs, sizeof(tomtom_tx_chs));
8930
8931 snd_soc_dapm_sync(dapm);
8932
8933 ret = tomtom_setup_irqs(tomtom);
8934 if (ret) {
8935 pr_err("%s: tomtom irq setup failed %d\n", __func__, ret);
8936 goto err_pdata;
8937 }
8938
8939 atomic_set(&kp_tomtom_priv, (unsigned long)tomtom);
8940 mutex_lock(&tomtom->codec_mutex);
8941 snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
8942 snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
8943 snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
8944 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
8945 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
8946 mutex_unlock(&tomtom->codec_mutex);
8947 snd_soc_dapm_sync(dapm);
8948
8949 codec->component.ignore_pmdown_time = 1;
8950 ret = tomtom_cpe_initialize(codec);
8951 if (ret) {
8952 dev_info(codec->dev,
8953 "%s: cpe initialization failed, ret = %d\n",
8954 __func__, ret);
8955 /* Do not fail probe if CPE failed */
8956 ret = 0;
8957 }
8958 return ret;
8959
8960err_pdata:
8961 kfree(ptr);
8962 control->rx_chs = NULL;
8963 control->tx_chs = NULL;
8964err_hwdep:
8965 kfree(tomtom->fw_data);
8966 tomtom->fw_data = NULL;
8967err_nomem_slimch:
8968 devm_kfree(codec->dev, tomtom);
8969 return ret;
8970}
Banajit Goswami2be7b482017-02-03 23:32:37 -08008971static int tomtom_codec_remove(struct snd_soc_codec *codec)
Banajit Goswamide8271c2017-01-18 00:28:59 -08008972{
8973 struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
8974 struct wcd9xxx *control;
8975
8976 WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
8977 atomic_set(&kp_tomtom_priv, 0);
8978
8979 WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
8980
8981 control = dev_get_drvdata(codec->dev->parent);
8982 control->rx_chs = NULL;
8983 control->tx_chs = NULL;
8984
8985 if (tomtom->wcd_ext_clk)
8986 clk_put(tomtom->wcd_ext_clk);
8987 tomtom_cleanup_irqs(tomtom);
8988
8989 /* cleanup MBHC */
8990 wcd9xxx_mbhc_deinit(&tomtom->mbhc);
8991 /* cleanup resmgr */
8992 wcd9xxx_resmgr_deinit(&tomtom->resmgr);
8993
8994 tomtom->spkdrv_reg = NULL;
8995 tomtom->spkdrv2_reg = NULL;
8996
8997 devm_kfree(codec->dev, tomtom);
Banajit Goswamie0b20e12017-02-05 18:11:11 -08008998 return 0;
Banajit Goswamide8271c2017-01-18 00:28:59 -08008999}
9000
9001static struct regmap *tomtom_get_regmap(struct device *dev)
9002{
9003 struct wcd9xxx *control = dev_get_drvdata(dev->parent);
9004
9005 return control->regmap;
9006}
9007
9008static struct snd_soc_codec_driver soc_codec_dev_tomtom = {
Banajit Goswami2be7b482017-02-03 23:32:37 -08009009 .probe = tomtom_codec_probe,
9010 .remove = tomtom_codec_remove,
Banajit Goswamide8271c2017-01-18 00:28:59 -08009011 .get_regmap = tomtom_get_regmap,
Banajit Goswami8e306f02016-12-15 20:49:07 -08009012 .component_driver = {
Banajit Goswamiaf472112017-01-29 22:15:11 -08009013 .controls = tomtom_snd_controls,
9014 .num_controls = ARRAY_SIZE(tomtom_snd_controls),
Banajit Goswami8e306f02016-12-15 20:49:07 -08009015 .dapm_widgets = tomtom_dapm_widgets,
9016 .num_dapm_widgets = ARRAY_SIZE(tomtom_dapm_widgets),
9017 .dapm_routes = audio_map,
9018 .num_dapm_routes = ARRAY_SIZE(audio_map),
9019 },
Banajit Goswamide8271c2017-01-18 00:28:59 -08009020};
9021
9022#ifdef CONFIG_PM
9023static int tomtom_suspend(struct device *dev)
9024{
9025 dev_dbg(dev, "%s: system suspend\n", __func__);
9026 return 0;
9027}
9028
9029static int tomtom_resume(struct device *dev)
9030{
9031 struct platform_device *pdev = to_platform_device(dev);
9032 struct tomtom_priv *tomtom = platform_get_drvdata(pdev);
9033
9034 if (!tomtom) {
9035 dev_err(dev, "%s: tomtom private data is NULL\n", __func__);
9036 return -EINVAL;
9037 }
9038 dev_dbg(dev, "%s: system resume\n", __func__);
9039 /* Notify */
9040 wcd9xxx_resmgr_notifier_call(&tomtom->resmgr,
9041 WCD9XXX_EVENT_POST_RESUME);
9042 return 0;
9043}
9044
9045static const struct dev_pm_ops tomtom_pm_ops = {
9046 .suspend = tomtom_suspend,
9047 .resume = tomtom_resume,
9048};
9049#endif
9050
9051static int tomtom_probe(struct platform_device *pdev)
9052{
9053 int ret = 0;
9054 struct tomtom_priv *tomtom;
9055
9056 tomtom = devm_kzalloc(&pdev->dev, sizeof(struct tomtom_priv),
9057 GFP_KERNEL);
9058 if (!tomtom)
9059 return -ENOMEM;
9060
9061 platform_set_drvdata(pdev, tomtom);
9062
9063 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
9064 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tomtom,
9065 tomtom_dai, ARRAY_SIZE(tomtom_dai));
9066 else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
9067 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tomtom,
9068 tomtom_i2s_dai, ARRAY_SIZE(tomtom_i2s_dai));
9069 mutex_init(&tomtom->codec_mutex);
9070 return ret;
9071}
9072static int tomtom_remove(struct platform_device *pdev)
9073{
9074 struct tomtom_priv *tomtom = platform_get_drvdata(pdev);
9075
9076 mutex_destroy(&tomtom->codec_mutex);
9077 snd_soc_unregister_codec(&pdev->dev);
9078 return 0;
9079}
9080static struct platform_driver tomtom_codec_driver = {
9081 .probe = tomtom_probe,
9082 .remove = tomtom_remove,
9083 .driver = {
9084 .name = "tomtom_codec",
9085 .owner = THIS_MODULE,
9086#ifdef CONFIG_PM
9087 .pm = &tomtom_pm_ops,
9088#endif
9089 },
9090};
9091
9092static int __init tomtom_codec_init(void)
9093{
9094 return platform_driver_register(&tomtom_codec_driver);
9095}
9096
9097static void __exit tomtom_codec_exit(void)
9098{
9099 platform_driver_unregister(&tomtom_codec_driver);
9100}
9101
9102module_init(tomtom_codec_init);
9103module_exit(tomtom_codec_exit);
9104
9105MODULE_DESCRIPTION("TomTom codec driver");
9106MODULE_LICENSE("GPL v2");