blob: bb877335c56f82ef6e0026e08346ad309a0cb582 [file] [log] [blame]
Banajit Goswamide8271c2017-01-18 00:28:59 -08001/* Copyright (c) 2015-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/clk.h>
24#include <linux/delay.h>
25#include <linux/pm_runtime.h>
26#include <linux/kernel.h>
27#include <linux/gpio.h>
28#include <linux/regmap.h>
29#include <linux/spi/spi.h>
30#include <linux/mfd/wcd9xxx/core.h>
31#include <linux/mfd/wcd9xxx/wcd9xxx-irq.h>
32#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
33#include <linux/mfd/wcd934x/registers.h>
34#include <linux/mfd/wcd9xxx/pdata.h>
35#include <linux/regulator/consumer.h>
36#include <linux/soundwire/swr-wcd.h>
37#include <sound/pcm.h>
38#include <sound/pcm_params.h>
39#include <sound/soc.h>
40#include <sound/soc-dapm.h>
41#include <sound/tlv.h>
42#include <sound/info.h>
43#include "wcd934x.h"
44#include "wcd934x-mbhc.h"
45#include "wcd934x-routing.h"
46#include "wcd934x-dsp-cntl.h"
47#include "../wcd9xxx-common-v2.h"
48#include "../wcd9xxx-resmgr-v2.h"
49#include "../wcdcal-hwdep.h"
50#include "wcd934x-dsd.h"
51
52#define WCD934X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
53 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
54 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
55 SNDRV_PCM_RATE_384000)
56/* Fractional Rates */
57#define WCD934X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
58 SNDRV_PCM_RATE_176400)
59
60#define WCD934X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
61 SNDRV_PCM_FMTBIT_S24_LE)
62
63#define WCD934X_FORMATS_S16_S24_S32_LE (SNDRV_PCM_FMTBIT_S16_LE | \
64 SNDRV_PCM_FMTBIT_S24_LE | \
65 SNDRV_PCM_FMTBIT_S32_LE)
66
67#define WCD934X_FORMATS_S16_LE (SNDRV_PCM_FMTBIT_S16_LE)
68
69/* Macros for packing register writes into a U32 */
70#define WCD934X_PACKED_REG_SIZE sizeof(u32)
71#define WCD934X_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
72 do { \
73 ((reg) = ((packed >> 16) & (0xffff))); \
74 ((mask) = ((packed >> 8) & (0xff))); \
75 ((val) = ((packed) & (0xff))); \
76 } while (0)
77
78#define STRING(name) #name
79#define WCD_DAPM_ENUM(name, reg, offset, text) \
80static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
81static const struct snd_kcontrol_new name##_mux = \
82 SOC_DAPM_ENUM(STRING(name), name##_enum)
83
84#define WCD_DAPM_ENUM_EXT(name, reg, offset, text, getname, putname) \
85static SOC_ENUM_SINGLE_DECL(name##_enum, reg, offset, text); \
86static const struct snd_kcontrol_new name##_mux = \
87 SOC_DAPM_ENUM_EXT(STRING(name), name##_enum, getname, putname)
88
89#define WCD_DAPM_MUX(name, shift, kctl) \
90 SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, shift, 0, &kctl##_mux)
91
92/*
93 * Timeout in milli seconds and it is the wait time for
94 * slim channel removal interrupt to receive.
95 */
96#define WCD934X_SLIM_CLOSE_TIMEOUT 1000
97#define WCD934X_SLIM_IRQ_OVERFLOW (1 << 0)
98#define WCD934X_SLIM_IRQ_UNDERFLOW (1 << 1)
99#define WCD934X_SLIM_IRQ_PORT_CLOSED (1 << 2)
100#define WCD934X_MCLK_CLK_12P288MHZ 12288000
101#define WCD934X_MCLK_CLK_9P6MHZ 9600000
102
103#define WCD934X_INTERP_MUX_NUM_INPUTS 3
104#define WCD934X_NUM_INTERPOLATORS 9
105#define WCD934X_NUM_DECIMATORS 9
106#define WCD934X_RX_PATH_CTL_OFFSET 20
107
108#define BYTE_BIT_MASK(nr) (1 << ((nr) % BITS_PER_BYTE))
109
110#define WCD934X_REG_BITS 8
111#define WCD934X_MAX_VALID_ADC_MUX 13
112#define WCD934X_INVALID_ADC_MUX 9
113
114#define WCD934X_AMIC_PWR_LEVEL_LP 0
115#define WCD934X_AMIC_PWR_LEVEL_DEFAULT 1
116#define WCD934X_AMIC_PWR_LEVEL_HP 2
117#define WCD934X_AMIC_PWR_LVL_MASK 0x60
118#define WCD934X_AMIC_PWR_LVL_SHIFT 0x5
119
120#define WCD934X_DEC_PWR_LVL_MASK 0x06
121#define WCD934X_DEC_PWR_LVL_LP 0x02
122#define WCD934X_DEC_PWR_LVL_HP 0x04
123#define WCD934X_DEC_PWR_LVL_DF 0x00
124#define WCD934X_STRING_LEN 100
125
126#define WCD934X_DIG_CORE_REG_MIN WCD934X_CDC_ANC0_CLK_RESET_CTL
127#define WCD934X_DIG_CORE_REG_MAX 0xFFF
128
129#define WCD934X_MAX_MICBIAS 4
130#define DAPM_MICBIAS1_STANDALONE "MIC BIAS1 Standalone"
131#define DAPM_MICBIAS2_STANDALONE "MIC BIAS2 Standalone"
132#define DAPM_MICBIAS3_STANDALONE "MIC BIAS3 Standalone"
133#define DAPM_MICBIAS4_STANDALONE "MIC BIAS4 Standalone"
134
135#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
136#define CF_MIN_3DB_4HZ 0x0
137#define CF_MIN_3DB_75HZ 0x1
138#define CF_MIN_3DB_150HZ 0x2
139
140#define CPE_ERR_WDOG_BITE BIT(0)
141#define CPE_FATAL_IRQS CPE_ERR_WDOG_BITE
142
143#define WCD934X_MAD_AUDIO_FIRMWARE_PATH "wcd934x/wcd934x_mad_audio.bin"
144
145#define TAVIL_VERSION_ENTRY_SIZE 17
146
147#define WCD934X_DIG_CORE_COLLAPSE_TIMER_MS (5 * 1000)
148
149enum {
150 POWER_COLLAPSE,
151 POWER_RESUME,
152};
153
154static int dig_core_collapse_enable = 1;
155module_param(dig_core_collapse_enable, int, 0664);
156MODULE_PARM_DESC(dig_core_collapse_enable, "enable/disable power gating");
157
158/* dig_core_collapse timer in seconds */
159static int dig_core_collapse_timer = (WCD934X_DIG_CORE_COLLAPSE_TIMER_MS/1000);
160module_param(dig_core_collapse_timer, int, 0664);
161MODULE_PARM_DESC(dig_core_collapse_timer, "timer for power gating");
162
163#define TAVIL_HPH_REG_RANGE_1 (WCD934X_HPH_R_DAC_CTL - WCD934X_HPH_CNP_EN + 1)
164#define TAVIL_HPH_REG_RANGE_2 (WCD934X_HPH_NEW_ANA_HPH3 -\
165 WCD934X_HPH_NEW_ANA_HPH2 + 1)
166#define TAVIL_HPH_REG_RANGE_3 (WCD934X_HPH_NEW_INT_PA_RDAC_MISC3 -\
167 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL + 1)
168#define TAVIL_HPH_TOTAL_REG (TAVIL_HPH_REG_RANGE_1 + TAVIL_HPH_REG_RANGE_2 +\
169 TAVIL_HPH_REG_RANGE_3)
170
171enum {
172 VI_SENSE_1,
173 VI_SENSE_2,
174 AUDIO_NOMINAL,
175 HPH_PA_DELAY,
176};
177
178enum {
179 AIF1_PB = 0,
180 AIF1_CAP,
181 AIF2_PB,
182 AIF2_CAP,
183 AIF3_PB,
184 AIF3_CAP,
185 AIF4_PB,
186 AIF4_VIFEED,
187 AIF4_MAD_TX,
188 NUM_CODEC_DAIS,
189};
190
191enum {
192 INTn_1_INP_SEL_ZERO = 0,
193 INTn_1_INP_SEL_DEC0,
194 INTn_1_INP_SEL_DEC1,
195 INTn_1_INP_SEL_IIR0,
196 INTn_1_INP_SEL_IIR1,
197 INTn_1_INP_SEL_RX0,
198 INTn_1_INP_SEL_RX1,
199 INTn_1_INP_SEL_RX2,
200 INTn_1_INP_SEL_RX3,
201 INTn_1_INP_SEL_RX4,
202 INTn_1_INP_SEL_RX5,
203 INTn_1_INP_SEL_RX6,
204 INTn_1_INP_SEL_RX7,
205};
206
207enum {
208 INTn_2_INP_SEL_ZERO = 0,
209 INTn_2_INP_SEL_RX0,
210 INTn_2_INP_SEL_RX1,
211 INTn_2_INP_SEL_RX2,
212 INTn_2_INP_SEL_RX3,
213 INTn_2_INP_SEL_RX4,
214 INTn_2_INP_SEL_RX5,
215 INTn_2_INP_SEL_RX6,
216 INTn_2_INP_SEL_RX7,
217 INTn_2_INP_SEL_PROXIMITY,
218};
219
220enum {
221 INTERP_MAIN_PATH,
222 INTERP_MIX_PATH,
223};
224
225struct tavil_idle_detect_config {
226 u8 hph_idle_thr;
227 u8 hph_idle_detect_en;
228};
229
230static const struct intr_data wcd934x_intr_table[] = {
231 {WCD9XXX_IRQ_SLIMBUS, false},
232 {WCD934X_IRQ_MBHC_SW_DET, true},
233 {WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, true},
234 {WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, true},
235 {WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, true},
236 {WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
237 {WCD934X_IRQ_MISC, false},
238 {WCD934X_IRQ_HPH_PA_CNPL_COMPLETE, false},
239 {WCD934X_IRQ_HPH_PA_CNPR_COMPLETE, false},
240 {WCD934X_IRQ_EAR_PA_CNP_COMPLETE, false},
241 {WCD934X_IRQ_LINE_PA1_CNP_COMPLETE, false},
242 {WCD934X_IRQ_LINE_PA2_CNP_COMPLETE, false},
243 {WCD934X_IRQ_SLNQ_ANALOG_ERROR, false},
244 {WCD934X_IRQ_RESERVED_3, false},
245 {WCD934X_IRQ_HPH_PA_OCPL_FAULT, false},
246 {WCD934X_IRQ_HPH_PA_OCPR_FAULT, false},
247 {WCD934X_IRQ_EAR_PA_OCP_FAULT, false},
248 {WCD934X_IRQ_SOUNDWIRE, false},
249 {WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE, false},
250 {WCD934X_IRQ_RCO_ERROR, false},
251 {WCD934X_IRQ_CPE_ERROR, false},
252 {WCD934X_IRQ_MAD_AUDIO, false},
253 {WCD934X_IRQ_MAD_BEACON, false},
254 {WCD934X_IRQ_CPE1_INTR, true},
255 {WCD934X_IRQ_RESERVED_4, false},
256 {WCD934X_IRQ_MAD_ULTRASOUND, false},
257 {WCD934X_IRQ_VBAT_ATTACK, false},
258 {WCD934X_IRQ_VBAT_RESTORE, false},
259};
260
261struct tavil_cpr_reg_defaults {
262 int wr_data;
263 int wr_addr;
264};
265
266struct interp_sample_rate {
267 int sample_rate;
268 int rate_val;
269};
270
271static struct interp_sample_rate sr_val_tbl[] = {
272 {8000, 0x0}, {16000, 0x1}, {32000, 0x3}, {48000, 0x4}, {96000, 0x5},
273 {192000, 0x6}, {384000, 0x7}, {44100, 0x9}, {88200, 0xA},
274 {176400, 0xB}, {352800, 0xC},
275};
276
277static const struct wcd9xxx_ch tavil_rx_chs[WCD934X_RX_MAX] = {
278 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER, 0),
279 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 1, 1),
280 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 2, 2),
281 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 3, 3),
282 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 4, 4),
283 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 5, 5),
284 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 6, 6),
285 WCD9XXX_CH(WCD934X_RX_PORT_START_NUMBER + 7, 7),
286};
287
288static const struct wcd9xxx_ch tavil_tx_chs[WCD934X_TX_MAX] = {
289 WCD9XXX_CH(0, 0),
290 WCD9XXX_CH(1, 1),
291 WCD9XXX_CH(2, 2),
292 WCD9XXX_CH(3, 3),
293 WCD9XXX_CH(4, 4),
294 WCD9XXX_CH(5, 5),
295 WCD9XXX_CH(6, 6),
296 WCD9XXX_CH(7, 7),
297 WCD9XXX_CH(8, 8),
298 WCD9XXX_CH(9, 9),
299 WCD9XXX_CH(10, 10),
300 WCD9XXX_CH(11, 11),
301 WCD9XXX_CH(12, 12),
302 WCD9XXX_CH(13, 13),
303 WCD9XXX_CH(14, 14),
304 WCD9XXX_CH(15, 15),
305};
306
307static const u32 vport_slim_check_table[NUM_CODEC_DAIS] = {
308 0, /* AIF1_PB */
309 BIT(AIF2_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX), /* AIF1_CAP */
310 0, /* AIF2_PB */
311 BIT(AIF1_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX), /* AIF2_CAP */
312 0, /* AIF3_PB */
313 BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF4_MAD_TX), /* AIF3_CAP */
314 0, /* AIF4_PB */
315};
316
317/* Codec supports 2 IIR filters */
318enum {
319 IIR0 = 0,
320 IIR1,
321 IIR_MAX,
322};
323
324/* Each IIR has 5 Filter Stages */
325enum {
326 BAND1 = 0,
327 BAND2,
328 BAND3,
329 BAND4,
330 BAND5,
331 BAND_MAX,
332};
333
334enum {
335 COMPANDER_1, /* HPH_L */
336 COMPANDER_2, /* HPH_R */
337 COMPANDER_3, /* LO1_DIFF */
338 COMPANDER_4, /* LO2_DIFF */
339 COMPANDER_5, /* LO3_SE - not used in Tavil */
340 COMPANDER_6, /* LO4_SE - not used in Tavil */
341 COMPANDER_7, /* SWR SPK CH1 */
342 COMPANDER_8, /* SWR SPK CH2 */
343 COMPANDER_MAX,
344};
345
346enum {
347 ASRC_IN_HPHL,
348 ASRC_IN_LO1,
349 ASRC_IN_HPHR,
350 ASRC_IN_LO2,
351 ASRC_IN_SPKR1,
352 ASRC_IN_SPKR2,
353 ASRC_INVALID,
354};
355
356enum {
357 ASRC0,
358 ASRC1,
359 ASRC2,
360 ASRC3,
361 ASRC_MAX,
362};
363
364enum {
365 CONV_88P2K_TO_384K,
366 CONV_96K_TO_352P8K,
367 CONV_352P8K_TO_384K,
368 CONV_384K_TO_352P8K,
369 CONV_384K_TO_384K,
370 CONV_96K_TO_384K,
371};
372
373static struct afe_param_slimbus_slave_port_cfg tavil_slimbus_slave_port_cfg = {
374 .minor_version = 1,
375 .slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
376 .slave_dev_pgd_la = 0,
377 .slave_dev_intfdev_la = 0,
378 .bit_width = 16,
379 .data_format = 0,
380 .num_channels = 1
381};
382
383static struct afe_param_cdc_reg_page_cfg tavil_cdc_reg_page_cfg = {
384 .minor_version = AFE_API_VERSION_CDC_REG_PAGE_CFG,
385 .enable = 1,
386 .proc_id = AFE_CDC_REG_PAGE_ASSIGN_PROC_ID_1,
387};
388
389static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
390 {
391 1,
392 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_MAIN_CTL_1),
393 HW_MAD_AUDIO_ENABLE, 0x1, WCD934X_REG_BITS, 0
394 },
395 {
396 1,
397 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_AUDIO_CTL_3),
398 HW_MAD_AUDIO_SLEEP_TIME, 0xF, WCD934X_REG_BITS, 0
399 },
400 {
401 1,
402 (WCD934X_REGISTER_START_OFFSET + WCD934X_SOC_MAD_AUDIO_CTL_4),
403 HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, WCD934X_REG_BITS, 0
404 },
405 {
406 1,
407 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_CFG),
408 MAD_AUDIO_INT_DEST_SELECT_REG, 0x2, WCD934X_REG_BITS, 0
409 },
410 {
411 1,
412 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_MASK3),
413 MAD_AUDIO_INT_MASK_REG, 0x1, WCD934X_REG_BITS, 0
414 },
415 {
416 1,
417 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_STATUS3),
418 MAD_AUDIO_INT_STATUS_REG, 0x1, WCD934X_REG_BITS, 0
419 },
420 {
421 1,
422 (WCD934X_REGISTER_START_OFFSET + WCD934X_INTR_PIN2_CLEAR3),
423 MAD_AUDIO_INT_CLEAR_REG, 0x1, WCD934X_REG_BITS, 0
424 },
425 {
426 1,
427 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_TX_BASE),
428 SB_PGD_PORT_TX_WATERMARK_N, 0x1E, WCD934X_REG_BITS, 0x1
429 },
430 {
431 1,
432 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_TX_BASE),
433 SB_PGD_PORT_TX_ENABLE_N, 0x1, WCD934X_REG_BITS, 0x1
434 },
435 {
436 1,
437 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_RX_BASE),
438 SB_PGD_PORT_RX_WATERMARK_N, 0x1E, WCD934X_REG_BITS, 0x1
439 },
440 {
441 1,
442 (WCD934X_REGISTER_START_OFFSET + WCD934X_SB_PGD_PORT_RX_BASE),
443 SB_PGD_PORT_RX_ENABLE_N, 0x1, WCD934X_REG_BITS, 0x1
444 },
445 {
446 1,
447 (WCD934X_REGISTER_START_OFFSET +
448 WCD934X_CDC_ANC0_IIR_ADAPT_CTL),
449 AANC_FF_GAIN_ADAPTIVE, 0x4, WCD934X_REG_BITS, 0
450 },
451 {
452 1,
453 (WCD934X_REGISTER_START_OFFSET +
454 WCD934X_CDC_ANC0_IIR_ADAPT_CTL),
455 AANC_FFGAIN_ADAPTIVE_EN, 0x8, WCD934X_REG_BITS, 0
456 },
457 {
458 1,
459 (WCD934X_REGISTER_START_OFFSET +
460 WCD934X_CDC_ANC0_FF_A_GAIN_CTL),
461 AANC_GAIN_CONTROL, 0xFF, WCD934X_REG_BITS, 0
462 },
463 {
464 1,
465 (WCD934X_REGISTER_START_OFFSET +
466 SB_PGD_TX_PORT_MULTI_CHANNEL_0(0)),
467 SB_PGD_TX_PORTn_MULTI_CHNL_0, 0xFF, WCD934X_REG_BITS, 0x4
468 },
469 {
470 1,
471 (WCD934X_REGISTER_START_OFFSET +
472 SB_PGD_TX_PORT_MULTI_CHANNEL_1(0)),
473 SB_PGD_TX_PORTn_MULTI_CHNL_1, 0xFF, WCD934X_REG_BITS, 0x4
474 },
475 {
476 1,
477 (WCD934X_REGISTER_START_OFFSET +
478 SB_PGD_RX_PORT_MULTI_CHANNEL_0(0x180, 0)),
479 SB_PGD_RX_PORTn_MULTI_CHNL_0, 0xFF, WCD934X_REG_BITS, 0x4
480 },
481 {
482 1,
483 (WCD934X_REGISTER_START_OFFSET +
484 SB_PGD_RX_PORT_MULTI_CHANNEL_0(0x181, 0)),
485 SB_PGD_RX_PORTn_MULTI_CHNL_1, 0xFF, WCD934X_REG_BITS, 0x4
486 },
487};
488
489static struct afe_param_cdc_reg_cfg_data tavil_audio_reg_cfg = {
490 .num_registers = ARRAY_SIZE(audio_reg_cfg),
491 .reg_data = audio_reg_cfg,
492};
493
494static struct afe_param_id_cdc_aanc_version tavil_cdc_aanc_version = {
495 .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
496 .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
497};
498
499static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
500static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
501static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
502
503#define WCD934X_TX_UNMUTE_DELAY_MS 25
504
505static int tx_unmute_delay = WCD934X_TX_UNMUTE_DELAY_MS;
506module_param(tx_unmute_delay, int, 0664);
507MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path");
508
509
510/* Hold instance to soundwire platform device */
511struct tavil_swr_ctrl_data {
512 struct platform_device *swr_pdev;
513};
514
515struct wcd_swr_ctrl_platform_data {
516 void *handle; /* holds codec private data */
517 int (*read)(void *handle, int reg);
518 int (*write)(void *handle, int reg, int val);
519 int (*bulk_write)(void *handle, u32 *reg, u32 *val, size_t len);
520 int (*clk)(void *handle, bool enable);
521 int (*handle_irq)(void *handle,
522 irqreturn_t (*swrm_irq_handler)(int irq, void *data),
523 void *swrm_handle, int action);
524};
525
526/* Holds all Soundwire and speaker related information */
527struct wcd934x_swr {
528 struct tavil_swr_ctrl_data *ctrl_data;
529 struct wcd_swr_ctrl_platform_data plat_data;
530 struct mutex read_mutex;
531 struct mutex write_mutex;
532 struct mutex clk_mutex;
533 int spkr_gain_offset;
534 int spkr_mode;
535 int clk_users;
536 int rx_7_count;
537 int rx_8_count;
538};
539
540struct tx_mute_work {
541 struct tavil_priv *tavil;
542 u8 decimator;
543 struct delayed_work dwork;
544};
545
546#define WCD934X_SPK_ANC_EN_DELAY_MS 350
547static int spk_anc_en_delay = WCD934X_SPK_ANC_EN_DELAY_MS;
548module_param(spk_anc_en_delay, int, 0664);
549MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path");
550
551struct spk_anc_work {
552 struct tavil_priv *tavil;
553 struct delayed_work dwork;
554};
555
556struct hpf_work {
557 struct tavil_priv *tavil;
558 u8 decimator;
559 u8 hpf_cut_off_freq;
560 struct delayed_work dwork;
561};
562
563struct tavil_priv {
564 struct device *dev;
565 struct wcd9xxx *wcd9xxx;
566 struct snd_soc_codec *codec;
567 u32 rx_bias_count;
568 s32 dmic_0_1_clk_cnt;
569 s32 dmic_2_3_clk_cnt;
570 s32 dmic_4_5_clk_cnt;
571 s32 micb_ref[TAVIL_MAX_MICBIAS];
572 s32 pullup_ref[TAVIL_MAX_MICBIAS];
573
574 /* ANC related */
575 u32 anc_slot;
576 bool anc_func;
577
578 /* compander */
579 int comp_enabled[COMPANDER_MAX];
580 int ear_spkr_gain;
581
582 /* class h specific data */
583 struct wcd_clsh_cdc_data clsh_d;
584 /* Tavil Interpolator Mode Select for EAR, HPH_L and HPH_R */
585 u32 hph_mode;
586
587 /* Mad switch reference count */
588 int mad_switch_cnt;
589
590 /* track tavil interface type */
591 u8 intf_type;
592
593 /* to track the status */
594 unsigned long status_mask;
595
596 struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
597
598 /* num of slim ports required */
599 struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
600 /* Port values for Rx and Tx codec_dai */
601 unsigned int rx_port_value[WCD934X_RX_MAX];
602 unsigned int tx_port_value;
603
604 struct wcd9xxx_resmgr_v2 *resmgr;
605 struct wcd934x_swr swr;
606 struct mutex micb_lock;
607
608 struct delayed_work power_gate_work;
609 struct mutex power_lock;
610
611 struct clk *wcd_ext_clk;
612
613 /* mbhc module */
614 struct wcd934x_mbhc *mbhc;
615
616 struct mutex codec_mutex;
617 struct work_struct tavil_add_child_devices_work;
618 struct hpf_work tx_hpf_work[WCD934X_NUM_DECIMATORS];
619 struct tx_mute_work tx_mute_dwork[WCD934X_NUM_DECIMATORS];
620 struct spk_anc_work spk_anc_dwork;
621
622 unsigned int vi_feed_value;
623
624 /* DSP control */
625 struct wcd_dsp_cntl *wdsp_cntl;
626
627 /* cal info for codec */
628 struct fw_info *fw_data;
629
630 /* Entry for version info */
631 struct snd_info_entry *entry;
632 struct snd_info_entry *version_entry;
633
634 /* SVS voting related */
635 struct mutex svs_mutex;
636 int svs_ref_cnt;
637
638 int native_clk_users;
639 /* ASRC users count */
640 int asrc_users[ASRC_MAX];
641 int asrc_output_mode[ASRC_MAX];
642 /* Main path clock users count */
643 int main_clk_users[WCD934X_NUM_INTERPOLATORS];
644 struct tavil_dsd_config *dsd_config;
645 struct tavil_idle_detect_config idle_det_cfg;
646
647 int power_active_ref;
648};
649
650static const struct tavil_reg_mask_val tavil_spkr_default[] = {
651 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
652 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
653 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
654 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
655 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x7C, 0x50},
656 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x7C, 0x50},
657};
658
659static const struct tavil_reg_mask_val tavil_spkr_mode1[] = {
660 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x00},
661 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x00},
662 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x00},
663 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x00},
664 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x7C, 0x44},
665 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x7C, 0x44},
666};
667
668static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil);
669
670/*
671 * wcd934x_get_codec_info: Get codec specific information
672 *
673 * @wcd9xxx: pointer to wcd9xxx structure
674 * @wcd_type: pointer to wcd9xxx_codec_type structure
675 *
676 * Returns 0 for success or negative error code for failure
677 */
678int wcd934x_get_codec_info(struct wcd9xxx *wcd9xxx,
679 struct wcd9xxx_codec_type *wcd_type)
680{
681 u16 id_minor, id_major;
682 struct regmap *wcd_regmap;
683 int rc, version = -1;
684
685 if (!wcd9xxx || !wcd_type)
686 return -EINVAL;
687
688 if (!wcd9xxx->regmap) {
689 dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
690 return -EINVAL;
691 }
692 wcd_regmap = wcd9xxx->regmap;
693
694 rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
695 (u8 *)&id_minor, sizeof(u16));
696 if (rc)
697 return -EINVAL;
698
699 rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
700 (u8 *)&id_major, sizeof(u16));
701 if (rc)
702 return -EINVAL;
703
704 dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
705 __func__, id_major, id_minor);
706
707 if (id_major != TAVIL_MAJOR)
708 goto version_unknown;
709
710 /*
711 * As fine version info cannot be retrieved before tavil probe.
712 * Assign coarse versions for possible future use before tavil probe.
713 */
714 if (id_minor == cpu_to_le16(0))
715 version = TAVIL_VERSION_1_0;
716 else if (id_minor == cpu_to_le16(0x01))
717 version = TAVIL_VERSION_1_1;
718
719version_unknown:
720 if (version < 0)
721 dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
722 __func__);
723
724 /* Fill codec type info */
725 wcd_type->id_major = id_major;
726 wcd_type->id_minor = id_minor;
727 wcd_type->num_irqs = WCD934X_NUM_IRQS;
728 wcd_type->version = version;
729 wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
730 wcd_type->i2c_chip_status = 0x01;
731 wcd_type->intr_tbl = wcd934x_intr_table;
732 wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
733
734 wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
735 WCD934X_INTR_PIN1_STATUS0;
736 wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
737 WCD934X_INTR_PIN1_CLEAR0;
738 wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
739 WCD934X_INTR_PIN1_MASK0;
740 wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
741 WCD934X_INTR_LEVEL0;
742 wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
743 WCD934X_INTR_CLR_COMMIT;
744
745 return rc;
746}
747EXPORT_SYMBOL(wcd934x_get_codec_info);
748
749/*
750 * wcd934x_bringdown: Bringdown WCD Codec
751 *
752 * @wcd9xxx: Pointer to wcd9xxx structure
753 *
754 * Returns 0 for success or negative error code for failure
755 */
756int wcd934x_bringdown(struct wcd9xxx *wcd9xxx)
757{
758 if (!wcd9xxx || !wcd9xxx->regmap)
759 return -EINVAL;
760
761 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
762 0x04);
763
764 return 0;
765}
766EXPORT_SYMBOL(wcd934x_bringdown);
767
768/*
769 * wcd934x_bringup: Bringup WCD Codec
770 *
771 * @wcd9xxx: Pointer to the wcd9xxx structure
772 *
773 * Returns 0 for success or negative error code for failure
774 */
775int wcd934x_bringup(struct wcd9xxx *wcd9xxx)
776{
777 struct regmap *wcd_regmap;
778
779 if (!wcd9xxx)
780 return -EINVAL;
781
782 if (!wcd9xxx->regmap) {
783 dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
784 __func__);
785 return -EINVAL;
786 }
787 wcd_regmap = wcd9xxx->regmap;
788
789 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01);
790 regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19);
791 regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15);
792 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
793 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
794 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
795 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3);
796 regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7);
797
798 return 0;
799}
800EXPORT_SYMBOL(wcd934x_bringup);
801
802/**
803 * tavil_set_spkr_gain_offset - offset the speaker path
804 * gain with the given offset value.
805 *
806 * @codec: codec instance
807 * @offset: Indicates speaker path gain offset value.
808 *
809 * Returns 0 on success or -EINVAL on error.
810 */
811int tavil_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset)
812{
813 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
814
815 if (!priv)
816 return -EINVAL;
817
818 priv->swr.spkr_gain_offset = offset;
819 return 0;
820}
821EXPORT_SYMBOL(tavil_set_spkr_gain_offset);
822
823/**
824 * tavil_set_spkr_mode - Configures speaker compander and smartboost
825 * settings based on speaker mode.
826 *
827 * @codec: codec instance
828 * @mode: Indicates speaker configuration mode.
829 *
830 * Returns 0 on success or -EINVAL on error.
831 */
832int tavil_set_spkr_mode(struct snd_soc_codec *codec, int mode)
833{
834 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
835 int i;
836 const struct tavil_reg_mask_val *regs;
837 int size;
838
839 if (!priv)
840 return -EINVAL;
841
842 switch (mode) {
843 case WCD934X_SPKR_MODE_1:
844 regs = tavil_spkr_mode1;
845 size = ARRAY_SIZE(tavil_spkr_mode1);
846 break;
847 default:
848 regs = tavil_spkr_default;
849 size = ARRAY_SIZE(tavil_spkr_default);
850 break;
851 }
852
853 priv->swr.spkr_mode = mode;
854 for (i = 0; i < size; i++)
855 snd_soc_update_bits(codec, regs[i].reg,
856 regs[i].mask, regs[i].val);
857 return 0;
858}
859EXPORT_SYMBOL(tavil_set_spkr_mode);
860
861/**
862 * tavil_get_afe_config - returns specific codec configuration to afe to write
863 *
864 * @codec: codec instance
865 * @config_type: Indicates type of configuration to write.
866 */
867void *tavil_get_afe_config(struct snd_soc_codec *codec,
868 enum afe_config_type config_type)
869{
870 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
871
872 switch (config_type) {
873 case AFE_SLIMBUS_SLAVE_CONFIG:
874 return &priv->slimbus_slave_cfg;
875 case AFE_CDC_REGISTERS_CONFIG:
876 return &tavil_audio_reg_cfg;
877 case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
878 return &tavil_slimbus_slave_port_cfg;
879 case AFE_AANC_VERSION:
880 return &tavil_cdc_aanc_version;
881 case AFE_CDC_REGISTER_PAGE_CONFIG:
882 return &tavil_cdc_reg_page_cfg;
883 default:
884 dev_info(codec->dev, "%s: Unknown config_type 0x%x\n",
885 __func__, config_type);
886 return NULL;
887 }
888}
889EXPORT_SYMBOL(tavil_get_afe_config);
890
891static bool is_tavil_playback_dai(int dai_id)
892{
893 if ((dai_id == AIF1_PB) || (dai_id == AIF2_PB) ||
894 (dai_id == AIF3_PB) || (dai_id == AIF4_PB))
895 return true;
896
897 return false;
898}
899
900static int tavil_find_playback_dai_id_for_port(int port_id,
901 struct tavil_priv *tavil)
902{
903 struct wcd9xxx_codec_dai_data *dai;
904 struct wcd9xxx_ch *ch;
905 int i, slv_port_id;
906
907 for (i = AIF1_PB; i < NUM_CODEC_DAIS; i++) {
908 if (!is_tavil_playback_dai(i))
909 continue;
910
911 dai = &tavil->dai[i];
912 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
913 slv_port_id = wcd9xxx_get_slave_port(ch->ch_num);
914 if ((slv_port_id > 0) && (slv_port_id == port_id))
915 return i;
916 }
917 }
918
919 return -EINVAL;
920}
921
922static void tavil_vote_svs(struct tavil_priv *tavil, bool vote)
923{
924 struct wcd9xxx *wcd9xxx;
925
926 wcd9xxx = tavil->wcd9xxx;
927
928 mutex_lock(&tavil->svs_mutex);
929 if (vote) {
930 tavil->svs_ref_cnt++;
931 if (tavil->svs_ref_cnt == 1)
932 regmap_update_bits(wcd9xxx->regmap,
933 WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
934 0x01, 0x01);
935 } else {
936 /* Do not decrement ref count if it is already 0 */
937 if (tavil->svs_ref_cnt == 0)
938 goto done;
939
940 tavil->svs_ref_cnt--;
941 if (tavil->svs_ref_cnt == 0)
942 regmap_update_bits(wcd9xxx->regmap,
943 WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
944 0x01, 0x00);
945 }
946done:
947 dev_dbg(tavil->dev, "%s: vote = %s, updated ref cnt = %u\n", __func__,
948 vote ? "vote" : "Unvote", tavil->svs_ref_cnt);
949 mutex_unlock(&tavil->svs_mutex);
950}
951
952static int tavil_get_anc_slot(struct snd_kcontrol *kcontrol,
953 struct snd_ctl_elem_value *ucontrol)
954{
955 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
956 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
957
958 ucontrol->value.integer.value[0] = tavil->anc_slot;
959 return 0;
960}
961
962static int tavil_put_anc_slot(struct snd_kcontrol *kcontrol,
963 struct snd_ctl_elem_value *ucontrol)
964{
965 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
966 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
967
968 tavil->anc_slot = ucontrol->value.integer.value[0];
969 return 0;
970}
971
972static int tavil_get_anc_func(struct snd_kcontrol *kcontrol,
973 struct snd_ctl_elem_value *ucontrol)
974{
975 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
976 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
977
978 ucontrol->value.integer.value[0] = (tavil->anc_func == true ? 1 : 0);
979 return 0;
980}
981
982static int tavil_put_anc_func(struct snd_kcontrol *kcontrol,
983 struct snd_ctl_elem_value *ucontrol)
984{
985 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
986 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
987 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
988
989 mutex_lock(&tavil->codec_mutex);
990 tavil->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
991 dev_dbg(codec->dev, "%s: anc_func %x", __func__, tavil->anc_func);
992
993 if (tavil->anc_func == true) {
994 snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
995 snd_soc_dapm_enable_pin(dapm, "ANC EAR");
996 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
997 snd_soc_dapm_disable_pin(dapm, "EAR PA");
998 snd_soc_dapm_disable_pin(dapm, "EAR");
999 } else {
1000 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
1001 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
1002 snd_soc_dapm_disable_pin(dapm, "ANC SPK1 PA");
1003 snd_soc_dapm_enable_pin(dapm, "EAR PA");
1004 snd_soc_dapm_enable_pin(dapm, "EAR");
1005 }
1006 mutex_unlock(&tavil->codec_mutex);
1007
1008 snd_soc_dapm_sync(dapm);
1009 return 0;
1010}
1011
1012static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w,
1013 struct snd_kcontrol *kcontrol, int event)
1014{
1015 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1016 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1017 const char *filename;
1018 const struct firmware *fw;
1019 int i;
1020 int ret = 0;
1021 int num_anc_slots;
1022 struct wcd9xxx_anc_header *anc_head;
1023 struct firmware_cal *hwdep_cal = NULL;
1024 u32 anc_writes_size = 0;
1025 u32 anc_cal_size = 0;
1026 int anc_size_remaining;
1027 u32 *anc_ptr;
1028 u16 reg;
1029 u8 mask, val;
1030 size_t cal_size;
1031 const void *data;
1032
1033 if (!tavil->anc_func)
1034 return 0;
1035
1036 switch (event) {
1037 case SND_SOC_DAPM_PRE_PMU:
1038 hwdep_cal = wcdcal_get_fw_cal(tavil->fw_data, WCD9XXX_ANC_CAL);
1039 if (hwdep_cal) {
1040 data = hwdep_cal->data;
1041 cal_size = hwdep_cal->size;
1042 dev_dbg(codec->dev, "%s: using hwdep calibration, cal_size %zd",
1043 __func__, cal_size);
1044 } else {
1045 filename = "WCD934X/WCD934X_anc.bin";
1046 ret = request_firmware(&fw, filename, codec->dev);
1047 if (IS_ERR_VALUE(ret)) {
1048 dev_err(codec->dev, "%s: Failed to acquire ANC data: %d\n",
1049 __func__, ret);
1050 return ret;
1051 }
1052 if (!fw) {
1053 dev_err(codec->dev, "%s: Failed to get anc fw\n",
1054 __func__);
1055 return -ENODEV;
1056 }
1057 data = fw->data;
1058 cal_size = fw->size;
1059 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
1060 __func__);
1061 }
1062 if (cal_size < sizeof(struct wcd9xxx_anc_header)) {
1063 dev_err(codec->dev, "%s: Invalid cal_size %zd\n",
1064 __func__, cal_size);
1065 ret = -EINVAL;
1066 goto err;
1067 }
1068 /* First number is the number of register writes */
1069 anc_head = (struct wcd9xxx_anc_header *)(data);
1070 anc_ptr = (u32 *)(data + sizeof(struct wcd9xxx_anc_header));
1071 anc_size_remaining = cal_size -
1072 sizeof(struct wcd9xxx_anc_header);
1073 num_anc_slots = anc_head->num_anc_slots;
1074
1075 if (tavil->anc_slot >= num_anc_slots) {
1076 dev_err(codec->dev, "%s: Invalid ANC slot selected\n",
1077 __func__);
1078 ret = -EINVAL;
1079 goto err;
1080 }
1081 for (i = 0; i < num_anc_slots; i++) {
1082 if (anc_size_remaining < WCD934X_PACKED_REG_SIZE) {
1083 dev_err(codec->dev, "%s: Invalid register format\n",
1084 __func__);
1085 ret = -EINVAL;
1086 goto err;
1087 }
1088 anc_writes_size = (u32)(*anc_ptr);
1089 anc_size_remaining -= sizeof(u32);
1090 anc_ptr += 1;
1091
1092 if ((anc_writes_size * WCD934X_PACKED_REG_SIZE) >
1093 anc_size_remaining) {
1094 dev_err(codec->dev, "%s: Invalid register format\n",
1095 __func__);
1096 ret = -EINVAL;
1097 goto err;
1098 }
1099
1100 if (tavil->anc_slot == i)
1101 break;
1102
1103 anc_size_remaining -= (anc_writes_size *
1104 WCD934X_PACKED_REG_SIZE);
1105 anc_ptr += anc_writes_size;
1106 }
1107 if (i == num_anc_slots) {
1108 dev_err(codec->dev, "%s: Selected ANC slot not present\n",
1109 __func__);
1110 ret = -EINVAL;
1111 goto err;
1112 }
1113
1114 anc_cal_size = anc_writes_size;
1115 for (i = 0; i < anc_writes_size; i++) {
1116 WCD934X_CODEC_UNPACK_ENTRY(anc_ptr[i], reg, mask, val);
1117 snd_soc_write(codec, reg, (val & mask));
1118 }
1119
1120 /* Rate converter clk enable and set bypass mode */
1121 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL,
1122 0x05, 0x05);
1123 if (!hwdep_cal)
1124 release_firmware(fw);
1125 break;
1126 case SND_SOC_DAPM_POST_PMD:
1127 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL,
1128 0x05, 0x00);
1129 if (!strcmp(w->name, "ANC EAR PA") ||
1130 !strcmp(w->name, "ANC SPK1 PA")) {
1131 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL,
1132 0x30, 0x00);
1133 msleep(50);
1134 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL,
1135 0x01, 0x00);
1136 snd_soc_update_bits(codec,
1137 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1138 0x38, 0x38);
1139 snd_soc_update_bits(codec,
1140 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1141 0x07, 0x00);
1142 snd_soc_update_bits(codec,
1143 WCD934X_CDC_ANC0_CLK_RESET_CTL,
1144 0x38, 0x00);
1145 }
1146 break;
1147 }
1148
1149 return 0;
1150err:
1151 if (!hwdep_cal)
1152 release_firmware(fw);
1153 return ret;
1154}
1155
1156static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
1157 struct snd_ctl_elem_value *ucontrol)
1158{
1159 struct snd_soc_dapm_widget_list *wlist =
1160 dapm_kcontrol_get_wlist(kcontrol);
1161 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1162 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1163 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1164
1165 ucontrol->value.integer.value[0] = tavil_p->vi_feed_value;
1166
1167 return 0;
1168}
1169
1170static int tavil_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
1171 struct snd_ctl_elem_value *ucontrol)
1172{
1173 struct snd_soc_dapm_widget_list *wlist =
1174 dapm_kcontrol_get_wlist(kcontrol);
1175 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1176 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1177 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1178 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1179 struct soc_multi_mixer_control *mixer =
1180 ((struct soc_multi_mixer_control *)kcontrol->private_value);
1181 u32 dai_id = widget->shift;
1182 u32 port_id = mixer->shift;
1183 u32 enable = ucontrol->value.integer.value[0];
1184
1185 dev_dbg(codec->dev, "%s: enable: %d, port_id:%d, dai_id: %d\n",
1186 __func__, enable, port_id, dai_id);
1187
1188 tavil_p->vi_feed_value = ucontrol->value.integer.value[0];
1189
1190 mutex_lock(&tavil_p->codec_mutex);
1191 if (enable) {
1192 if (port_id == WCD934X_TX14 && !test_bit(VI_SENSE_1,
1193 &tavil_p->status_mask)) {
1194 list_add_tail(&core->tx_chs[WCD934X_TX14].list,
1195 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1196 set_bit(VI_SENSE_1, &tavil_p->status_mask);
1197 }
1198 if (port_id == WCD934X_TX15 && !test_bit(VI_SENSE_2,
1199 &tavil_p->status_mask)) {
1200 list_add_tail(&core->tx_chs[WCD934X_TX15].list,
1201 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1202 set_bit(VI_SENSE_2, &tavil_p->status_mask);
1203 }
1204 } else {
1205 if (port_id == WCD934X_TX14 && test_bit(VI_SENSE_1,
1206 &tavil_p->status_mask)) {
1207 list_del_init(&core->tx_chs[WCD934X_TX14].list);
1208 clear_bit(VI_SENSE_1, &tavil_p->status_mask);
1209 }
1210 if (port_id == WCD934X_TX15 && test_bit(VI_SENSE_2,
1211 &tavil_p->status_mask)) {
1212 list_del_init(&core->tx_chs[WCD934X_TX15].list);
1213 clear_bit(VI_SENSE_2, &tavil_p->status_mask);
1214 }
1215 }
1216 mutex_unlock(&tavil_p->codec_mutex);
1217 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
1218
1219 return 0;
1220}
1221
1222static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
1223 struct snd_ctl_elem_value *ucontrol)
1224{
1225 struct snd_soc_dapm_widget_list *wlist =
1226 dapm_kcontrol_get_wlist(kcontrol);
1227 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1228 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1229 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1230
1231 ucontrol->value.integer.value[0] = tavil_p->tx_port_value;
1232 return 0;
1233}
1234
1235static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
1236 struct snd_ctl_elem_value *ucontrol)
1237{
1238 struct snd_soc_dapm_widget_list *wlist =
1239 dapm_kcontrol_get_wlist(kcontrol);
1240 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1241 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1242 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1243 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1244 struct snd_soc_dapm_update *update = NULL;
1245 struct soc_multi_mixer_control *mixer =
1246 ((struct soc_multi_mixer_control *)kcontrol->private_value);
1247 u32 dai_id = widget->shift;
1248 u32 port_id = mixer->shift;
1249 u32 enable = ucontrol->value.integer.value[0];
1250 u32 vtable;
1251
1252 dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
1253 __func__,
1254 widget->name, ucontrol->id.name, tavil_p->tx_port_value,
1255 widget->shift, ucontrol->value.integer.value[0]);
1256
1257 mutex_lock(&tavil_p->codec_mutex);
1258 if (dai_id >= ARRAY_SIZE(vport_slim_check_table)) {
1259 dev_err(codec->dev, "%s: dai_id: %d, out of bounds\n",
1260 __func__, dai_id);
1261 mutex_unlock(&tavil_p->codec_mutex);
1262 return -EINVAL;
1263 }
1264 vtable = vport_slim_check_table[dai_id];
1265
1266 switch (dai_id) {
1267 case AIF1_CAP:
1268 case AIF2_CAP:
1269 case AIF3_CAP:
1270 /* only add to the list if value not set */
1271 if (enable && !(tavil_p->tx_port_value & 1 << port_id)) {
1272 if (wcd9xxx_tx_vport_validation(vtable, port_id,
1273 tavil_p->dai, NUM_CODEC_DAIS)) {
1274 dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
1275 __func__, port_id);
1276 mutex_unlock(&tavil_p->codec_mutex);
1277 return 0;
1278 }
1279 tavil_p->tx_port_value |= 1 << port_id;
1280 list_add_tail(&core->tx_chs[port_id].list,
1281 &tavil_p->dai[dai_id].wcd9xxx_ch_list);
1282 } else if (!enable && (tavil_p->tx_port_value &
1283 1 << port_id)) {
1284 tavil_p->tx_port_value &= ~(1 << port_id);
1285 list_del_init(&core->tx_chs[port_id].list);
1286 } else {
1287 if (enable)
1288 dev_dbg(codec->dev, "%s: TX%u port is used by\n"
1289 "this virtual port\n",
1290 __func__, port_id);
1291 else
1292 dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
1293 "this virtual port\n",
1294 __func__, port_id);
1295 /* avoid update power function */
1296 mutex_unlock(&tavil_p->codec_mutex);
1297 return 0;
1298 }
1299 break;
1300 case AIF4_MAD_TX:
1301 break;
1302 default:
1303 dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
1304 mutex_unlock(&tavil_p->codec_mutex);
1305 return -EINVAL;
1306 }
1307 dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
1308 __func__, widget->name, widget->sname, tavil_p->tx_port_value,
1309 widget->shift);
1310
1311 mutex_unlock(&tavil_p->codec_mutex);
1312 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update);
1313
1314 return 0;
1315}
1316
1317static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
1318 struct snd_ctl_elem_value *ucontrol)
1319{
1320 struct snd_soc_dapm_widget_list *wlist =
1321 dapm_kcontrol_get_wlist(kcontrol);
1322 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1323 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1324 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1325
1326 ucontrol->value.enumerated.item[0] =
1327 tavil_p->rx_port_value[widget->shift];
1328 return 0;
1329}
1330
1331static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
1332 struct snd_ctl_elem_value *ucontrol)
1333{
1334 struct snd_soc_dapm_widget_list *wlist =
1335 dapm_kcontrol_get_wlist(kcontrol);
1336 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1337 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
1338 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1339 struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
1340 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1341 struct snd_soc_dapm_update *update = NULL;
1342 unsigned int rx_port_value;
1343 u32 port_id = widget->shift;
1344
1345 tavil_p->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
1346 rx_port_value = tavil_p->rx_port_value[port_id];
1347
1348 mutex_lock(&tavil_p->codec_mutex);
1349 dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
1350 __func__, widget->name, ucontrol->id.name,
1351 rx_port_value, widget->shift,
1352 ucontrol->value.integer.value[0]);
1353
1354 /* value need to match the Virtual port and AIF number */
1355 switch (rx_port_value) {
1356 case 0:
1357 list_del_init(&core->rx_chs[port_id].list);
1358 break;
1359 case 1:
1360 if (wcd9xxx_rx_vport_validation(port_id +
1361 WCD934X_RX_PORT_START_NUMBER,
1362 &tavil_p->dai[AIF1_PB].wcd9xxx_ch_list)) {
1363 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1364 __func__, port_id);
1365 goto rtn;
1366 }
1367 list_add_tail(&core->rx_chs[port_id].list,
1368 &tavil_p->dai[AIF1_PB].wcd9xxx_ch_list);
1369 break;
1370 case 2:
1371 if (wcd9xxx_rx_vport_validation(port_id +
1372 WCD934X_RX_PORT_START_NUMBER,
1373 &tavil_p->dai[AIF2_PB].wcd9xxx_ch_list)) {
1374 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1375 __func__, port_id);
1376 goto rtn;
1377 }
1378 list_add_tail(&core->rx_chs[port_id].list,
1379 &tavil_p->dai[AIF2_PB].wcd9xxx_ch_list);
1380 break;
1381 case 3:
1382 if (wcd9xxx_rx_vport_validation(port_id +
1383 WCD934X_RX_PORT_START_NUMBER,
1384 &tavil_p->dai[AIF3_PB].wcd9xxx_ch_list)) {
1385 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1386 __func__, port_id);
1387 goto rtn;
1388 }
1389 list_add_tail(&core->rx_chs[port_id].list,
1390 &tavil_p->dai[AIF3_PB].wcd9xxx_ch_list);
1391 break;
1392 case 4:
1393 if (wcd9xxx_rx_vport_validation(port_id +
1394 WCD934X_RX_PORT_START_NUMBER,
1395 &tavil_p->dai[AIF4_PB].wcd9xxx_ch_list)) {
1396 dev_dbg(codec->dev, "%s: RX%u is used by current requesting AIF_PB itself\n",
1397 __func__, port_id);
1398 goto rtn;
1399 }
1400 list_add_tail(&core->rx_chs[port_id].list,
1401 &tavil_p->dai[AIF4_PB].wcd9xxx_ch_list);
1402 break;
1403 default:
1404 dev_err(codec->dev, "Unknown AIF %d\n", rx_port_value);
1405 goto err;
1406 }
1407rtn:
1408 mutex_unlock(&tavil_p->codec_mutex);
1409 snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
1410 rx_port_value, e, update);
1411
1412 return 0;
1413err:
1414 mutex_unlock(&tavil_p->codec_mutex);
1415 return -EINVAL;
1416}
1417
1418static void tavil_codec_enable_slim_port_intr(
1419 struct wcd9xxx_codec_dai_data *dai,
1420 struct snd_soc_codec *codec)
1421{
1422 struct wcd9xxx_ch *ch;
1423 int port_num = 0;
1424 unsigned short reg = 0;
1425 u8 val = 0;
1426 struct tavil_priv *tavil_p;
1427
1428 if (!dai || !codec) {
1429 pr_err("%s: Invalid params\n", __func__);
1430 return;
1431 }
1432
1433 tavil_p = snd_soc_codec_get_drvdata(codec);
1434 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
1435 if (ch->port >= WCD934X_RX_PORT_START_NUMBER) {
1436 port_num = ch->port - WCD934X_RX_PORT_START_NUMBER;
1437 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + (port_num / 8);
1438 val = wcd9xxx_interface_reg_read(tavil_p->wcd9xxx,
1439 reg);
1440 if (!(val & BYTE_BIT_MASK(port_num))) {
1441 val |= BYTE_BIT_MASK(port_num);
1442 wcd9xxx_interface_reg_write(
1443 tavil_p->wcd9xxx, reg, val);
1444 val = wcd9xxx_interface_reg_read(
1445 tavil_p->wcd9xxx, reg);
1446 }
1447 } else {
1448 port_num = ch->port;
1449 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
1450 val = wcd9xxx_interface_reg_read(tavil_p->wcd9xxx,
1451 reg);
1452 if (!(val & BYTE_BIT_MASK(port_num))) {
1453 val |= BYTE_BIT_MASK(port_num);
1454 wcd9xxx_interface_reg_write(tavil_p->wcd9xxx,
1455 reg, val);
1456 val = wcd9xxx_interface_reg_read(
1457 tavil_p->wcd9xxx, reg);
1458 }
1459 }
1460 }
1461}
1462
1463static int tavil_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
1464 bool up)
1465{
1466 int ret = 0;
1467 struct wcd9xxx_ch *ch;
1468
1469 if (up) {
1470 list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
1471 ret = wcd9xxx_get_slave_port(ch->ch_num);
1472 if (ret < 0) {
1473 pr_err("%s: Invalid slave port ID: %d\n",
1474 __func__, ret);
1475 ret = -EINVAL;
1476 } else {
1477 set_bit(ret, &dai->ch_mask);
1478 }
1479 }
1480 } else {
1481 ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
1482 msecs_to_jiffies(
1483 WCD934X_SLIM_CLOSE_TIMEOUT));
1484 if (!ret) {
1485 pr_err("%s: Slim close tx/rx wait timeout, ch_mask:0x%lx\n",
1486 __func__, dai->ch_mask);
1487 ret = -ETIMEDOUT;
1488 } else {
1489 ret = 0;
1490 }
1491 }
1492 return ret;
1493}
1494
1495static void tavil_codec_mute_dsd(struct snd_soc_codec *codec,
1496 struct list_head *ch_list)
1497{
1498 u8 dsd0_in;
1499 u8 dsd1_in;
1500 struct wcd9xxx_ch *ch;
1501
1502 /* Read DSD Input Ports */
1503 dsd0_in = (snd_soc_read(codec, WCD934X_CDC_DSD0_CFG0) & 0x3C) >> 2;
1504 dsd1_in = (snd_soc_read(codec, WCD934X_CDC_DSD1_CFG0) & 0x3C) >> 2;
1505
1506 if ((dsd0_in == 0) && (dsd1_in == 0))
1507 return;
1508
1509 /*
1510 * Check if the ports getting disabled are connected to DSD inputs.
1511 * If connected, enable DSD mute to avoid DC entering into DSD Filter
1512 */
1513 list_for_each_entry(ch, ch_list, list) {
1514 if (ch->port == (dsd0_in + WCD934X_RX_PORT_START_NUMBER - 1))
1515 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
1516 0x04, 0x04);
1517 if (ch->port == (dsd1_in + WCD934X_RX_PORT_START_NUMBER - 1))
1518 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
1519 0x04, 0x04);
1520 }
1521}
1522
1523static int tavil_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
1524 struct snd_kcontrol *kcontrol,
1525 int event)
1526{
1527 struct wcd9xxx *core;
1528 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1529 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1530 int ret = 0;
1531 struct wcd9xxx_codec_dai_data *dai;
1532 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
1533
1534 core = dev_get_drvdata(codec->dev->parent);
1535
1536 dev_dbg(codec->dev, "%s: event called! codec name %s num_dai %d\n"
1537 "stream name %s event %d\n",
1538 __func__, codec->component.name,
1539 codec->component.num_dai, w->sname, event);
1540
1541 dai = &tavil_p->dai[w->shift];
1542 dev_dbg(codec->dev, "%s: w->name %s w->shift %d event %d\n",
1543 __func__, w->name, w->shift, event);
1544
1545 switch (event) {
1546 case SND_SOC_DAPM_POST_PMU:
1547 dai->bus_down_in_recovery = false;
1548 tavil_codec_enable_slim_port_intr(dai, codec);
1549 (void) tavil_codec_enable_slim_chmask(dai, true);
1550 ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
1551 dai->rate, dai->bit_width,
1552 &dai->grph);
1553 break;
1554 case SND_SOC_DAPM_POST_PMD:
1555 if (dsd_conf)
1556 tavil_codec_mute_dsd(codec, &dai->wcd9xxx_ch_list);
1557
1558 ret = wcd9xxx_disconnect_port(core, &dai->wcd9xxx_ch_list,
1559 dai->grph);
1560 dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
1561 __func__, ret);
1562
1563 if (!dai->bus_down_in_recovery)
1564 ret = tavil_codec_enable_slim_chmask(dai, false);
1565 else
1566 dev_dbg(codec->dev,
1567 "%s: bus in recovery skip enable slim_chmask",
1568 __func__);
1569 ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
1570 dai->grph);
1571 break;
1572 }
1573 return ret;
1574}
1575
1576static int tavil_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
1577 struct snd_kcontrol *kcontrol,
1578 int event)
1579{
1580 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1581 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
1582 struct wcd9xxx_codec_dai_data *dai;
1583 struct wcd9xxx *core;
1584 int ret = 0;
1585
1586 dev_dbg(codec->dev,
1587 "%s: w->name %s, w->shift = %d, num_dai %d stream name %s\n",
1588 __func__, w->name, w->shift,
1589 codec->component.num_dai, w->sname);
1590
1591 dai = &tavil_p->dai[w->shift];
1592 core = dev_get_drvdata(codec->dev->parent);
1593
1594 switch (event) {
1595 case SND_SOC_DAPM_POST_PMU:
1596 dai->bus_down_in_recovery = false;
1597 tavil_codec_enable_slim_port_intr(dai, codec);
1598 (void) tavil_codec_enable_slim_chmask(dai, true);
1599 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1600 dai->rate, dai->bit_width,
1601 &dai->grph);
1602 break;
1603 case SND_SOC_DAPM_POST_PMD:
1604 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1605 dai->grph);
1606 if (!dai->bus_down_in_recovery)
1607 ret = tavil_codec_enable_slim_chmask(dai, false);
1608 if (ret < 0) {
1609 ret = wcd9xxx_disconnect_port(core,
1610 &dai->wcd9xxx_ch_list,
1611 dai->grph);
1612 dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
1613 __func__, ret);
1614 }
1615 break;
1616 }
1617 return ret;
1618}
1619
1620static int tavil_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
1621 struct snd_kcontrol *kcontrol,
1622 int event)
1623{
1624 struct wcd9xxx *core = NULL;
1625 struct snd_soc_codec *codec = NULL;
1626 struct tavil_priv *tavil_p = NULL;
1627 int ret = 0;
1628 struct wcd9xxx_codec_dai_data *dai = NULL;
1629
1630 codec = snd_soc_dapm_to_codec(w->dapm);
1631 tavil_p = snd_soc_codec_get_drvdata(codec);
1632 core = dev_get_drvdata(codec->dev->parent);
1633
1634 dev_dbg(codec->dev,
1635 "%s: num_dai %d stream name %s w->name %s event %d shift %d\n",
1636 __func__, codec->component.num_dai, w->sname,
1637 w->name, event, w->shift);
1638
1639 if (w->shift != AIF4_VIFEED) {
1640 pr_err("%s Error in enabling the tx path\n", __func__);
1641 ret = -EINVAL;
1642 goto done;
1643 }
1644 dai = &tavil_p->dai[w->shift];
1645 switch (event) {
1646 case SND_SOC_DAPM_POST_PMU:
1647 if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
1648 dev_dbg(codec->dev, "%s: spkr1 enabled\n", __func__);
1649 /* Enable V&I sensing */
1650 snd_soc_update_bits(codec,
1651 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
1652 snd_soc_update_bits(codec,
1653 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1654 0x20);
1655 snd_soc_update_bits(codec,
1656 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x00);
1657 snd_soc_update_bits(codec,
1658 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x0F,
1659 0x00);
1660 snd_soc_update_bits(codec,
1661 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x10);
1662 snd_soc_update_bits(codec,
1663 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
1664 0x10);
1665 snd_soc_update_bits(codec,
1666 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x00);
1667 snd_soc_update_bits(codec,
1668 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1669 0x00);
1670 }
1671 if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
1672 pr_debug("%s: spkr2 enabled\n", __func__);
1673 /* Enable V&I sensing */
1674 snd_soc_update_bits(codec,
1675 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1676 0x20);
1677 snd_soc_update_bits(codec,
1678 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1679 0x20);
1680 snd_soc_update_bits(codec,
1681 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x0F,
1682 0x00);
1683 snd_soc_update_bits(codec,
1684 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x0F,
1685 0x00);
1686 snd_soc_update_bits(codec,
1687 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
1688 0x10);
1689 snd_soc_update_bits(codec,
1690 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
1691 0x10);
1692 snd_soc_update_bits(codec,
1693 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1694 0x00);
1695 snd_soc_update_bits(codec,
1696 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1697 0x00);
1698 }
1699 dai->bus_down_in_recovery = false;
1700 tavil_codec_enable_slim_port_intr(dai, codec);
1701 (void) tavil_codec_enable_slim_chmask(dai, true);
1702 ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1703 dai->rate, dai->bit_width,
1704 &dai->grph);
1705 break;
1706 case SND_SOC_DAPM_POST_PMD:
1707 ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
1708 dai->grph);
1709 if (ret)
1710 dev_err(codec->dev, "%s error in close_slim_sch_tx %d\n",
1711 __func__, ret);
1712 if (!dai->bus_down_in_recovery)
1713 ret = tavil_codec_enable_slim_chmask(dai, false);
1714 if (ret < 0) {
1715 ret = wcd9xxx_disconnect_port(core,
1716 &dai->wcd9xxx_ch_list,
1717 dai->grph);
1718 dev_dbg(codec->dev, "%s: Disconnect TX port, ret = %d\n",
1719 __func__, ret);
1720 }
1721 if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
1722 /* Disable V&I sensing */
1723 dev_dbg(codec->dev, "%s: spkr1 disabled\n", __func__);
1724 snd_soc_update_bits(codec,
1725 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
1726 snd_soc_update_bits(codec,
1727 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
1728 0x20);
1729 snd_soc_update_bits(codec,
1730 WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x00);
1731 snd_soc_update_bits(codec,
1732 WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
1733 0x00);
1734 }
1735 if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
1736 /* Disable V&I sensing */
1737 dev_dbg(codec->dev, "%s: spkr2 disabled\n", __func__);
1738 snd_soc_update_bits(codec,
1739 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
1740 0x20);
1741 snd_soc_update_bits(codec,
1742 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
1743 0x20);
1744 snd_soc_update_bits(codec,
1745 WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
1746 0x00);
1747 snd_soc_update_bits(codec,
1748 WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
1749 0x00);
1750 }
1751 break;
1752 }
1753done:
1754 return ret;
1755}
1756
1757static int tavil_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1758 struct snd_kcontrol *kcontrol, int event)
1759{
1760 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1761 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1762
1763 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1764
1765 switch (event) {
1766 case SND_SOC_DAPM_PRE_PMU:
1767 tavil->rx_bias_count++;
1768 if (tavil->rx_bias_count == 1) {
1769 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
1770 0x01, 0x01);
1771 }
1772 break;
1773 case SND_SOC_DAPM_POST_PMD:
1774 tavil->rx_bias_count--;
1775 if (!tavil->rx_bias_count)
1776 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
1777 0x01, 0x00);
1778 break;
1779 };
1780 dev_dbg(codec->dev, "%s: Current RX BIAS user count: %d\n", __func__,
1781 tavil->rx_bias_count);
1782
1783 return 0;
1784}
1785
1786static void tavil_spk_anc_update_callback(struct work_struct *work)
1787{
1788 struct spk_anc_work *spk_anc_dwork;
1789 struct tavil_priv *tavil;
1790 struct delayed_work *delayed_work;
1791 struct snd_soc_codec *codec;
1792
1793 delayed_work = to_delayed_work(work);
1794 spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork);
1795 tavil = spk_anc_dwork->tavil;
1796 codec = tavil->codec;
1797
1798 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10);
1799}
1800
1801static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w,
1802 struct snd_kcontrol *kcontrol,
1803 int event)
1804{
1805 int ret = 0;
1806 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1807 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1808
1809 if (!tavil->anc_func)
1810 return 0;
1811
1812 dev_dbg(codec->dev, "%s: w: %s event: %d anc: %d\n", __func__,
1813 w->name, event, tavil->anc_func);
1814
1815 switch (event) {
1816 case SND_SOC_DAPM_PRE_PMU:
1817 ret = tavil_codec_enable_anc(w, kcontrol, event);
1818 schedule_delayed_work(&tavil->spk_anc_dwork.dwork,
1819 msecs_to_jiffies(spk_anc_en_delay));
1820 break;
1821 case SND_SOC_DAPM_POST_PMD:
1822 cancel_delayed_work_sync(&tavil->spk_anc_dwork.dwork);
1823 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0,
1824 0x10, 0x00);
1825 ret = tavil_codec_enable_anc(w, kcontrol, event);
1826 break;
1827 }
1828 return ret;
1829}
1830
1831static int tavil_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
1832 struct snd_kcontrol *kcontrol,
1833 int event)
1834{
1835 int ret = 0;
1836 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1837
1838 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1839
1840 switch (event) {
1841 case SND_SOC_DAPM_POST_PMU:
1842 /*
1843 * 5ms sleep is required after PA is enabled as per
1844 * HW requirement
1845 */
1846 usleep_range(5000, 5500);
1847 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CTL,
1848 0x10, 0x00);
1849 /* Remove mix path mute if it is enabled */
1850 if ((snd_soc_read(codec, WCD934X_CDC_RX0_RX_PATH_MIX_CTL)) &
1851 0x10)
1852 snd_soc_update_bits(codec,
1853 WCD934X_CDC_RX0_RX_PATH_MIX_CTL,
1854 0x10, 0x00);
1855 break;
1856 case SND_SOC_DAPM_POST_PMD:
1857 /*
1858 * 5ms sleep is required after PA is disabled as per
1859 * HW requirement
1860 */
1861 usleep_range(5000, 5500);
1862
1863 if (!(strcmp(w->name, "ANC EAR PA"))) {
1864 ret = tavil_codec_enable_anc(w, kcontrol, event);
1865 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CFG0,
1866 0x10, 0x00);
1867 }
1868 break;
1869 };
1870
1871 return ret;
1872}
1873
1874static void tavil_codec_override(struct snd_soc_codec *codec, int mode,
1875 int event)
1876{
1877 if (mode == CLS_AB || mode == CLS_AB_HIFI) {
1878 switch (event) {
1879 case SND_SOC_DAPM_PRE_PMU:
1880 case SND_SOC_DAPM_POST_PMU:
1881 if (!(snd_soc_read(codec,
1882 WCD934X_CDC_RX2_RX_PATH_CTL) & 0x10) &&
1883 (!(snd_soc_read(codec,
1884 WCD934X_CDC_RX1_RX_PATH_CTL) & 0x10)))
1885 snd_soc_update_bits(codec,
1886 WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x02);
1887 break;
1888 case SND_SOC_DAPM_POST_PMD:
1889 snd_soc_update_bits(codec,
1890 WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x00);
1891 break;
1892 }
1893 }
1894}
1895
1896static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
1897 struct snd_kcontrol *kcontrol,
1898 int event)
1899{
1900 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1901 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1902 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
1903
1904 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1905
1906 switch (event) {
1907 case SND_SOC_DAPM_PRE_PMU:
1908 if (TAVIL_IS_1_0(tavil->wcd9xxx))
1909 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
1910 0x06, (0x03 << 1));
1911 set_bit(HPH_PA_DELAY, &tavil->status_mask);
1912 if (dsd_conf &&
1913 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) {
1914 /* Set regulator mode to AB if DSD is enabled */
1915 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
1916 0x02, 0x02);
1917 }
1918 break;
1919 case SND_SOC_DAPM_POST_PMU:
1920 /*
1921 * 7ms sleep is required after PA is enabled as per
1922 * HW requirement
1923 */
1924 if (test_bit(HPH_PA_DELAY, &tavil->status_mask)) {
1925 usleep_range(7000, 7100);
1926 clear_bit(HPH_PA_DELAY, &tavil->status_mask);
1927 }
1928
1929 snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x01);
1930
1931 /* Remove mute */
1932 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
1933 0x10, 0x00);
1934 /* Enable GM3 boost */
1935 snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
1936 0x80, 0x80);
1937 /* Enable AutoChop timer at the end of power up */
1938 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
1939 0x02, 0x02);
1940 /* Remove mix path mute if it is enabled */
1941 if ((snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) &
1942 0x10)
1943 snd_soc_update_bits(codec,
1944 WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
1945 0x10, 0x00);
1946 if (dsd_conf &&
1947 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
1948 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
1949 0x04, 0x00);
1950 tavil_codec_override(codec, tavil->hph_mode, event);
1951 break;
1952 case SND_SOC_DAPM_PRE_PMD:
1953 blocking_notifier_call_chain(&tavil->mbhc->notifier,
1954 WCD_EVENT_PRE_HPHR_PA_OFF,
1955 &tavil->mbhc->wcd_mbhc);
1956 /* Enable DSD Mute before PA disable */
1957 if (dsd_conf &&
1958 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
1959 snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
1960 0x04, 0x04);
1961 snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x00);
1962 snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
1963 0x10, 0x10);
1964 break;
1965 case SND_SOC_DAPM_POST_PMD:
1966 /* 5ms sleep is required after PA disable */
1967 usleep_range(5000, 5100);
1968 tavil_codec_override(codec, tavil->hph_mode, event);
1969 blocking_notifier_call_chain(&tavil->mbhc->notifier,
1970 WCD_EVENT_POST_HPHR_PA_OFF,
1971 &tavil->mbhc->wcd_mbhc);
1972 if (TAVIL_IS_1_0(tavil->wcd9xxx))
1973 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
1974 0x06, 0x0);
1975 break;
1976 };
1977
1978 return 0;
1979}
1980
1981static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
1982 struct snd_kcontrol *kcontrol,
1983 int event)
1984{
1985 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1986 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
1987 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
1988
1989 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
1990
1991 switch (event) {
1992 case SND_SOC_DAPM_PRE_PMU:
1993 if (TAVIL_IS_1_0(tavil->wcd9xxx))
1994 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
1995 0x06, (0x03 << 1));
1996 set_bit(HPH_PA_DELAY, &tavil->status_mask);
1997 if (dsd_conf &&
1998 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) {
1999 /* Set regulator mode to AB if DSD is enabled */
2000 snd_soc_update_bits(codec, WCD934X_ANA_RX_SUPPLIES,
2001 0x02, 0x02);
2002 }
2003 break;
2004 case SND_SOC_DAPM_POST_PMU:
2005 /*
2006 * 7ms sleep is required after PA is enabled as per
2007 * HW requirement
2008 */
2009 if (test_bit(HPH_PA_DELAY, &tavil->status_mask)) {
2010 usleep_range(7000, 7100);
2011 clear_bit(HPH_PA_DELAY, &tavil->status_mask);
2012 }
2013 snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x01);
2014 /* Remove Mute on primary path */
2015 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
2016 0x10, 0x00);
2017 /* Enable GM3 boost */
2018 snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
2019 0x80, 0x80);
2020 /* Enable AutoChop timer at the end of power up */
2021 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2022 0x02, 0x02);
2023 /* Remove mix path mute if it is enabled */
2024 if ((snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) &
2025 0x10)
2026 snd_soc_update_bits(codec,
2027 WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
2028 0x10, 0x00);
2029 if (dsd_conf &&
2030 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2031 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
2032 0x04, 0x00);
2033 tavil_codec_override(codec, tavil->hph_mode, event);
2034 break;
2035 case SND_SOC_DAPM_PRE_PMD:
2036 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2037 WCD_EVENT_PRE_HPHL_PA_OFF,
2038 &tavil->mbhc->wcd_mbhc);
2039 /* Enable DSD Mute before PA disable */
2040 if (dsd_conf &&
2041 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2042 snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
2043 0x04, 0x04);
2044
2045 snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x00);
2046 snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
2047 0x10, 0x10);
2048 break;
2049 case SND_SOC_DAPM_POST_PMD:
2050 /* 5ms sleep is required after PA disable */
2051 usleep_range(5000, 5100);
2052 tavil_codec_override(codec, tavil->hph_mode, event);
2053 blocking_notifier_call_chain(&tavil->mbhc->notifier,
2054 WCD_EVENT_POST_HPHL_PA_OFF,
2055 &tavil->mbhc->wcd_mbhc);
2056 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2057 snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
2058 0x06, 0x0);
2059 break;
2060 };
2061
2062 return 0;
2063}
2064
2065static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
2066 struct snd_kcontrol *kcontrol,
2067 int event)
2068{
2069 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2070 u16 lineout_vol_reg = 0, lineout_mix_vol_reg = 0;
2071
2072 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2073
2074 if (w->reg == WCD934X_ANA_LO_1_2) {
2075 if (w->shift == 7) {
2076 lineout_vol_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2077 lineout_mix_vol_reg = WCD934X_CDC_RX3_RX_PATH_MIX_CTL;
2078 } else if (w->shift == 6) {
2079 lineout_vol_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
2080 lineout_mix_vol_reg = WCD934X_CDC_RX4_RX_PATH_MIX_CTL;
2081 }
2082 } else {
2083 dev_err(codec->dev, "%s: Error enabling lineout PA\n",
2084 __func__);
2085 return -EINVAL;
2086 }
2087
2088 switch (event) {
2089 case SND_SOC_DAPM_PRE_PMU:
2090 tavil_codec_override(codec, CLS_AB, event);
2091 break;
2092 case SND_SOC_DAPM_POST_PMU:
2093 /*
2094 * 5ms sleep is required after PA is enabled as per
2095 * HW requirement
2096 */
2097 usleep_range(5000, 5500);
2098 snd_soc_update_bits(codec, lineout_vol_reg,
2099 0x10, 0x00);
2100 /* Remove mix path mute if it is enabled */
2101 if ((snd_soc_read(codec, lineout_mix_vol_reg)) & 0x10)
2102 snd_soc_update_bits(codec,
2103 lineout_mix_vol_reg,
2104 0x10, 0x00);
2105 break;
2106 case SND_SOC_DAPM_POST_PMD:
2107 /*
2108 * 5ms sleep is required after PA is disabled as per
2109 * HW requirement
2110 */
2111 usleep_range(5000, 5500);
2112 tavil_codec_override(codec, CLS_AB, event);
2113 default:
2114 break;
2115 };
2116
2117 return 0;
2118}
2119
2120static int tavil_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
2121 struct snd_kcontrol *kcontrol,
2122 int event)
2123{
2124 int ret = 0;
2125 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2126 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2127
2128 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2129
2130 switch (event) {
2131 case SND_SOC_DAPM_PRE_PMU:
2132 /* Disable AutoChop timer during power up */
2133 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2134 0x02, 0x00);
2135
2136 if (tavil->anc_func)
2137 ret = tavil_codec_enable_anc(w, kcontrol, event);
2138
2139 wcd_clsh_fsm(codec, &tavil->clsh_d,
2140 WCD_CLSH_EVENT_PRE_DAC,
2141 WCD_CLSH_STATE_EAR,
2142 CLS_H_NORMAL);
2143 if (tavil->anc_func)
2144 snd_soc_update_bits(codec, WCD934X_CDC_RX0_RX_PATH_CFG0,
2145 0x10, 0x10);
2146 break;
2147 case SND_SOC_DAPM_POST_PMD:
2148 wcd_clsh_fsm(codec, &tavil->clsh_d,
2149 WCD_CLSH_EVENT_POST_PA,
2150 WCD_CLSH_STATE_EAR,
2151 CLS_H_NORMAL);
2152 break;
2153 default:
2154 break;
2155 };
2156
2157 return ret;
2158}
2159
2160static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
2161 struct snd_kcontrol *kcontrol,
2162 int event)
2163{
2164 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2165 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2166 int hph_mode = tavil->hph_mode;
2167 u8 dem_inp;
2168 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
2169
2170 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2171 w->name, event, hph_mode);
2172
2173 switch (event) {
2174 case SND_SOC_DAPM_PRE_PMU:
2175 /* Read DEM INP Select */
2176 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_SEC0) &
2177 0x03;
2178 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2179 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2180 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2181 __func__, hph_mode);
2182 return -EINVAL;
2183 }
2184 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2185 /* Ripple freq control enable */
2186 snd_soc_update_bits(codec,
2187 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2188 0x01, 0x01);
2189 /* Disable AutoChop timer during power up */
2190 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2191 0x02, 0x00);
2192 /* Set RDAC gain */
2193 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2194 snd_soc_update_bits(codec,
2195 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2196 0xF0, 0x40);
2197 if (dsd_conf &&
2198 (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
2199 hph_mode = CLS_H_HIFI;
2200
2201 wcd_clsh_fsm(codec, &tavil->clsh_d,
2202 WCD_CLSH_EVENT_PRE_DAC,
2203 WCD_CLSH_STATE_HPHR,
2204 hph_mode);
2205 break;
2206 case SND_SOC_DAPM_POST_PMD:
2207 /* 1000us required as per HW requirement */
2208 usleep_range(1000, 1100);
2209 wcd_clsh_fsm(codec, &tavil->clsh_d,
2210 WCD_CLSH_EVENT_POST_PA,
2211 WCD_CLSH_STATE_HPHR,
2212 hph_mode);
2213 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2214 /* Ripple freq control disable */
2215 snd_soc_update_bits(codec,
2216 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2217 0x01, 0x0);
2218 /* Re-set RDAC gain */
2219 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2220 snd_soc_update_bits(codec,
2221 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2222 0xF0, 0x0);
2223 break;
2224 default:
2225 break;
2226 };
2227
2228 return 0;
2229}
2230
2231static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
2232 struct snd_kcontrol *kcontrol,
2233 int event)
2234{
2235 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2236 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2237 int hph_mode = tavil->hph_mode;
2238 u8 dem_inp;
2239 int ret = 0;
2240 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
2241
2242 dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__,
2243 w->name, event, hph_mode);
2244
2245 switch (event) {
2246 case SND_SOC_DAPM_PRE_PMU:
2247 /* Read DEM INP Select */
2248 dem_inp = snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_SEC0) &
2249 0x03;
2250 if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
2251 (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
2252 dev_err(codec->dev, "%s: DEM Input not set correctly, hph_mode: %d\n",
2253 __func__, hph_mode);
2254 return -EINVAL;
2255 }
2256 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2257 /* Ripple freq control enable */
2258 snd_soc_update_bits(codec,
2259 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2260 0x01, 0x01);
2261 /* Disable AutoChop timer during power up */
2262 snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
2263 0x02, 0x00);
2264 /* Set RDAC gain */
2265 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2266 snd_soc_update_bits(codec,
2267 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2268 0xF0, 0x40);
2269 if (dsd_conf &&
2270 (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
2271 hph_mode = CLS_H_HIFI;
2272
2273 wcd_clsh_fsm(codec, &tavil->clsh_d,
2274 WCD_CLSH_EVENT_PRE_DAC,
2275 WCD_CLSH_STATE_HPHL,
2276 hph_mode);
2277 break;
2278 case SND_SOC_DAPM_POST_PMD:
2279 /* 1000us required as per HW requirement */
2280 usleep_range(1000, 1100);
2281 wcd_clsh_fsm(codec, &tavil->clsh_d,
2282 WCD_CLSH_EVENT_POST_PA,
2283 WCD_CLSH_STATE_HPHL,
2284 hph_mode);
2285 if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
2286 /* Ripple freq control disable */
2287 snd_soc_update_bits(codec,
2288 WCD934X_SIDO_NEW_VOUT_D_FREQ2,
2289 0x01, 0x0);
2290 /* Re-set RDAC gain */
2291 if (TAVIL_IS_1_0(tavil->wcd9xxx))
2292 snd_soc_update_bits(codec,
2293 WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
2294 0xF0, 0x0);
2295 break;
2296 default:
2297 break;
2298 };
2299
2300 return ret;
2301}
2302
2303static int tavil_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
2304 struct snd_kcontrol *kcontrol,
2305 int event)
2306{
2307 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2308 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2309
2310 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2311
2312 switch (event) {
2313 case SND_SOC_DAPM_PRE_PMU:
2314 wcd_clsh_fsm(codec, &tavil->clsh_d,
2315 WCD_CLSH_EVENT_PRE_DAC,
2316 WCD_CLSH_STATE_LO,
2317 CLS_AB);
2318 break;
2319 case SND_SOC_DAPM_POST_PMD:
2320 wcd_clsh_fsm(codec, &tavil->clsh_d,
2321 WCD_CLSH_EVENT_POST_PA,
2322 WCD_CLSH_STATE_LO,
2323 CLS_AB);
2324 break;
2325 }
2326
2327 return 0;
2328}
2329
2330static int tavil_codec_spk_boost_event(struct snd_soc_dapm_widget *w,
2331 struct snd_kcontrol *kcontrol,
2332 int event)
2333{
2334 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2335 u16 boost_path_ctl, boost_path_cfg1;
2336 u16 reg, reg_mix;
2337
2338 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
2339
2340 if (!strcmp(w->name, "RX INT7 CHAIN")) {
2341 boost_path_ctl = WCD934X_CDC_BOOST0_BOOST_PATH_CTL;
2342 boost_path_cfg1 = WCD934X_CDC_RX7_RX_PATH_CFG1;
2343 reg = WCD934X_CDC_RX7_RX_PATH_CTL;
2344 reg_mix = WCD934X_CDC_RX7_RX_PATH_MIX_CTL;
2345 } else if (!strcmp(w->name, "RX INT8 CHAIN")) {
2346 boost_path_ctl = WCD934X_CDC_BOOST1_BOOST_PATH_CTL;
2347 boost_path_cfg1 = WCD934X_CDC_RX8_RX_PATH_CFG1;
2348 reg = WCD934X_CDC_RX8_RX_PATH_CTL;
2349 reg_mix = WCD934X_CDC_RX8_RX_PATH_MIX_CTL;
2350 } else {
2351 dev_err(codec->dev, "%s: unknown widget: %s\n",
2352 __func__, w->name);
2353 return -EINVAL;
2354 }
2355
2356 switch (event) {
2357 case SND_SOC_DAPM_PRE_PMU:
2358 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
2359 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
2360 snd_soc_update_bits(codec, reg, 0x10, 0x00);
2361 if ((snd_soc_read(codec, reg_mix)) & 0x10)
2362 snd_soc_update_bits(codec, reg_mix, 0x10, 0x00);
2363 break;
2364 case SND_SOC_DAPM_POST_PMD:
2365 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
2366 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
2367 break;
2368 };
2369
2370 return 0;
2371}
2372
2373static int __tavil_codec_enable_swr(struct snd_soc_dapm_widget *w, int event)
2374{
2375 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2376 struct tavil_priv *tavil;
2377 int ch_cnt = 0;
2378
2379 tavil = snd_soc_codec_get_drvdata(codec);
2380
2381 switch (event) {
2382 case SND_SOC_DAPM_PRE_PMU:
2383 if (((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2384 (strnstr(w->name, "INT7 MIX2",
2385 sizeof("RX INT7 MIX2")))))
2386 tavil->swr.rx_7_count++;
2387 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2388 !tavil->swr.rx_8_count)
2389 tavil->swr.rx_8_count++;
2390 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2391
2392 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2393 SWR_DEVICE_UP, NULL);
2394 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2395 SWR_SET_NUM_RX_CH, &ch_cnt);
2396 break;
2397 case SND_SOC_DAPM_POST_PMD:
2398 if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
2399 (strnstr(w->name, "INT7 MIX2",
2400 sizeof("RX INT7 MIX2"))))
2401 tavil->swr.rx_7_count--;
2402 if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
2403 tavil->swr.rx_8_count)
2404 tavil->swr.rx_8_count--;
2405 ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
2406
2407 swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
2408 SWR_SET_NUM_RX_CH, &ch_cnt);
2409
2410 break;
2411 }
2412 dev_dbg(tavil->dev, "%s: %s: current swr ch cnt: %d\n",
2413 __func__, w->name, ch_cnt);
2414
2415 return 0;
2416}
2417
2418static int tavil_codec_enable_swr(struct snd_soc_dapm_widget *w,
2419 struct snd_kcontrol *kcontrol, int event)
2420{
2421 return __tavil_codec_enable_swr(w, event);
2422}
2423
2424static int tavil_codec_config_mad(struct snd_soc_codec *codec)
2425{
2426 int ret = 0;
2427 int idx;
2428 const struct firmware *fw;
2429 struct firmware_cal *hwdep_cal = NULL;
2430 struct wcd_mad_audio_cal *mad_cal = NULL;
2431 const void *data;
2432 const char *filename = WCD934X_MAD_AUDIO_FIRMWARE_PATH;
2433 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2434 size_t cal_size;
2435
2436 hwdep_cal = wcdcal_get_fw_cal(tavil->fw_data, WCD9XXX_MAD_CAL);
2437 if (hwdep_cal) {
2438 data = hwdep_cal->data;
2439 cal_size = hwdep_cal->size;
2440 dev_dbg(codec->dev, "%s: using hwdep calibration\n",
2441 __func__);
2442 } else {
2443 ret = request_firmware(&fw, filename, codec->dev);
2444 if (ret || !fw) {
2445 dev_err(codec->dev,
2446 "%s: MAD firmware acquire failed, err = %d\n",
2447 __func__, ret);
2448 return -ENODEV;
2449 }
2450 data = fw->data;
2451 cal_size = fw->size;
2452 dev_dbg(codec->dev, "%s: using request_firmware calibration\n",
2453 __func__);
2454 }
2455
2456 if (cal_size < sizeof(*mad_cal)) {
2457 dev_err(codec->dev,
2458 "%s: Incorrect size %zd for MAD Cal, expected %zd\n",
2459 __func__, cal_size, sizeof(*mad_cal));
2460 ret = -ENOMEM;
2461 goto done;
2462 }
2463
2464 mad_cal = (struct wcd_mad_audio_cal *) (data);
2465 if (!mad_cal) {
2466 dev_err(codec->dev,
2467 "%s: Invalid calibration data\n",
2468 __func__);
2469 ret = -EINVAL;
2470 goto done;
2471 }
2472
2473 snd_soc_write(codec, WCD934X_SOC_MAD_MAIN_CTL_2,
2474 mad_cal->microphone_info.cycle_time);
2475 snd_soc_update_bits(codec, WCD934X_SOC_MAD_MAIN_CTL_1, 0xFF << 3,
2476 ((uint16_t)mad_cal->microphone_info.settle_time)
2477 << 3);
2478
2479 /* Audio */
2480 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_8,
2481 mad_cal->audio_info.rms_omit_samples);
2482 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_1,
2483 0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
2484 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2, 0x03 << 2,
2485 mad_cal->audio_info.detection_mechanism << 2);
2486 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_7,
2487 mad_cal->audio_info.rms_diff_threshold & 0x3F);
2488 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_5,
2489 mad_cal->audio_info.rms_threshold_lsb);
2490 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_CTL_6,
2491 mad_cal->audio_info.rms_threshold_msb);
2492
2493 for (idx = 0; idx < ARRAY_SIZE(mad_cal->audio_info.iir_coefficients);
2494 idx++) {
2495 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_PTR,
2496 0x3F, idx);
2497 snd_soc_write(codec, WCD934X_SOC_MAD_AUDIO_IIR_CTL_VAL,
2498 mad_cal->audio_info.iir_coefficients[idx]);
2499 dev_dbg(codec->dev, "%s:MAD Audio IIR Coef[%d] = 0X%x",
2500 __func__, idx,
2501 mad_cal->audio_info.iir_coefficients[idx]);
2502 }
2503
2504 /* Beacon */
2505 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_8,
2506 mad_cal->beacon_info.rms_omit_samples);
2507 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_1,
2508 0x07 << 4, mad_cal->beacon_info.rms_comp_time << 4);
2509 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_CTL_2, 0x03 << 2,
2510 mad_cal->beacon_info.detection_mechanism << 2);
2511 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_7,
2512 mad_cal->beacon_info.rms_diff_threshold & 0x1F);
2513 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_5,
2514 mad_cal->beacon_info.rms_threshold_lsb);
2515 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_CTL_6,
2516 mad_cal->beacon_info.rms_threshold_msb);
2517
2518 for (idx = 0; idx < ARRAY_SIZE(mad_cal->beacon_info.iir_coefficients);
2519 idx++) {
2520 snd_soc_update_bits(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_PTR,
2521 0x3F, idx);
2522 snd_soc_write(codec, WCD934X_SOC_MAD_BEACON_IIR_CTL_VAL,
2523 mad_cal->beacon_info.iir_coefficients[idx]);
2524 dev_dbg(codec->dev, "%s:MAD Beacon IIR Coef[%d] = 0X%x",
2525 __func__, idx,
2526 mad_cal->beacon_info.iir_coefficients[idx]);
2527 }
2528
2529 /* Ultrasound */
2530 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_1,
2531 0x07 << 4,
2532 mad_cal->ultrasound_info.rms_comp_time << 4);
2533 snd_soc_update_bits(codec, WCD934X_SOC_MAD_ULTR_CTL_2, 0x03 << 2,
2534 mad_cal->ultrasound_info.detection_mechanism << 2);
2535 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_7,
2536 mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
2537 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_5,
2538 mad_cal->ultrasound_info.rms_threshold_lsb);
2539 snd_soc_write(codec, WCD934X_SOC_MAD_ULTR_CTL_6,
2540 mad_cal->ultrasound_info.rms_threshold_msb);
2541
2542done:
2543 if (!hwdep_cal)
2544 release_firmware(fw);
2545
2546 return ret;
2547}
2548
2549static int __tavil_codec_enable_mad(struct snd_soc_codec *codec, bool enable)
2550{
2551 int rc = 0;
2552
2553 /* Return if CPE INPUT is DEC1 */
2554 if (snd_soc_read(codec, WCD934X_CPE_SS_SVA_CFG) & 0x04) {
2555 dev_dbg(codec->dev, "%s: MAD is bypassed, skip mad %s\n",
2556 __func__, enable ? "enable" : "disable");
2557 return rc;
2558 }
2559
2560 dev_dbg(codec->dev, "%s: enable = %s\n", __func__,
2561 enable ? "enable" : "disable");
2562
2563 if (enable) {
2564 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2565 0x03, 0x03);
2566 rc = tavil_codec_config_mad(codec);
2567 if (IS_ERR_VALUE(rc)) {
2568 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2569 0x03, 0x00);
2570 goto done;
2571 }
2572
2573 /* Turn on MAD clk */
2574 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2575 0x01, 0x01);
2576
2577 /* Undo reset for MAD */
2578 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2579 0x02, 0x00);
2580 } else {
2581 snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
2582 0x03, 0x00);
2583 /* Reset the MAD block */
2584 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2585 0x02, 0x02);
2586 /* Turn off MAD clk */
2587 snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
2588 0x01, 0x00);
2589 }
2590done:
2591 return rc;
2592}
2593
2594static int tavil_codec_ape_enable_mad(struct snd_soc_dapm_widget *w,
2595 struct snd_kcontrol *kcontrol,
2596 int event)
2597{
2598 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2599 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2600 int rc = 0;
2601
2602 switch (event) {
2603 case SND_SOC_DAPM_PRE_PMU:
2604 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x40);
2605 rc = __tavil_codec_enable_mad(codec, true);
2606 break;
2607 case SND_SOC_DAPM_PRE_PMD:
2608 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x40, 0x00);
2609 __tavil_codec_enable_mad(codec, false);
2610 break;
2611 }
2612
2613 dev_dbg(tavil->dev, "%s: event = %d\n", __func__, event);
2614 return rc;
2615}
2616
2617static int tavil_codec_cpe_mad_ctl(struct snd_soc_dapm_widget *w,
2618 struct snd_kcontrol *kcontrol, int event)
2619{
2620 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2621 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2622 int rc = 0;
2623
2624 switch (event) {
2625 case SND_SOC_DAPM_PRE_PMU:
2626 tavil->mad_switch_cnt++;
2627 if (tavil->mad_switch_cnt != 1)
2628 goto done;
2629
2630 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x20);
2631 rc = __tavil_codec_enable_mad(codec, true);
2632 if (IS_ERR_VALUE(rc)) {
2633 tavil->mad_switch_cnt--;
2634 goto done;
2635 }
2636
2637 break;
2638 case SND_SOC_DAPM_PRE_PMD:
2639 tavil->mad_switch_cnt--;
2640 if (tavil->mad_switch_cnt != 0)
2641 goto done;
2642
2643 snd_soc_update_bits(codec, WCD934X_CPE_SS_SVA_CFG, 0x20, 0x00);
2644 __tavil_codec_enable_mad(codec, false);
2645 break;
2646 }
2647done:
2648 dev_dbg(tavil->dev, "%s: event = %d, mad_switch_cnt = %d\n",
2649 __func__, event, tavil->mad_switch_cnt);
2650 return rc;
2651}
2652
2653static int tavil_get_asrc_mode(struct tavil_priv *tavil, int asrc,
2654 u8 main_sr, u8 mix_sr)
2655{
2656 u8 asrc_output_mode;
2657 int asrc_mode = CONV_88P2K_TO_384K;
2658
2659 if ((asrc < 0) || (asrc >= ASRC_MAX))
2660 return 0;
2661
2662 asrc_output_mode = tavil->asrc_output_mode[asrc];
2663
2664 if (asrc_output_mode) {
2665 /*
2666 * If Mix sample rate is < 96KHz, use 96K to 352.8K
2667 * conversion, or else use 384K to 352.8K conversion
2668 */
2669 if (mix_sr < 5)
2670 asrc_mode = CONV_96K_TO_352P8K;
2671 else
2672 asrc_mode = CONV_384K_TO_352P8K;
2673 } else {
2674 /* Integer main and Fractional mix path */
2675 if (main_sr < 8 && mix_sr > 9) {
2676 asrc_mode = CONV_352P8K_TO_384K;
2677 } else if (main_sr > 8 && mix_sr < 8) {
2678 /* Fractional main and Integer mix path */
2679 if (mix_sr < 5)
2680 asrc_mode = CONV_96K_TO_352P8K;
2681 else
2682 asrc_mode = CONV_384K_TO_352P8K;
2683 } else if (main_sr < 8 && mix_sr < 8) {
2684 /* Integer main and Integer mix path */
2685 asrc_mode = CONV_96K_TO_384K;
2686 }
2687 }
2688
2689 return asrc_mode;
2690}
2691
2692static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
2693 int asrc_in, int event)
2694{
2695 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2696 u16 cfg_reg, ctl_reg, clk_reg, asrc_ctl, mix_ctl_reg;
2697 int asrc, ret = 0;
2698 u8 main_sr, mix_sr, asrc_mode = 0;
2699
2700 switch (asrc_in) {
2701 case ASRC_IN_HPHL:
2702 cfg_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
2703 ctl_reg = WCD934X_CDC_RX1_RX_PATH_CTL;
2704 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2705 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2706 asrc = ASRC0;
2707 break;
2708 case ASRC_IN_LO1:
2709 cfg_reg = WCD934X_CDC_RX3_RX_PATH_CFG0;
2710 ctl_reg = WCD934X_CDC_RX3_RX_PATH_CTL;
2711 clk_reg = WCD934X_MIXING_ASRC0_CLK_RST_CTL;
2712 asrc_ctl = WCD934X_MIXING_ASRC0_CTL1;
2713 asrc = ASRC0;
2714 break;
2715 case ASRC_IN_HPHR:
2716 cfg_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
2717 ctl_reg = WCD934X_CDC_RX2_RX_PATH_CTL;
2718 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
2719 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
2720 asrc = ASRC1;
2721 break;
2722 case ASRC_IN_LO2:
2723 cfg_reg = WCD934X_CDC_RX4_RX_PATH_CFG0;
2724 ctl_reg = WCD934X_CDC_RX4_RX_PATH_CTL;
2725 clk_reg = WCD934X_MIXING_ASRC1_CLK_RST_CTL;
2726 asrc_ctl = WCD934X_MIXING_ASRC1_CTL1;
2727 asrc = ASRC1;
2728 break;
2729 case ASRC_IN_SPKR1:
2730 cfg_reg = WCD934X_CDC_RX7_RX_PATH_CFG0;
2731 ctl_reg = WCD934X_CDC_RX7_RX_PATH_CTL;
2732 clk_reg = WCD934X_MIXING_ASRC2_CLK_RST_CTL;
2733 asrc_ctl = WCD934X_MIXING_ASRC2_CTL1;
2734 asrc = ASRC2;
2735 break;
2736 case ASRC_IN_SPKR2:
2737 cfg_reg = WCD934X_CDC_RX8_RX_PATH_CFG0;
2738 ctl_reg = WCD934X_CDC_RX8_RX_PATH_CTL;
2739 clk_reg = WCD934X_MIXING_ASRC3_CLK_RST_CTL;
2740 asrc_ctl = WCD934X_MIXING_ASRC3_CTL1;
2741 asrc = ASRC3;
2742 break;
2743 default:
2744 dev_err(codec->dev, "%s: Invalid asrc input :%d\n", __func__,
2745 asrc_in);
2746 ret = -EINVAL;
2747 goto done;
2748 };
2749
2750 switch (event) {
2751 case SND_SOC_DAPM_PRE_PMU:
2752 if (tavil->asrc_users[asrc] == 0) {
2753 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x80);
2754 snd_soc_update_bits(codec, clk_reg, 0x01, 0x01);
2755 main_sr = snd_soc_read(codec, ctl_reg) & 0x0F;
2756 mix_ctl_reg = ctl_reg + 5;
2757 mix_sr = snd_soc_read(codec, mix_ctl_reg) & 0x0F;
2758 asrc_mode = tavil_get_asrc_mode(tavil, asrc,
2759 main_sr, mix_sr);
2760 dev_dbg(codec->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
2761 __func__, main_sr, mix_sr, asrc_mode);
2762 snd_soc_update_bits(codec, asrc_ctl, 0x07, asrc_mode);
2763 }
2764 tavil->asrc_users[asrc]++;
2765 break;
2766 case SND_SOC_DAPM_POST_PMD:
2767 tavil->asrc_users[asrc]--;
2768 if (tavil->asrc_users[asrc] <= 0) {
2769 tavil->asrc_users[asrc] = 0;
2770 snd_soc_update_bits(codec, asrc_ctl, 0x07, 0x00);
2771 snd_soc_update_bits(codec, cfg_reg, 0x80, 0x00);
2772 snd_soc_update_bits(codec, clk_reg, 0x01, 0x00);
2773 }
2774 break;
2775 };
2776
2777 dev_dbg(codec->dev, "%s: ASRC%d, users: %d\n",
2778 __func__, asrc, tavil->asrc_users[asrc]);
2779
2780done:
2781 return ret;
2782}
2783
2784static int tavil_codec_enable_asrc_resampler(struct snd_soc_dapm_widget *w,
2785 struct snd_kcontrol *kcontrol,
2786 int event)
2787{
2788 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2789 int ret = 0;
2790 u8 cfg, asrc_in;
2791
2792 cfg = snd_soc_read(codec, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0);
2793 if (!(cfg & 0xFF)) {
2794 dev_err(codec->dev, "%s: ASRC%u input not selected\n",
2795 __func__, w->shift);
2796 return -EINVAL;
2797 }
2798
2799 switch (w->shift) {
2800 case ASRC0:
2801 asrc_in = ((cfg & 0x03) == 1) ? ASRC_IN_HPHL : ASRC_IN_LO1;
2802 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
2803 break;
2804 case ASRC1:
2805 asrc_in = ((cfg & 0x0C) == 4) ? ASRC_IN_HPHR : ASRC_IN_LO2;
2806 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
2807 break;
2808 case ASRC2:
2809 asrc_in = ((cfg & 0x30) == 0x20) ? ASRC_IN_SPKR1 : ASRC_INVALID;
2810 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
2811 break;
2812 case ASRC3:
2813 asrc_in = ((cfg & 0xC0) == 0x80) ? ASRC_IN_SPKR2 : ASRC_INVALID;
2814 ret = tavil_codec_enable_asrc(codec, asrc_in, event);
2815 break;
2816 default:
2817 dev_err(codec->dev, "%s: Invalid asrc:%u\n", __func__,
2818 w->shift);
2819 ret = -EINVAL;
2820 break;
2821 };
2822
2823 return ret;
2824}
2825
2826static int tavil_enable_native_supply(struct snd_soc_dapm_widget *w,
2827 struct snd_kcontrol *kcontrol, int event)
2828{
2829 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2830 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2831
2832 switch (event) {
2833 case SND_SOC_DAPM_PRE_PMU:
2834 if (++tavil->native_clk_users == 1) {
2835 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
2836 0x01, 0x01);
2837 usleep_range(100, 120);
2838 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
2839 0x06, 0x02);
2840 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
2841 0x01, 0x01);
2842 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
2843 0x04, 0x00);
2844 usleep_range(30, 50);
2845 snd_soc_update_bits(codec,
2846 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
2847 0x02, 0x02);
2848 snd_soc_update_bits(codec,
2849 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
2850 0x10, 0x10);
2851 }
2852 break;
2853 case SND_SOC_DAPM_PRE_PMD:
2854 if (tavil->native_clk_users &&
2855 (--tavil->native_clk_users == 0)) {
2856 snd_soc_update_bits(codec,
2857 WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
2858 0x10, 0x00);
2859 snd_soc_update_bits(codec,
2860 WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
2861 0x02, 0x00);
2862 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_GATE,
2863 0x04, 0x04);
2864 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
2865 0x01, 0x00);
2866 snd_soc_update_bits(codec, WCD934X_CLK_SYS_MCLK2_PRG1,
2867 0x06, 0x00);
2868 snd_soc_update_bits(codec, WCD934X_CLK_SYS_PLL_ENABLES,
2869 0x01, 0x00);
2870 }
2871 break;
2872 }
2873
2874 dev_dbg(codec->dev, "%s: native_clk_users: %d, event: %d\n",
2875 __func__, tavil->native_clk_users, event);
2876
2877 return 0;
2878}
2879
2880static void tavil_codec_hphdelay_lutbypass(struct snd_soc_codec *codec,
2881 u16 interp_idx, int event)
2882{
2883 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2884 u8 hph_dly_mask;
2885 u16 hph_lut_bypass_reg = 0;
2886 u16 hph_comp_ctrl7 = 0;
2887
2888
2889 switch (interp_idx) {
2890 case INTERP_HPHL:
2891 hph_dly_mask = 1;
2892 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
2893 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
2894 break;
2895 case INTERP_HPHR:
2896 hph_dly_mask = 2;
2897 hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
2898 hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
2899 break;
2900 default:
2901 break;
2902 }
2903
2904 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
2905 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
2906 hph_dly_mask, 0x0);
2907 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x80);
2908 if (tavil->hph_mode == CLS_H_ULP)
2909 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x20);
2910 }
2911
2912 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
2913 snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
2914 hph_dly_mask, hph_dly_mask);
2915 snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x00);
2916 snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x0);
2917 }
2918}
2919
2920static void tavil_codec_hd2_control(struct tavil_priv *priv,
2921 u16 interp_idx, int event)
2922{
2923 u16 hd2_scale_reg;
2924 u16 hd2_enable_reg = 0;
2925 struct snd_soc_codec *codec = priv->codec;
2926
2927 if (TAVIL_IS_1_1(priv->wcd9xxx))
2928 return;
2929
2930 switch (interp_idx) {
2931 case INTERP_HPHL:
2932 hd2_scale_reg = WCD934X_CDC_RX1_RX_PATH_SEC3;
2933 hd2_enable_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
2934 break;
2935 case INTERP_HPHR:
2936 hd2_scale_reg = WCD934X_CDC_RX2_RX_PATH_SEC3;
2937 hd2_enable_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
2938 break;
2939 }
2940
2941 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
2942 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x14);
2943 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
2944 }
2945
2946 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
2947 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
2948 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
2949 }
2950}
2951
2952static int tavil_codec_config_ear_spkr_gain(struct snd_soc_codec *codec,
2953 int event, int gain_reg)
2954{
2955 int comp_gain_offset, val;
2956 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
2957
2958 switch (tavil->swr.spkr_mode) {
2959 /* Compander gain in SPKR_MODE1 case is 12 dB */
2960 case WCD934X_SPKR_MODE_1:
2961 comp_gain_offset = -12;
2962 break;
2963 /* Default case compander gain is 15 dB */
2964 default:
2965 comp_gain_offset = -15;
2966 break;
2967 }
2968
2969 switch (event) {
2970 case SND_SOC_DAPM_POST_PMU:
2971 /* Apply ear spkr gain only if compander is enabled */
2972 if (tavil->comp_enabled[COMPANDER_7] &&
2973 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
2974 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
2975 (tavil->ear_spkr_gain != 0)) {
2976 /* For example, val is -8(-12+5-1) for 4dB of gain */
2977 val = comp_gain_offset + tavil->ear_spkr_gain - 1;
2978 snd_soc_write(codec, gain_reg, val);
2979
2980 dev_dbg(codec->dev, "%s: RX7 Volume %d dB\n",
2981 __func__, val);
2982 }
2983 break;
2984 case SND_SOC_DAPM_POST_PMD:
2985 /*
2986 * Reset RX7 volume to 0 dB if compander is enabled and
2987 * ear_spkr_gain is non-zero.
2988 */
2989 if (tavil->comp_enabled[COMPANDER_7] &&
2990 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
2991 gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL) &&
2992 (tavil->ear_spkr_gain != 0)) {
2993 snd_soc_write(codec, gain_reg, 0x0);
2994
2995 dev_dbg(codec->dev, "%s: Reset RX7 Volume to 0 dB\n",
2996 __func__);
2997 }
2998 break;
2999 }
3000
3001 return 0;
3002}
3003
3004static int tavil_config_compander(struct snd_soc_codec *codec, int interp_n,
3005 int event)
3006{
3007 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3008 int comp;
3009 u16 comp_ctl0_reg, rx_path_cfg0_reg;
3010
3011 /* EAR does not have compander */
3012 if (!interp_n)
3013 return 0;
3014
3015 comp = interp_n - 1;
3016 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
3017 __func__, event, comp + 1, tavil->comp_enabled[comp]);
3018
3019 if (!tavil->comp_enabled[comp])
3020 return 0;
3021
3022 comp_ctl0_reg = WCD934X_CDC_COMPANDER1_CTL0 + (comp * 8);
3023 rx_path_cfg0_reg = WCD934X_CDC_RX1_RX_PATH_CFG0 + (comp * 20);
3024
3025 if (SND_SOC_DAPM_EVENT_ON(event)) {
3026 /* Enable Compander Clock */
3027 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
3028 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3029 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3030 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
3031 }
3032
3033 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3034 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
3035 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
3036 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
3037 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
3038 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
3039 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
3040 }
3041
3042 return 0;
3043}
3044
3045static void tavil_codec_idle_detect_control(struct snd_soc_codec *codec,
3046 int interp, int event)
3047{
3048 int reg = 0, mask, val;
3049 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3050
3051 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3052 return;
3053
3054 if (interp == INTERP_HPHL) {
3055 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3056 mask = 0x01;
3057 val = 0x01;
3058 }
3059 if (interp == INTERP_HPHR) {
3060 reg = WCD934X_CDC_RX_IDLE_DET_PATH_CTL;
3061 mask = 0x02;
3062 val = 0x02;
3063 }
3064
3065 if (reg && SND_SOC_DAPM_EVENT_ON(event))
3066 snd_soc_update_bits(codec, reg, mask, val);
3067
3068 if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
3069 snd_soc_update_bits(codec, reg, mask, 0x00);
3070 tavil->idle_det_cfg.hph_idle_thr = 0;
3071 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, 0x0);
3072 }
3073}
3074
3075/**
3076 * tavil_codec_enable_interp_clk - Enable main path Interpolator
3077 * clock.
3078 *
3079 * @codec: Codec instance
3080 * @event: Indicates speaker path gain offset value
3081 * @intp_idx: Interpolator index
3082 * Returns number of main clock users
3083 */
3084int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec,
3085 int event, int interp_idx)
3086{
3087 struct tavil_priv *tavil;
3088 u16 main_reg;
3089
3090 if (!codec) {
3091 pr_err("%s: codec is NULL\n", __func__);
3092 return -EINVAL;
3093 }
3094
3095 tavil = snd_soc_codec_get_drvdata(codec);
3096 main_reg = WCD934X_CDC_RX0_RX_PATH_CTL + (interp_idx * 20);
3097
3098 if (SND_SOC_DAPM_EVENT_ON(event)) {
3099 if (tavil->main_clk_users[interp_idx] == 0) {
3100 /* Main path PGA mute enable */
3101 snd_soc_update_bits(codec, main_reg, 0x10, 0x10);
3102 /* Clk enable */
3103 snd_soc_update_bits(codec, main_reg, 0x20, 0x20);
3104 tavil_codec_idle_detect_control(codec, interp_idx,
3105 event);
3106 tavil_codec_hd2_control(tavil, interp_idx, event);
3107 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3108 event);
3109 tavil_config_compander(codec, interp_idx, event);
3110 }
3111 tavil->main_clk_users[interp_idx]++;
3112 }
3113
3114 if (SND_SOC_DAPM_EVENT_OFF(event)) {
3115 tavil->main_clk_users[interp_idx]--;
3116 if (tavil->main_clk_users[interp_idx] <= 0) {
3117 tavil->main_clk_users[interp_idx] = 0;
3118 tavil_config_compander(codec, interp_idx, event);
3119 tavil_codec_hphdelay_lutbypass(codec, interp_idx,
3120 event);
3121 tavil_codec_hd2_control(tavil, interp_idx, event);
3122 tavil_codec_idle_detect_control(codec, interp_idx,
3123 event);
3124 /* Clk Disable */
3125 snd_soc_update_bits(codec, main_reg, 0x20, 0x00);
3126 /* Reset enable and disable */
3127 snd_soc_update_bits(codec, main_reg, 0x40, 0x40);
3128 snd_soc_update_bits(codec, main_reg, 0x40, 0x00);
3129 /* Reset rate to 48K*/
3130 snd_soc_update_bits(codec, main_reg, 0x0F, 0x04);
3131 }
3132 }
3133
3134 dev_dbg(codec->dev, "%s event %d main_clk_users %d\n",
3135 __func__, event, tavil->main_clk_users[interp_idx]);
3136
3137 return tavil->main_clk_users[interp_idx];
3138}
3139EXPORT_SYMBOL(tavil_codec_enable_interp_clk);
3140
3141static int tavil_codec_set_idle_detect_thr(struct snd_soc_codec *codec,
3142 int interp, int path_type)
3143{
3144 int port_id[4] = { 0, 0, 0, 0 };
3145 int *port_ptr, num_ports;
3146 int bit_width = 0, i;
3147 int mux_reg, mux_reg_val;
3148 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3149 int dai_id, idle_thr;
3150
3151 if ((interp != INTERP_HPHL) && (interp != INTERP_HPHR))
3152 return 0;
3153
3154 if (!tavil->idle_det_cfg.hph_idle_detect_en)
3155 return 0;
3156
3157 port_ptr = &port_id[0];
3158 num_ports = 0;
3159
3160 /*
3161 * Read interpolator MUX input registers and find
3162 * which slimbus port is connected and store the port
3163 * numbers in port_id array.
3164 */
3165 if (path_type == INTERP_MIX_PATH) {
3166 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1 +
3167 2 * (interp - 1);
3168 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3169
3170 if ((mux_reg_val >= INTn_2_INP_SEL_RX0) &&
3171 (mux_reg_val < INTn_2_INP_SEL_PROXIMITY)) {
3172 *port_ptr++ = mux_reg_val +
3173 WCD934X_RX_PORT_START_NUMBER - 1;
3174 num_ports++;
3175 }
3176 }
3177
3178 if (path_type == INTERP_MAIN_PATH) {
3179 mux_reg = WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0 +
3180 2 * (interp - 1);
3181 mux_reg_val = snd_soc_read(codec, mux_reg) & 0x0f;
3182 i = WCD934X_INTERP_MUX_NUM_INPUTS;
3183
3184 while (i) {
3185 if ((mux_reg_val >= INTn_1_INP_SEL_RX0) &&
3186 (mux_reg_val <= INTn_1_INP_SEL_RX7)) {
3187 *port_ptr++ = mux_reg_val +
3188 WCD934X_RX_PORT_START_NUMBER -
3189 INTn_1_INP_SEL_RX0;
3190 num_ports++;
3191 }
3192 mux_reg_val = (snd_soc_read(codec, mux_reg) &
3193 0xf0) >> 4;
3194 mux_reg += 1;
3195 i--;
3196 }
3197 }
3198
3199 dev_dbg(codec->dev, "%s: num_ports: %d, ports[%d %d %d %d]\n",
3200 __func__, num_ports, port_id[0], port_id[1],
3201 port_id[2], port_id[3]);
3202
3203 i = 0;
3204 while (num_ports) {
3205 dai_id = tavil_find_playback_dai_id_for_port(port_id[i++],
3206 tavil);
3207
3208 if ((dai_id >= 0) && (dai_id < NUM_CODEC_DAIS)) {
3209 dev_dbg(codec->dev, "%s: dai_id: %d bit_width: %d\n",
3210 __func__, dai_id,
3211 tavil->dai[dai_id].bit_width);
3212
3213 if (tavil->dai[dai_id].bit_width > bit_width)
3214 bit_width = tavil->dai[dai_id].bit_width;
3215 }
3216
3217 num_ports--;
3218 }
3219
3220 switch (bit_width) {
3221 case 16:
3222 idle_thr = 0xff; /* F16 */
3223 break;
3224 case 24:
3225 case 32:
3226 idle_thr = 0x03; /* F22 */
3227 break;
3228 default:
3229 idle_thr = 0x00;
3230 break;
3231 }
3232
3233 dev_dbg(codec->dev, "%s: (new) idle_thr: %d, (cur) idle_thr: %d\n",
3234 __func__, idle_thr, tavil->idle_det_cfg.hph_idle_thr);
3235
3236 if ((tavil->idle_det_cfg.hph_idle_thr == 0) ||
3237 (idle_thr < tavil->idle_det_cfg.hph_idle_thr)) {
3238 snd_soc_write(codec, WCD934X_CDC_RX_IDLE_DET_CFG3, idle_thr);
3239 tavil->idle_det_cfg.hph_idle_thr = idle_thr;
3240 }
3241
3242 return 0;
3243}
3244
3245static int tavil_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
3246 struct snd_kcontrol *kcontrol,
3247 int event)
3248{
3249 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3250 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3251 u16 gain_reg, mix_reg;
3252 int offset_val = 0;
3253 int val = 0;
3254
3255 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3256 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3257 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3258 __func__, w->shift, w->name);
3259 return -EINVAL;
3260 };
3261
3262 gain_reg = WCD934X_CDC_RX0_RX_VOL_MIX_CTL +
3263 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3264 mix_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
3265 (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
3266
3267 if (w->shift == INTERP_SPKR1 || w->shift == INTERP_SPKR2)
3268 __tavil_codec_enable_swr(w, event);
3269
3270 switch (event) {
3271 case SND_SOC_DAPM_PRE_PMU:
3272 tavil_codec_set_idle_detect_thr(codec, w->shift,
3273 INTERP_MIX_PATH);
3274 tavil_codec_enable_interp_clk(codec, event, w->shift);
3275 /* Clk enable */
3276 snd_soc_update_bits(codec, mix_reg, 0x20, 0x20);
3277 break;
3278 case SND_SOC_DAPM_POST_PMU:
3279 if ((tavil->swr.spkr_gain_offset ==
3280 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3281 (tavil->comp_enabled[COMPANDER_7] ||
3282 tavil->comp_enabled[COMPANDER_8]) &&
3283 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3284 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3285 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3286 0x01, 0x01);
3287 snd_soc_update_bits(codec,
3288 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3289 0x01, 0x01);
3290 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3291 0x01, 0x01);
3292 snd_soc_update_bits(codec,
3293 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3294 0x01, 0x01);
3295 offset_val = -2;
3296 }
3297 val = snd_soc_read(codec, gain_reg);
3298 val += offset_val;
3299 snd_soc_write(codec, gain_reg, val);
3300 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3301 break;
3302 case SND_SOC_DAPM_POST_PMD:
3303 /* Clk Disable */
3304 snd_soc_update_bits(codec, mix_reg, 0x20, 0x00);
3305 tavil_codec_enable_interp_clk(codec, event, w->shift);
3306 /* Reset enable and disable */
3307 snd_soc_update_bits(codec, mix_reg, 0x40, 0x40);
3308 snd_soc_update_bits(codec, mix_reg, 0x40, 0x00);
3309
3310 if ((tavil->swr.spkr_gain_offset ==
3311 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3312 (tavil->comp_enabled[COMPANDER_7] ||
3313 tavil->comp_enabled[COMPANDER_8]) &&
3314 (gain_reg == WCD934X_CDC_RX7_RX_VOL_MIX_CTL ||
3315 gain_reg == WCD934X_CDC_RX8_RX_VOL_MIX_CTL)) {
3316 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3317 0x01, 0x00);
3318 snd_soc_update_bits(codec,
3319 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3320 0x01, 0x00);
3321 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3322 0x01, 0x00);
3323 snd_soc_update_bits(codec,
3324 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3325 0x01, 0x00);
3326 offset_val = 2;
3327 val = snd_soc_read(codec, gain_reg);
3328 val += offset_val;
3329 snd_soc_write(codec, gain_reg, val);
3330 }
3331 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3332 break;
3333 };
3334 dev_dbg(codec->dev, "%s event %d name %s\n", __func__, event, w->name);
3335
3336 return 0;
3337}
3338
3339/**
3340 * tavil_get_dsd_config - Get pointer to dsd config structure
3341 *
3342 * @codec: pointer to snd_soc_codec structure
3343 *
3344 * Returns pointer to tavil_dsd_config structure
3345 */
3346struct tavil_dsd_config *tavil_get_dsd_config(struct snd_soc_codec *codec)
3347{
3348 struct tavil_priv *tavil;
3349
3350 if (!codec)
3351 return NULL;
3352
3353 tavil = snd_soc_codec_get_drvdata(codec);
3354
3355 if (!tavil)
3356 return NULL;
3357
3358 return tavil->dsd_config;
3359}
3360EXPORT_SYMBOL(tavil_get_dsd_config);
3361
3362static int tavil_codec_enable_main_path(struct snd_soc_dapm_widget *w,
3363 struct snd_kcontrol *kcontrol,
3364 int event)
3365{
3366 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3367 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3368 u16 gain_reg;
3369 u16 reg;
3370 int val;
3371 int offset_val = 0;
3372
3373 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
3374
3375 if (w->shift >= WCD934X_NUM_INTERPOLATORS ||
3376 w->shift == INTERP_LO3_NA || w->shift == INTERP_LO4_NA) {
3377 dev_err(codec->dev, "%s: Invalid Interpolator value %d for name %s\n",
3378 __func__, w->shift, w->name);
3379 return -EINVAL;
3380 };
3381
3382 reg = WCD934X_CDC_RX0_RX_PATH_CTL + (w->shift *
3383 WCD934X_RX_PATH_CTL_OFFSET);
3384 gain_reg = WCD934X_CDC_RX0_RX_VOL_CTL + (w->shift *
3385 WCD934X_RX_PATH_CTL_OFFSET);
3386
3387 switch (event) {
3388 case SND_SOC_DAPM_PRE_PMU:
3389 tavil_codec_set_idle_detect_thr(codec, w->shift,
3390 INTERP_MAIN_PATH);
3391 tavil_codec_enable_interp_clk(codec, event, w->shift);
3392 break;
3393 case SND_SOC_DAPM_POST_PMU:
3394 /* apply gain after int clk is enabled */
3395 if ((tavil->swr.spkr_gain_offset ==
3396 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3397 (tavil->comp_enabled[COMPANDER_7] ||
3398 tavil->comp_enabled[COMPANDER_8]) &&
3399 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3400 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3401 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3402 0x01, 0x01);
3403 snd_soc_update_bits(codec,
3404 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3405 0x01, 0x01);
3406 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3407 0x01, 0x01);
3408 snd_soc_update_bits(codec,
3409 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3410 0x01, 0x01);
3411 offset_val = -2;
3412 }
3413 val = snd_soc_read(codec, gain_reg);
3414 val += offset_val;
3415 snd_soc_write(codec, gain_reg, val);
3416 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3417 break;
3418 case SND_SOC_DAPM_POST_PMD:
3419 tavil_codec_enable_interp_clk(codec, event, w->shift);
3420
3421 if ((tavil->swr.spkr_gain_offset ==
3422 WCD934X_RX_GAIN_OFFSET_M1P5_DB) &&
3423 (tavil->comp_enabled[COMPANDER_7] ||
3424 tavil->comp_enabled[COMPANDER_8]) &&
3425 (gain_reg == WCD934X_CDC_RX7_RX_VOL_CTL ||
3426 gain_reg == WCD934X_CDC_RX8_RX_VOL_CTL)) {
3427 snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_SEC1,
3428 0x01, 0x00);
3429 snd_soc_update_bits(codec,
3430 WCD934X_CDC_RX7_RX_PATH_MIX_SEC0,
3431 0x01, 0x00);
3432 snd_soc_update_bits(codec, WCD934X_CDC_RX8_RX_PATH_SEC1,
3433 0x01, 0x00);
3434 snd_soc_update_bits(codec,
3435 WCD934X_CDC_RX8_RX_PATH_MIX_SEC0,
3436 0x01, 0x00);
3437 offset_val = 2;
3438 val = snd_soc_read(codec, gain_reg);
3439 val += offset_val;
3440 snd_soc_write(codec, gain_reg, val);
3441 }
3442 tavil_codec_config_ear_spkr_gain(codec, event, gain_reg);
3443 break;
3444 };
3445
3446 return 0;
3447}
3448
3449static int tavil_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
3450 struct snd_kcontrol *kcontrol, int event)
3451{
3452 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3453
3454 dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
3455
3456 switch (event) {
3457 case SND_SOC_DAPM_POST_PMU: /* fall through */
3458 case SND_SOC_DAPM_PRE_PMD:
3459 if (strnstr(w->name, "IIR0", sizeof("IIR0"))) {
3460 snd_soc_write(codec,
3461 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
3462 snd_soc_read(codec,
3463 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL));
3464 snd_soc_write(codec,
3465 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL,
3466 snd_soc_read(codec,
3467 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL));
3468 snd_soc_write(codec,
3469 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL,
3470 snd_soc_read(codec,
3471 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL));
3472 snd_soc_write(codec,
3473 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL,
3474 snd_soc_read(codec,
3475 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL));
3476 } else {
3477 snd_soc_write(codec,
3478 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
3479 snd_soc_read(codec,
3480 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL));
3481 snd_soc_write(codec,
3482 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL,
3483 snd_soc_read(codec,
3484 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL));
3485 snd_soc_write(codec,
3486 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL,
3487 snd_soc_read(codec,
3488 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL));
3489 }
3490 break;
3491 }
3492 return 0;
3493}
3494
3495static int tavil_codec_find_amic_input(struct snd_soc_codec *codec,
3496 int adc_mux_n)
3497{
3498 u16 mask, shift, adc_mux_in_reg;
3499 u16 amic_mux_sel_reg;
3500 bool is_amic;
3501
3502 if (adc_mux_n < 0 || adc_mux_n > WCD934X_MAX_VALID_ADC_MUX ||
3503 adc_mux_n == WCD934X_INVALID_ADC_MUX)
3504 return 0;
3505
3506 if (adc_mux_n < 3) {
3507 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3508 adc_mux_n;
3509 mask = 0x03;
3510 shift = 0;
3511 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3512 2 * adc_mux_n;
3513 } else if (adc_mux_n < 4) {
3514 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3515 mask = 0x03;
3516 shift = 0;
3517 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3518 2 * adc_mux_n;
3519 } else if (adc_mux_n < 7) {
3520 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3521 (adc_mux_n - 4);
3522 mask = 0x0C;
3523 shift = 2;
3524 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3525 adc_mux_n - 4;
3526 } else if (adc_mux_n < 8) {
3527 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3528 mask = 0x0C;
3529 shift = 2;
3530 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3531 adc_mux_n - 4;
3532 } else if (adc_mux_n < 12) {
3533 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
3534 ((adc_mux_n == 8) ? (adc_mux_n - 8) :
3535 (adc_mux_n - 9));
3536 mask = 0x30;
3537 shift = 4;
3538 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3539 adc_mux_n - 4;
3540 } else if (adc_mux_n < 13) {
3541 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
3542 mask = 0x30;
3543 shift = 4;
3544 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3545 adc_mux_n - 4;
3546 } else {
3547 adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1;
3548 mask = 0xC0;
3549 shift = 6;
3550 amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3551 adc_mux_n - 4;
3552 }
3553
3554 is_amic = (((snd_soc_read(codec, adc_mux_in_reg) & mask) >> shift)
3555 == 1);
3556 if (!is_amic)
3557 return 0;
3558
3559 return snd_soc_read(codec, amic_mux_sel_reg) & 0x07;
3560}
3561
3562static void tavil_codec_set_tx_hold(struct snd_soc_codec *codec,
3563 u16 amic_reg, bool set)
3564{
3565 u8 mask = 0x20;
3566 u8 val;
3567
3568 if (amic_reg == WCD934X_ANA_AMIC1 ||
3569 amic_reg == WCD934X_ANA_AMIC3)
3570 mask = 0x40;
3571
3572 val = set ? mask : 0x00;
3573
3574 switch (amic_reg) {
3575 case WCD934X_ANA_AMIC1:
3576 case WCD934X_ANA_AMIC2:
3577 snd_soc_update_bits(codec, WCD934X_ANA_AMIC2, mask, val);
3578 break;
3579 case WCD934X_ANA_AMIC3:
3580 case WCD934X_ANA_AMIC4:
3581 snd_soc_update_bits(codec, WCD934X_ANA_AMIC4, mask, val);
3582 break;
3583 default:
3584 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3585 __func__, amic_reg);
3586 break;
3587 }
3588}
3589
3590static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w,
3591 struct snd_kcontrol *kcontrol, int event)
3592{
3593 int adc_mux_n = w->shift;
3594 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3595 int amic_n;
3596 u16 amic_reg;
3597
3598 dev_dbg(codec->dev, "%s: event: %d\n", __func__, event);
3599
3600 switch (event) {
3601 case SND_SOC_DAPM_POST_PMU:
3602 amic_n = tavil_codec_find_amic_input(codec, adc_mux_n);
3603 if (amic_n) {
3604 amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1;
3605 tavil_codec_set_tx_hold(codec, amic_reg, false);
3606 }
3607 break;
3608 default:
3609 break;
3610 }
3611
3612 return 0;
3613}
3614
3615static u16 tavil_codec_get_amic_pwlvl_reg(struct snd_soc_codec *codec, int amic)
3616{
3617 u16 pwr_level_reg = 0;
3618
3619 switch (amic) {
3620 case 1:
3621 case 2:
3622 pwr_level_reg = WCD934X_ANA_AMIC1;
3623 break;
3624
3625 case 3:
3626 case 4:
3627 pwr_level_reg = WCD934X_ANA_AMIC3;
3628 break;
3629 default:
3630 dev_dbg(codec->dev, "%s: invalid amic: %d\n",
3631 __func__, amic);
3632 break;
3633 }
3634
3635 return pwr_level_reg;
3636}
3637
3638#define TX_HPF_CUT_OFF_FREQ_MASK 0x60
3639#define CF_MIN_3DB_4HZ 0x0
3640#define CF_MIN_3DB_75HZ 0x1
3641#define CF_MIN_3DB_150HZ 0x2
3642
3643static void tavil_tx_hpf_corner_freq_callback(struct work_struct *work)
3644{
3645 struct delayed_work *hpf_delayed_work;
3646 struct hpf_work *hpf_work;
3647 struct tavil_priv *tavil;
3648 struct snd_soc_codec *codec;
3649 u16 dec_cfg_reg, amic_reg, go_bit_reg;
3650 u8 hpf_cut_off_freq;
3651 int amic_n;
3652
3653 hpf_delayed_work = to_delayed_work(work);
3654 hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
3655 tavil = hpf_work->tavil;
3656 codec = tavil->codec;
3657 hpf_cut_off_freq = hpf_work->hpf_cut_off_freq;
3658
3659 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * hpf_work->decimator;
3660 go_bit_reg = dec_cfg_reg + 7;
3661
3662 dev_dbg(codec->dev, "%s: decimator %u hpf_cut_of_freq 0x%x\n",
3663 __func__, hpf_work->decimator, hpf_cut_off_freq);
3664
3665 amic_n = tavil_codec_find_amic_input(codec, hpf_work->decimator);
3666 if (amic_n) {
3667 amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1;
3668 tavil_codec_set_tx_hold(codec, amic_reg, false);
3669 }
3670 snd_soc_update_bits(codec, dec_cfg_reg, TX_HPF_CUT_OFF_FREQ_MASK,
3671 hpf_cut_off_freq << 5);
3672 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x02);
3673 /* Minimum 1 clk cycle delay is required as per HW spec */
3674 usleep_range(1000, 1010);
3675 snd_soc_update_bits(codec, go_bit_reg, 0x02, 0x00);
3676}
3677
3678static void tavil_tx_mute_update_callback(struct work_struct *work)
3679{
3680 struct tx_mute_work *tx_mute_dwork;
3681 struct tavil_priv *tavil;
3682 struct delayed_work *delayed_work;
3683 struct snd_soc_codec *codec;
3684 u16 tx_vol_ctl_reg, hpf_gate_reg;
3685
3686 delayed_work = to_delayed_work(work);
3687 tx_mute_dwork = container_of(delayed_work, struct tx_mute_work, dwork);
3688 tavil = tx_mute_dwork->tavil;
3689 codec = tavil->codec;
3690
3691 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
3692 16 * tx_mute_dwork->decimator;
3693 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 +
3694 16 * tx_mute_dwork->decimator;
3695 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
3696}
3697
3698static int tavil_codec_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
3699 struct snd_kcontrol *kcontrol, int event)
3700{
3701 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3702 u16 sidetone_reg;
3703
3704 dev_dbg(codec->dev, "%s %d %d\n", __func__, event, w->shift);
3705 sidetone_reg = WCD934X_CDC_RX0_RX_PATH_CFG1 + 0x14*(w->shift);
3706
3707 switch (event) {
3708 case SND_SOC_DAPM_PRE_PMU:
3709 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
3710 __tavil_codec_enable_swr(w, event);
3711 tavil_codec_enable_interp_clk(codec, event, w->shift);
3712 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x10);
3713 break;
3714 case SND_SOC_DAPM_POST_PMD:
3715 snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x00);
3716 tavil_codec_enable_interp_clk(codec, event, w->shift);
3717 if (!strcmp(w->name, "RX INT7 MIX2 INP"))
3718 __tavil_codec_enable_swr(w, event);
3719 break;
3720 default:
3721 break;
3722 };
3723 return 0;
3724}
3725
3726static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
3727 struct snd_kcontrol *kcontrol, int event)
3728{
3729 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3730 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
3731 unsigned int decimator;
3732 char *dec_adc_mux_name = NULL;
3733 char *widget_name = NULL;
3734 char *wname;
3735 int ret = 0, amic_n;
3736 u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
3737 u16 tx_gain_ctl_reg;
3738 char *dec;
3739 u8 hpf_cut_off_freq;
3740
3741 dev_dbg(codec->dev, "%s %d\n", __func__, event);
3742
3743 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
3744 if (!widget_name)
3745 return -ENOMEM;
3746
3747 wname = widget_name;
3748 dec_adc_mux_name = strsep(&widget_name, " ");
3749 if (!dec_adc_mux_name) {
3750 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
3751 __func__, w->name);
3752 ret = -EINVAL;
3753 goto out;
3754 }
3755 dec_adc_mux_name = widget_name;
3756
3757 dec = strpbrk(dec_adc_mux_name, "012345678");
3758 if (!dec) {
3759 dev_err(codec->dev, "%s: decimator index not found\n",
3760 __func__);
3761 ret = -EINVAL;
3762 goto out;
3763 }
3764
3765 ret = kstrtouint(dec, 10, &decimator);
3766 if (ret < 0) {
3767 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
3768 __func__, wname);
3769 ret = -EINVAL;
3770 goto out;
3771 }
3772
3773 dev_dbg(codec->dev, "%s(): widget = %s decimator = %u\n", __func__,
3774 w->name, decimator);
3775
3776 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator;
3777 hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
3778 dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
3779 tx_gain_ctl_reg = WCD934X_CDC_TX0_TX_VOL_CTL + 16 * decimator;
3780
3781 switch (event) {
3782 case SND_SOC_DAPM_PRE_PMU:
3783 amic_n = tavil_codec_find_amic_input(codec, decimator);
3784 if (amic_n)
3785 pwr_level_reg = tavil_codec_get_amic_pwlvl_reg(codec,
3786 amic_n);
3787
3788 if (pwr_level_reg) {
3789 switch ((snd_soc_read(codec, pwr_level_reg) &
3790 WCD934X_AMIC_PWR_LVL_MASK) >>
3791 WCD934X_AMIC_PWR_LVL_SHIFT) {
3792 case WCD934X_AMIC_PWR_LEVEL_LP:
3793 snd_soc_update_bits(codec, dec_cfg_reg,
3794 WCD934X_DEC_PWR_LVL_MASK,
3795 WCD934X_DEC_PWR_LVL_LP);
3796 break;
3797
3798 case WCD934X_AMIC_PWR_LEVEL_HP:
3799 snd_soc_update_bits(codec, dec_cfg_reg,
3800 WCD934X_DEC_PWR_LVL_MASK,
3801 WCD934X_DEC_PWR_LVL_HP);
3802 break;
3803 case WCD934X_AMIC_PWR_LEVEL_DEFAULT:
3804 default:
3805 snd_soc_update_bits(codec, dec_cfg_reg,
3806 WCD934X_DEC_PWR_LVL_MASK,
3807 WCD934X_DEC_PWR_LVL_DF);
3808 break;
3809 }
3810 }
3811 /* Enable TX PGA Mute */
3812 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
3813 break;
3814 case SND_SOC_DAPM_POST_PMU:
3815 hpf_cut_off_freq = (snd_soc_read(codec, dec_cfg_reg) &
3816 TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
3817
3818 tavil->tx_hpf_work[decimator].hpf_cut_off_freq =
3819 hpf_cut_off_freq;
3820 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
3821 snd_soc_update_bits(codec, dec_cfg_reg,
3822 TX_HPF_CUT_OFF_FREQ_MASK,
3823 CF_MIN_3DB_150HZ << 5);
3824 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x02);
3825 /*
3826 * Minimum 1 clk cycle delay is required as per
3827 * HW spec.
3828 */
3829 usleep_range(1000, 1010);
3830 snd_soc_update_bits(codec, hpf_gate_reg, 0x02, 0x00);
3831 }
3832 /* schedule work queue to Remove Mute */
3833 schedule_delayed_work(&tavil->tx_mute_dwork[decimator].dwork,
3834 msecs_to_jiffies(tx_unmute_delay));
3835 if (tavil->tx_hpf_work[decimator].hpf_cut_off_freq !=
3836 CF_MIN_3DB_150HZ)
3837 schedule_delayed_work(
3838 &tavil->tx_hpf_work[decimator].dwork,
3839 msecs_to_jiffies(300));
3840 /* apply gain after decimator is enabled */
3841 snd_soc_write(codec, tx_gain_ctl_reg,
3842 snd_soc_read(codec, tx_gain_ctl_reg));
3843 break;
3844 case SND_SOC_DAPM_PRE_PMD:
3845 hpf_cut_off_freq =
3846 tavil->tx_hpf_work[decimator].hpf_cut_off_freq;
3847 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x10);
3848 if (cancel_delayed_work_sync(
3849 &tavil->tx_hpf_work[decimator].dwork)) {
3850 if (hpf_cut_off_freq != CF_MIN_3DB_150HZ) {
3851 snd_soc_update_bits(codec, dec_cfg_reg,
3852 TX_HPF_CUT_OFF_FREQ_MASK,
3853 hpf_cut_off_freq << 5);
3854 snd_soc_update_bits(codec, hpf_gate_reg,
3855 0x02, 0x02);
3856 /*
3857 * Minimum 1 clk cycle delay is required as per
3858 * HW spec.
3859 */
3860 usleep_range(1000, 1010);
3861 snd_soc_update_bits(codec, hpf_gate_reg,
3862 0x02, 0x00);
3863 }
3864 }
3865 cancel_delayed_work_sync(
3866 &tavil->tx_mute_dwork[decimator].dwork);
3867 break;
3868 case SND_SOC_DAPM_POST_PMD:
3869 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
3870 snd_soc_update_bits(codec, dec_cfg_reg,
3871 WCD934X_DEC_PWR_LVL_MASK,
3872 WCD934X_DEC_PWR_LVL_DF);
3873 break;
3874 };
3875out:
3876 kfree(wname);
3877 return ret;
3878}
3879
3880static u32 tavil_get_dmic_sample_rate(struct snd_soc_codec *codec,
3881 unsigned int dmic,
3882 struct wcd9xxx_pdata *pdata)
3883{
3884 u8 tx_stream_fs;
3885 u8 adc_mux_index = 0, adc_mux_sel = 0;
3886 bool dec_found = false;
3887 u16 adc_mux_ctl_reg, tx_fs_reg;
3888 u32 dmic_fs;
3889
3890 while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) {
3891 if (adc_mux_index < 4) {
3892 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
3893 (adc_mux_index * 2);
3894 } else if (adc_mux_index < WCD934X_INVALID_ADC_MUX) {
3895 adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
3896 adc_mux_index - 4;
3897 } else if (adc_mux_index == WCD934X_INVALID_ADC_MUX) {
3898 ++adc_mux_index;
3899 continue;
3900 }
3901 adc_mux_sel = ((snd_soc_read(codec, adc_mux_ctl_reg) &
3902 0xF8) >> 3) - 1;
3903
3904 if (adc_mux_sel == dmic) {
3905 dec_found = true;
3906 break;
3907 }
3908
3909 ++adc_mux_index;
3910 }
3911
3912 if (dec_found && adc_mux_index <= 8) {
3913 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index);
3914 tx_stream_fs = snd_soc_read(codec, tx_fs_reg) & 0x0F;
3915 if (tx_stream_fs <= 4) {
3916 if (pdata->dmic_sample_rate <=
3917 WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ)
3918 dmic_fs = pdata->dmic_sample_rate;
3919 else
3920 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ;
3921 } else
3922 dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
3923 } else {
3924 dmic_fs = pdata->dmic_sample_rate;
3925 }
3926
3927 return dmic_fs;
3928}
3929
3930static u8 tavil_get_dmic_clk_val(struct snd_soc_codec *codec,
3931 u32 mclk_rate, u32 dmic_clk_rate)
3932{
3933 u32 div_factor;
3934 u8 dmic_ctl_val;
3935
3936 dev_dbg(codec->dev,
3937 "%s: mclk_rate = %d, dmic_sample_rate = %d\n",
3938 __func__, mclk_rate, dmic_clk_rate);
3939
3940 /* Default value to return in case of error */
3941 if (mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
3942 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
3943 else
3944 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
3945
3946 if (dmic_clk_rate == 0) {
3947 dev_err(codec->dev,
3948 "%s: dmic_sample_rate cannot be 0\n",
3949 __func__);
3950 goto done;
3951 }
3952
3953 div_factor = mclk_rate / dmic_clk_rate;
3954 switch (div_factor) {
3955 case 2:
3956 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
3957 break;
3958 case 3:
3959 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
3960 break;
3961 case 4:
3962 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_4;
3963 break;
3964 case 6:
3965 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_6;
3966 break;
3967 case 8:
3968 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_8;
3969 break;
3970 case 16:
3971 dmic_ctl_val = WCD934X_DMIC_CLK_DIV_16;
3972 break;
3973 default:
3974 dev_err(codec->dev,
3975 "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
3976 __func__, div_factor, mclk_rate, dmic_clk_rate);
3977 break;
3978 }
3979
3980done:
3981 return dmic_ctl_val;
3982}
3983
3984static int tavil_codec_enable_adc(struct snd_soc_dapm_widget *w,
3985 struct snd_kcontrol *kcontrol, int event)
3986{
3987 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
3988
3989 dev_dbg(codec->dev, "%s: event:%d\n", __func__, event);
3990
3991 switch (event) {
3992 case SND_SOC_DAPM_PRE_PMU:
3993 tavil_codec_set_tx_hold(codec, w->reg, true);
3994 break;
3995 default:
3996 break;
3997 }
3998
3999 return 0;
4000}
4001
4002static int tavil_codec_enable_dmic(struct snd_soc_dapm_widget *w,
4003 struct snd_kcontrol *kcontrol, int event)
4004{
4005 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4006 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4007 struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);
4008 u8 dmic_clk_en = 0x01;
4009 u16 dmic_clk_reg;
4010 s32 *dmic_clk_cnt;
4011 u8 dmic_rate_val, dmic_rate_shift = 1;
4012 unsigned int dmic;
4013 u32 dmic_sample_rate;
4014 int ret;
4015 char *wname;
4016
4017 wname = strpbrk(w->name, "012345");
4018 if (!wname) {
4019 dev_err(codec->dev, "%s: widget not found\n", __func__);
4020 return -EINVAL;
4021 }
4022
4023 ret = kstrtouint(wname, 10, &dmic);
4024 if (ret < 0) {
4025 dev_err(codec->dev, "%s: Invalid DMIC line on the codec\n",
4026 __func__);
4027 return -EINVAL;
4028 }
4029
4030 switch (dmic) {
4031 case 0:
4032 case 1:
4033 dmic_clk_cnt = &(tavil->dmic_0_1_clk_cnt);
4034 dmic_clk_reg = WCD934X_CPE_SS_DMIC0_CTL;
4035 break;
4036 case 2:
4037 case 3:
4038 dmic_clk_cnt = &(tavil->dmic_2_3_clk_cnt);
4039 dmic_clk_reg = WCD934X_CPE_SS_DMIC1_CTL;
4040 break;
4041 case 4:
4042 case 5:
4043 dmic_clk_cnt = &(tavil->dmic_4_5_clk_cnt);
4044 dmic_clk_reg = WCD934X_CPE_SS_DMIC2_CTL;
4045 break;
4046 default:
4047 dev_err(codec->dev, "%s: Invalid DMIC Selection\n",
4048 __func__);
4049 return -EINVAL;
4050 };
4051 dev_dbg(codec->dev, "%s: event %d DMIC%d dmic_clk_cnt %d\n",
4052 __func__, event, dmic, *dmic_clk_cnt);
4053
4054 switch (event) {
4055 case SND_SOC_DAPM_PRE_PMU:
4056 dmic_sample_rate = tavil_get_dmic_sample_rate(codec, dmic,
4057 pdata);
4058 dmic_rate_val =
4059 tavil_get_dmic_clk_val(codec,
4060 pdata->mclk_rate,
4061 dmic_sample_rate);
4062
4063 (*dmic_clk_cnt)++;
4064 if (*dmic_clk_cnt == 1) {
4065 snd_soc_update_bits(codec, dmic_clk_reg,
4066 0x07 << dmic_rate_shift,
4067 dmic_rate_val << dmic_rate_shift);
4068 snd_soc_update_bits(codec, dmic_clk_reg,
4069 dmic_clk_en, dmic_clk_en);
4070 }
4071
4072 break;
4073 case SND_SOC_DAPM_POST_PMD:
4074 dmic_rate_val =
4075 tavil_get_dmic_clk_val(codec,
4076 pdata->mclk_rate,
4077 pdata->mad_dmic_sample_rate);
4078 (*dmic_clk_cnt)--;
4079 if (*dmic_clk_cnt == 0) {
4080 snd_soc_update_bits(codec, dmic_clk_reg,
4081 dmic_clk_en, 0);
4082 snd_soc_update_bits(codec, dmic_clk_reg,
4083 0x07 << dmic_rate_shift,
4084 dmic_rate_val << dmic_rate_shift);
4085 }
4086 break;
4087 };
4088
4089 return 0;
4090}
4091
4092/*
4093 * tavil_mbhc_micb_adjust_voltage: adjust specific micbias voltage
4094 * @codec: handle to snd_soc_codec *
4095 * @req_volt: micbias voltage to be set
4096 * @micb_num: micbias to be set, e.g. micbias1 or micbias2
4097 *
4098 * return 0 if adjustment is success or error code in case of failure
4099 */
4100int tavil_mbhc_micb_adjust_voltage(struct snd_soc_codec *codec,
4101 int req_volt, int micb_num)
4102{
4103 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4104 int cur_vout_ctl, req_vout_ctl;
4105 int micb_reg, micb_val, micb_en;
4106 int ret = 0;
4107
4108 switch (micb_num) {
4109 case MIC_BIAS_1:
4110 micb_reg = WCD934X_ANA_MICB1;
4111 break;
4112 case MIC_BIAS_2:
4113 micb_reg = WCD934X_ANA_MICB2;
4114 break;
4115 case MIC_BIAS_3:
4116 micb_reg = WCD934X_ANA_MICB3;
4117 break;
4118 case MIC_BIAS_4:
4119 micb_reg = WCD934X_ANA_MICB4;
4120 break;
4121 default:
4122 return -EINVAL;
4123 }
4124 mutex_lock(&tavil->micb_lock);
4125
4126 /*
4127 * If requested micbias voltage is same as current micbias
4128 * voltage, then just return. Otherwise, adjust voltage as
4129 * per requested value. If micbias is already enabled, then
4130 * to avoid slow micbias ramp-up or down enable pull-up
4131 * momentarily, change the micbias value and then re-enable
4132 * micbias.
4133 */
4134 micb_val = snd_soc_read(codec, micb_reg);
4135 micb_en = (micb_val & 0xC0) >> 6;
4136 cur_vout_ctl = micb_val & 0x3F;
4137
4138 req_vout_ctl = wcd934x_get_micb_vout_ctl_val(req_volt);
4139 if (IS_ERR_VALUE(req_vout_ctl)) {
4140 ret = -EINVAL;
4141 goto exit;
4142 }
4143 if (cur_vout_ctl == req_vout_ctl) {
4144 ret = 0;
4145 goto exit;
4146 }
4147
4148 dev_dbg(codec->dev, "%s: micb_num: %d, cur_mv: %d, req_mv: %d, micb_en: %d\n",
4149 __func__, micb_num, WCD_VOUT_CTL_TO_MICB(cur_vout_ctl),
4150 req_volt, micb_en);
4151
4152 if (micb_en == 0x1)
4153 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4154
4155 snd_soc_update_bits(codec, micb_reg, 0x3F, req_vout_ctl);
4156
4157 if (micb_en == 0x1) {
4158 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4159 /*
4160 * Add 2ms delay as per HW requirement after enabling
4161 * micbias
4162 */
4163 usleep_range(2000, 2100);
4164 }
4165exit:
4166 mutex_unlock(&tavil->micb_lock);
4167 return ret;
4168}
4169EXPORT_SYMBOL(tavil_mbhc_micb_adjust_voltage);
4170
4171/*
4172 * tavil_micbias_control: enable/disable micbias
4173 * @codec: handle to snd_soc_codec *
4174 * @micb_num: micbias to be enabled/disabled, e.g. micbias1 or micbias2
4175 * @req: control requested, enable/disable or pullup enable/disable
4176 * @is_dapm: triggered by dapm or not
4177 *
4178 * return 0 if control is success or error code in case of failure
4179 */
4180int tavil_micbias_control(struct snd_soc_codec *codec,
4181 int micb_num, int req, bool is_dapm)
4182{
4183 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4184 int micb_index = micb_num - 1;
4185 u16 micb_reg;
4186 int pre_off_event = 0, post_off_event = 0;
4187 int post_on_event = 0, post_dapm_off = 0;
4188 int post_dapm_on = 0;
4189
4190 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4191 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4192 __func__, micb_index);
4193 return -EINVAL;
4194 }
4195
4196 switch (micb_num) {
4197 case MIC_BIAS_1:
4198 micb_reg = WCD934X_ANA_MICB1;
4199 break;
4200 case MIC_BIAS_2:
4201 micb_reg = WCD934X_ANA_MICB2;
4202 pre_off_event = WCD_EVENT_PRE_MICBIAS_2_OFF;
4203 post_off_event = WCD_EVENT_POST_MICBIAS_2_OFF;
4204 post_on_event = WCD_EVENT_POST_MICBIAS_2_ON;
4205 post_dapm_on = WCD_EVENT_POST_DAPM_MICBIAS_2_ON;
4206 post_dapm_off = WCD_EVENT_POST_DAPM_MICBIAS_2_OFF;
4207 break;
4208 case MIC_BIAS_3:
4209 micb_reg = WCD934X_ANA_MICB3;
4210 break;
4211 case MIC_BIAS_4:
4212 micb_reg = WCD934X_ANA_MICB4;
4213 break;
4214 default:
4215 dev_err(codec->dev, "%s: Invalid micbias number: %d\n",
4216 __func__, micb_num);
4217 return -EINVAL;
4218 }
4219 mutex_lock(&tavil->micb_lock);
4220
4221 switch (req) {
4222 case MICB_PULLUP_ENABLE:
4223 tavil->pullup_ref[micb_index]++;
4224 if ((tavil->pullup_ref[micb_index] == 1) &&
4225 (tavil->micb_ref[micb_index] == 0))
4226 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4227 break;
4228 case MICB_PULLUP_DISABLE:
4229 if (tavil->pullup_ref[micb_index] > 0)
4230 tavil->pullup_ref[micb_index]--;
4231 if ((tavil->pullup_ref[micb_index] == 0) &&
4232 (tavil->micb_ref[micb_index] == 0))
4233 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4234 break;
4235 case MICB_ENABLE:
4236 tavil->micb_ref[micb_index]++;
4237 if (tavil->micb_ref[micb_index] == 1) {
4238 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x40);
4239 if (post_on_event && tavil->mbhc)
4240 blocking_notifier_call_chain(
4241 &tavil->mbhc->notifier,
4242 post_on_event,
4243 &tavil->mbhc->wcd_mbhc);
4244 }
4245 if (is_dapm && post_dapm_on && tavil->mbhc)
4246 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4247 post_dapm_on, &tavil->mbhc->wcd_mbhc);
4248 break;
4249 case MICB_DISABLE:
4250 if (tavil->micb_ref[micb_index] > 0)
4251 tavil->micb_ref[micb_index]--;
4252 if ((tavil->micb_ref[micb_index] == 0) &&
4253 (tavil->pullup_ref[micb_index] > 0))
4254 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x80);
4255 else if ((tavil->micb_ref[micb_index] == 0) &&
4256 (tavil->pullup_ref[micb_index] == 0)) {
4257 if (pre_off_event && tavil->mbhc)
4258 blocking_notifier_call_chain(
4259 &tavil->mbhc->notifier,
4260 pre_off_event,
4261 &tavil->mbhc->wcd_mbhc);
4262 snd_soc_update_bits(codec, micb_reg, 0xC0, 0x00);
4263 if (post_off_event && tavil->mbhc)
4264 blocking_notifier_call_chain(
4265 &tavil->mbhc->notifier,
4266 post_off_event,
4267 &tavil->mbhc->wcd_mbhc);
4268 }
4269 if (is_dapm && post_dapm_off && tavil->mbhc)
4270 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4271 post_dapm_off, &tavil->mbhc->wcd_mbhc);
4272 break;
4273 };
4274
4275 dev_dbg(codec->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
4276 __func__, micb_num, tavil->micb_ref[micb_index],
4277 tavil->pullup_ref[micb_index]);
4278
4279 mutex_unlock(&tavil->micb_lock);
4280
4281 return 0;
4282}
4283EXPORT_SYMBOL(tavil_micbias_control);
4284
4285static int __tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4286 int event)
4287{
4288 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4289 int micb_num;
4290
4291 dev_dbg(codec->dev, "%s: wname: %s, event: %d\n",
4292 __func__, w->name, event);
4293
4294 if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
4295 micb_num = MIC_BIAS_1;
4296 else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
4297 micb_num = MIC_BIAS_2;
4298 else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
4299 micb_num = MIC_BIAS_3;
4300 else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4")))
4301 micb_num = MIC_BIAS_4;
4302 else
4303 return -EINVAL;
4304
4305 switch (event) {
4306 case SND_SOC_DAPM_PRE_PMU:
4307 /*
4308 * MIC BIAS can also be requested by MBHC,
4309 * so use ref count to handle micbias pullup
4310 * and enable requests
4311 */
4312 tavil_micbias_control(codec, micb_num, MICB_ENABLE, true);
4313 break;
4314 case SND_SOC_DAPM_POST_PMU:
4315 /* wait for cnp time */
4316 usleep_range(1000, 1100);
4317 break;
4318 case SND_SOC_DAPM_POST_PMD:
4319 tavil_micbias_control(codec, micb_num, MICB_DISABLE, true);
4320 break;
4321 };
4322
4323 return 0;
4324}
4325
4326/*
4327 * tavil_codec_enable_standalone_micbias - enable micbias standalone
4328 * @codec: pointer to codec instance
4329 * @micb_num: number of micbias to be enabled
4330 * @enable: true to enable micbias or false to disable
4331 *
4332 * This function is used to enable micbias (1, 2, 3 or 4) during
4333 * standalone independent of whether TX use-case is running or not
4334 *
4335 * Return: error code in case of failure or 0 for success
4336 */
4337int tavil_codec_enable_standalone_micbias(struct snd_soc_codec *codec,
4338 int micb_num,
4339 bool enable)
4340{
4341 const char * const micb_names[] = {
4342 DAPM_MICBIAS1_STANDALONE, DAPM_MICBIAS2_STANDALONE,
4343 DAPM_MICBIAS3_STANDALONE, DAPM_MICBIAS4_STANDALONE
4344 };
4345 int micb_index = micb_num - 1;
4346 int rc;
4347
4348 if (!codec) {
4349 pr_err("%s: Codec memory is NULL\n", __func__);
4350 return -EINVAL;
4351 }
4352
4353 if ((micb_index < 0) || (micb_index > TAVIL_MAX_MICBIAS - 1)) {
4354 dev_err(codec->dev, "%s: Invalid micbias index, micb_ind:%d\n",
4355 __func__, micb_index);
4356 return -EINVAL;
4357 }
4358
4359 if (enable)
4360 rc = snd_soc_dapm_force_enable_pin(
4361 snd_soc_codec_get_dapm(codec),
4362 micb_names[micb_index]);
4363 else
4364 rc = snd_soc_dapm_disable_pin(snd_soc_codec_get_dapm(codec),
4365 micb_names[micb_index]);
4366
4367 if (!rc)
4368 snd_soc_dapm_sync(snd_soc_codec_get_dapm(codec));
4369 else
4370 dev_err(codec->dev, "%s: micbias%d force %s pin failed\n",
4371 __func__, micb_num, (enable ? "enable" : "disable"));
4372
4373 return rc;
4374}
4375EXPORT_SYMBOL(tavil_codec_enable_standalone_micbias);
4376
4377static int tavil_codec_force_enable_micbias(struct snd_soc_dapm_widget *w,
4378 struct snd_kcontrol *kcontrol,
4379 int event)
4380{
4381 int ret = 0;
4382 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4383 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4384
4385 switch (event) {
4386 case SND_SOC_DAPM_PRE_PMU:
4387 wcd_resmgr_enable_master_bias(tavil->resmgr);
4388 tavil_cdc_mclk_enable(codec, true);
4389 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_PRE_PMU);
4390 /* Wait for 1ms for better cnp */
4391 usleep_range(1000, 1100);
4392 tavil_cdc_mclk_enable(codec, false);
4393 break;
4394 case SND_SOC_DAPM_POST_PMD:
4395 ret = __tavil_codec_enable_micbias(w, SND_SOC_DAPM_POST_PMD);
4396 wcd_resmgr_disable_master_bias(tavil->resmgr);
4397 break;
4398 }
4399
4400 return ret;
4401}
4402
4403static int tavil_codec_enable_micbias(struct snd_soc_dapm_widget *w,
4404 struct snd_kcontrol *kcontrol, int event)
4405{
4406 return __tavil_codec_enable_micbias(w, event);
4407}
4408
4409
4410static const struct reg_sequence tavil_hph_reset_tbl[] = {
4411 { WCD934X_HPH_CNP_EN, 0x80 },
4412 { WCD934X_HPH_CNP_WG_CTL, 0x9A },
4413 { WCD934X_HPH_CNP_WG_TIME, 0x14 },
4414 { WCD934X_HPH_OCP_CTL, 0x28 },
4415 { WCD934X_HPH_AUTO_CHOP, 0x16 },
4416 { WCD934X_HPH_CHOP_CTL, 0x83 },
4417 { WCD934X_HPH_PA_CTL1, 0x46 },
4418 { WCD934X_HPH_PA_CTL2, 0x50 },
4419 { WCD934X_HPH_L_EN, 0x80 },
4420 { WCD934X_HPH_L_TEST, 0xE0 },
4421 { WCD934X_HPH_L_ATEST, 0x50 },
4422 { WCD934X_HPH_R_EN, 0x80 },
4423 { WCD934X_HPH_R_TEST, 0xE0 },
4424 { WCD934X_HPH_R_ATEST, 0x54 },
4425 { WCD934X_HPH_RDAC_CLK_CTL1, 0x99 },
4426 { WCD934X_HPH_RDAC_CLK_CTL2, 0x9B },
4427 { WCD934X_HPH_RDAC_LDO_CTL, 0x33 },
4428 { WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 },
4429 { WCD934X_HPH_REFBUFF_UHQA_CTL, 0xA8 },
4430};
4431
4432static const struct reg_sequence tavil_hph_reset_tbl_1_0[] = {
4433 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0A },
4434 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4435 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4436 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4437 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4438 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x00 },
4439 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0xA0 },
4440 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4441 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4442 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x00 },
4443 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4444 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4445 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4446 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4447 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4448 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4449 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4450 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4451 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4452};
4453
4454static const struct reg_sequence tavil_hph_reset_tbl_1_1[] = {
4455 { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E },
4456 { WCD934X_HPH_L_DAC_CTL, 0x00 },
4457 { WCD934X_HPH_R_DAC_CTL, 0x00 },
4458 { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
4459 { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
4460 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 },
4461 { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0x81 },
4462 { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
4463 { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
4464 { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x81 },
4465 { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
4466 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
4467 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
4468 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
4469 { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
4470 { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
4471 { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
4472 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
4473 { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
4474};
4475
4476static const struct tavil_reg_mask_val tavil_pa_disable[] = {
4477 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x10 }, /* RX1 mute enable */
4478 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x10 }, /* RX2 mute enable */
4479 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 }, /* GM3 boost disable */
4480 { WCD934X_ANA_HPH, 0x80, 0x00 }, /* HPHL PA disable */
4481 { WCD934X_ANA_HPH, 0x40, 0x00 }, /* HPHR PA disable */
4482 { WCD934X_ANA_HPH, 0x20, 0x00 }, /* HPHL REF dsable */
4483 { WCD934X_ANA_HPH, 0x10, 0x00 }, /* HPHR REF disable */
4484};
4485
4486static const struct tavil_reg_mask_val tavil_ocp_en_seq[] = {
4487 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4488 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4489 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4490 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4491};
4492
4493static const struct tavil_reg_mask_val tavil_ocp_en_seq_1[] = {
4494 { WCD934X_RX_OCP_CTL, 0x0F, 0x02 }, /* OCP number of attempts is 2 */
4495 { WCD934X_HPH_OCP_CTL, 0xFA, 0x3A }, /* OCP current limit */
4496};
4497
4498/* LO-HIFI */
4499static const struct tavil_reg_mask_val tavil_pre_pa_en_lohifi[] = {
4500 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4501 { WCD934X_FLYBACK_VNEG_CTRL_4, 0xf0, 0x80 },
4502 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x20 },
4503 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4504 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4505 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0xc0 },
4506 { WCD934X_HPH_PA_CTL1, 0x0e, 0x02 },
4507 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4508};
4509
4510static const struct tavil_reg_mask_val tavil_pre_pa_en[] = {
4511 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
4512 { WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x0 },
4513 { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
4514 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
4515 { WCD934X_RX_BIAS_HPH_LOWPOWER, 0xf0, 0x80 },
4516 { WCD934X_HPH_PA_CTL1, 0x0e, 0x06 },
4517 { WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x06 },
4518};
4519
4520static const struct tavil_reg_mask_val tavil_post_pa_en[] = {
4521 { WCD934X_HPH_L_TEST, 0x01, 0x01 }, /* Enable HPHL OCP */
4522 { WCD934X_HPH_R_TEST, 0x01, 0x01 }, /* Enable HPHR OCP */
4523 { WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x20 }, /* RX1 mute disable */
4524 { WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x20 }, /* RX2 mute disable */
4525 { WCD934X_HPH_CNP_WG_CTL, 0x80, 0x80 }, /* GM3 boost enable */
4526 { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x02 },
4527};
4528
4529static void tavil_codec_hph_reg_range_read(struct regmap *map, u8 *buf)
4530{
4531 regmap_bulk_read(map, WCD934X_HPH_CNP_EN, buf, TAVIL_HPH_REG_RANGE_1);
4532 regmap_bulk_read(map, WCD934X_HPH_NEW_ANA_HPH2,
4533 buf + TAVIL_HPH_REG_RANGE_1, TAVIL_HPH_REG_RANGE_2);
4534 regmap_bulk_read(map, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
4535 buf + TAVIL_HPH_REG_RANGE_1 + TAVIL_HPH_REG_RANGE_2,
4536 TAVIL_HPH_REG_RANGE_3);
4537}
4538
4539static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil,
4540 struct regmap *map, int pa_status)
4541{
4542 int i;
4543 unsigned int reg;
4544
4545 blocking_notifier_call_chain(&tavil->mbhc->notifier,
4546 WCD_EVENT_OCP_OFF,
4547 &tavil->mbhc->wcd_mbhc);
4548
4549 if (pa_status & 0xC0)
4550 goto pa_en_restore;
4551
4552 dev_dbg(tavil->dev, "%s: HPH PA in disable state (0x%x)\n",
4553 __func__, pa_status);
4554
4555 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x10);
4556 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x10);
4557 regmap_write_bits(map, WCD934X_ANA_HPH, 0xC0, 0x00);
4558 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x00);
4559 regmap_write_bits(map, WCD934X_CDC_RX1_RX_PATH_CTL, 0x10, 0x00);
4560 regmap_write_bits(map, WCD934X_CDC_RX2_RX_PATH_CTL, 0x10, 0x00);
4561
4562 /* Restore to HW defaults */
4563 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4564 ARRAY_SIZE(tavil_hph_reset_tbl));
4565 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4566 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4567 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4568 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4569 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4570 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4571
4572 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq); i++)
4573 regmap_write_bits(map, tavil_ocp_en_seq[i].reg,
4574 tavil_ocp_en_seq[i].mask,
4575 tavil_ocp_en_seq[i].val);
4576 goto end;
4577
4578
4579pa_en_restore:
4580 dev_dbg(tavil->dev, "%s: HPH PA in enable state (0x%x)\n",
4581 __func__, pa_status);
4582
4583 /* Disable PA and other registers before restoring */
4584 for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) {
4585 if (TAVIL_IS_1_1(tavil->wcd9xxx) &&
4586 (tavil_pa_disable[i].reg == WCD934X_HPH_CNP_WG_CTL))
4587 continue;
4588 regmap_write_bits(map, tavil_pa_disable[i].reg,
4589 tavil_pa_disable[i].mask,
4590 tavil_pa_disable[i].val);
4591 }
4592
4593 regmap_multi_reg_write(map, tavil_hph_reset_tbl,
4594 ARRAY_SIZE(tavil_hph_reset_tbl));
4595 if (TAVIL_IS_1_1(tavil->wcd9xxx))
4596 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
4597 ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
4598 if (TAVIL_IS_1_0(tavil->wcd9xxx))
4599 regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
4600 ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
4601
4602 for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq_1); i++)
4603 regmap_write_bits(map, tavil_ocp_en_seq_1[i].reg,
4604 tavil_ocp_en_seq_1[i].mask,
4605 tavil_ocp_en_seq_1[i].val);
4606
4607 if (tavil->hph_mode == CLS_H_LOHIFI) {
4608 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) {
4609 reg = tavil_pre_pa_en_lohifi[i].reg;
4610 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4611 ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
4612 (reg == WCD934X_HPH_CNP_WG_CTL) ||
4613 (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
4614 continue;
4615 regmap_write_bits(map,
4616 tavil_pre_pa_en_lohifi[i].reg,
4617 tavil_pre_pa_en_lohifi[i].mask,
4618 tavil_pre_pa_en_lohifi[i].val);
4619 }
4620 } else {
4621 for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) {
4622 reg = tavil_pre_pa_en[i].reg;
4623 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4624 ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
4625 (reg == WCD934X_HPH_CNP_WG_CTL) ||
4626 (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
4627 continue;
4628 regmap_write_bits(map, tavil_pre_pa_en[i].reg,
4629 tavil_pre_pa_en[i].mask,
4630 tavil_pre_pa_en[i].val);
4631 }
4632 }
4633
4634 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
4635 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x84);
4636 regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x84);
4637 }
4638
4639 regmap_write_bits(map, WCD934X_ANA_HPH, 0x0C, pa_status & 0x0C);
4640 regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x30);
4641 /* wait for 100usec after HPH DAC is enabled */
4642 usleep_range(100, 110);
4643 regmap_write(map, WCD934X_ANA_HPH, pa_status);
4644 /* Sleep for 7msec after PA is enabled */
4645 usleep_range(7000, 7100);
4646
4647 for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) {
4648 if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
4649 (tavil_post_pa_en[i].reg == WCD934X_HPH_CNP_WG_CTL))
4650 continue;
4651 regmap_write_bits(map, tavil_post_pa_en[i].reg,
4652 tavil_post_pa_en[i].mask,
4653 tavil_post_pa_en[i].val);
4654 }
4655
4656end:
4657 tavil->mbhc->is_hph_recover = true;
4658 blocking_notifier_call_chain(
4659 &tavil->mbhc->notifier,
4660 WCD_EVENT_OCP_ON,
4661 &tavil->mbhc->wcd_mbhc);
4662}
4663
4664static int tavil_codec_reset_hph_registers(struct snd_soc_dapm_widget *w,
4665 struct snd_kcontrol *kcontrol,
4666 int event)
4667{
4668 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
4669 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4670 struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
4671 u8 cache_val[TAVIL_HPH_TOTAL_REG];
4672 u8 hw_val[TAVIL_HPH_TOTAL_REG];
4673 int pa_status;
4674 int ret;
4675
4676 dev_dbg(wcd9xxx->dev, "%s: event: %d\n", __func__, event);
4677
4678 switch (event) {
4679 case SND_SOC_DAPM_PRE_PMU:
4680 memset(cache_val, 0, TAVIL_HPH_TOTAL_REG);
4681 memset(hw_val, 0, TAVIL_HPH_TOTAL_REG);
4682
4683 regmap_read(wcd9xxx->regmap, WCD934X_ANA_HPH, &pa_status);
4684
4685 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, cache_val);
4686
4687 /* Read register values from HW directly */
4688 regcache_cache_bypass(wcd9xxx->regmap, true);
4689 tavil_codec_hph_reg_range_read(wcd9xxx->regmap, hw_val);
4690 regcache_cache_bypass(wcd9xxx->regmap, false);
4691
4692 /* compare both the registers to know if there is corruption */
4693 ret = memcmp(cache_val, hw_val, TAVIL_HPH_TOTAL_REG);
4694
4695 /* If both the values are same, it means no corruption */
4696 if (ret) {
4697 dev_dbg(codec->dev, "%s: cache and hw reg are not same\n",
4698 __func__);
4699 tavil_codec_hph_reg_recover(tavil, wcd9xxx->regmap,
4700 pa_status);
4701 } else {
4702 dev_dbg(codec->dev, "%s: cache and hw reg are same\n",
4703 __func__);
4704 tavil->mbhc->is_hph_recover = false;
4705 }
4706 break;
4707 default:
4708 break;
4709 };
4710
4711 return 0;
4712}
4713
4714static int tavil_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
4715 struct snd_ctl_elem_value *ucontrol)
4716{
4717 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4718 int iir_idx = ((struct soc_multi_mixer_control *)
4719 kcontrol->private_value)->reg;
4720 int band_idx = ((struct soc_multi_mixer_control *)
4721 kcontrol->private_value)->shift;
4722 /* IIR filter band registers are at integer multiples of 16 */
4723 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
4724
4725 ucontrol->value.integer.value[0] = (snd_soc_read(codec, iir_reg) &
4726 (1 << band_idx)) != 0;
4727
4728 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
4729 iir_idx, band_idx,
4730 (uint32_t)ucontrol->value.integer.value[0]);
4731 return 0;
4732}
4733
4734static int tavil_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
4735 struct snd_ctl_elem_value *ucontrol)
4736{
4737 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4738 int iir_idx = ((struct soc_multi_mixer_control *)
4739 kcontrol->private_value)->reg;
4740 int band_idx = ((struct soc_multi_mixer_control *)
4741 kcontrol->private_value)->shift;
4742 bool iir_band_en_status;
4743 int value = ucontrol->value.integer.value[0];
4744 u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
4745
4746 /* Mask first 5 bits, 6-8 are reserved */
4747 snd_soc_update_bits(codec, iir_reg, (1 << band_idx),
4748 (value << band_idx));
4749
4750 iir_band_en_status = ((snd_soc_read(codec, iir_reg) &
4751 (1 << band_idx)) != 0);
4752 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
4753 iir_idx, band_idx, iir_band_en_status);
4754 return 0;
4755}
4756
4757static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
4758 int iir_idx, int band_idx,
4759 int coeff_idx)
4760{
4761 uint32_t value = 0;
4762
4763 /* Address does not automatically update if reading */
4764 snd_soc_write(codec,
4765 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
4766 ((band_idx * BAND_MAX + coeff_idx)
4767 * sizeof(uint32_t)) & 0x7F);
4768
4769 value |= snd_soc_read(codec,
4770 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx));
4771
4772 snd_soc_write(codec,
4773 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
4774 ((band_idx * BAND_MAX + coeff_idx)
4775 * sizeof(uint32_t) + 1) & 0x7F);
4776
4777 value |= (snd_soc_read(codec,
4778 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
4779 16 * iir_idx)) << 8);
4780
4781 snd_soc_write(codec,
4782 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
4783 ((band_idx * BAND_MAX + coeff_idx)
4784 * sizeof(uint32_t) + 2) & 0x7F);
4785
4786 value |= (snd_soc_read(codec,
4787 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
4788 16 * iir_idx)) << 16);
4789
4790 snd_soc_write(codec,
4791 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
4792 ((band_idx * BAND_MAX + coeff_idx)
4793 * sizeof(uint32_t) + 3) & 0x7F);
4794
4795 /* Mask bits top 2 bits since they are reserved */
4796 value |= ((snd_soc_read(codec,
4797 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL +
4798 16 * iir_idx)) & 0x3F) << 24);
4799
4800 return value;
4801}
4802
4803static int tavil_iir_band_audio_mixer_get(struct snd_kcontrol *kcontrol,
4804 struct snd_ctl_elem_value *ucontrol)
4805{
4806 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4807 int iir_idx = ((struct soc_multi_mixer_control *)
4808 kcontrol->private_value)->reg;
4809 int band_idx = ((struct soc_multi_mixer_control *)
4810 kcontrol->private_value)->shift;
4811
4812 ucontrol->value.integer.value[0] =
4813 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
4814 ucontrol->value.integer.value[1] =
4815 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
4816 ucontrol->value.integer.value[2] =
4817 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
4818 ucontrol->value.integer.value[3] =
4819 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
4820 ucontrol->value.integer.value[4] =
4821 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
4822
4823 dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
4824 "%s: IIR #%d band #%d b1 = 0x%x\n"
4825 "%s: IIR #%d band #%d b2 = 0x%x\n"
4826 "%s: IIR #%d band #%d a1 = 0x%x\n"
4827 "%s: IIR #%d band #%d a2 = 0x%x\n",
4828 __func__, iir_idx, band_idx,
4829 (uint32_t)ucontrol->value.integer.value[0],
4830 __func__, iir_idx, band_idx,
4831 (uint32_t)ucontrol->value.integer.value[1],
4832 __func__, iir_idx, band_idx,
4833 (uint32_t)ucontrol->value.integer.value[2],
4834 __func__, iir_idx, band_idx,
4835 (uint32_t)ucontrol->value.integer.value[3],
4836 __func__, iir_idx, band_idx,
4837 (uint32_t)ucontrol->value.integer.value[4]);
4838 return 0;
4839}
4840
4841static void set_iir_band_coeff(struct snd_soc_codec *codec,
4842 int iir_idx, int band_idx,
4843 uint32_t value)
4844{
4845 snd_soc_write(codec,
4846 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
4847 (value & 0xFF));
4848
4849 snd_soc_write(codec,
4850 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
4851 (value >> 8) & 0xFF);
4852
4853 snd_soc_write(codec,
4854 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
4855 (value >> 16) & 0xFF);
4856
4857 /* Mask top 2 bits, 7-8 are reserved */
4858 snd_soc_write(codec,
4859 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx),
4860 (value >> 24) & 0x3F);
4861}
4862
4863static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
4864 struct snd_ctl_elem_value *ucontrol)
4865{
4866 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4867 int iir_idx = ((struct soc_multi_mixer_control *)
4868 kcontrol->private_value)->reg;
4869 int band_idx = ((struct soc_multi_mixer_control *)
4870 kcontrol->private_value)->shift;
4871
4872 /*
4873 * Mask top bit it is reserved
4874 * Updates addr automatically for each B2 write
4875 */
4876 snd_soc_write(codec,
4877 (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
4878 (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
4879
4880 set_iir_band_coeff(codec, iir_idx, band_idx,
4881 ucontrol->value.integer.value[0]);
4882 set_iir_band_coeff(codec, iir_idx, band_idx,
4883 ucontrol->value.integer.value[1]);
4884 set_iir_band_coeff(codec, iir_idx, band_idx,
4885 ucontrol->value.integer.value[2]);
4886 set_iir_band_coeff(codec, iir_idx, band_idx,
4887 ucontrol->value.integer.value[3]);
4888 set_iir_band_coeff(codec, iir_idx, band_idx,
4889 ucontrol->value.integer.value[4]);
4890
4891 pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
4892 "%s: IIR #%d band #%d b1 = 0x%x\n"
4893 "%s: IIR #%d band #%d b2 = 0x%x\n"
4894 "%s: IIR #%d band #%d a1 = 0x%x\n"
4895 "%s: IIR #%d band #%d a2 = 0x%x\n",
4896 __func__, iir_idx, band_idx,
4897 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
4898 __func__, iir_idx, band_idx,
4899 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
4900 __func__, iir_idx, band_idx,
4901 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
4902 __func__, iir_idx, band_idx,
4903 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
4904 __func__, iir_idx, band_idx,
4905 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
4906 return 0;
4907}
4908
4909static int tavil_compander_get(struct snd_kcontrol *kcontrol,
4910 struct snd_ctl_elem_value *ucontrol)
4911{
4912
4913 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4914 int comp = ((struct soc_multi_mixer_control *)
4915 kcontrol->private_value)->shift;
4916 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4917
4918 ucontrol->value.integer.value[0] = tavil->comp_enabled[comp];
4919 return 0;
4920}
4921
4922static int tavil_compander_put(struct snd_kcontrol *kcontrol,
4923 struct snd_ctl_elem_value *ucontrol)
4924{
4925 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4926 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4927 int comp = ((struct soc_multi_mixer_control *)
4928 kcontrol->private_value)->shift;
4929 int value = ucontrol->value.integer.value[0];
4930
4931 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
4932 __func__, comp + 1, tavil->comp_enabled[comp], value);
4933 tavil->comp_enabled[comp] = value;
4934
4935 /* Any specific register configuration for compander */
4936 switch (comp) {
4937 case COMPANDER_1:
4938 /* Set Gain Source Select based on compander enable/disable */
4939 snd_soc_update_bits(codec, WCD934X_HPH_L_EN, 0x20,
4940 (value ? 0x00:0x20));
4941 break;
4942 case COMPANDER_2:
4943 snd_soc_update_bits(codec, WCD934X_HPH_R_EN, 0x20,
4944 (value ? 0x00:0x20));
4945 break;
4946 case COMPANDER_3:
4947 case COMPANDER_4:
4948 case COMPANDER_7:
4949 case COMPANDER_8:
4950 break;
4951 default:
4952 /*
4953 * if compander is not enabled for any interpolator,
4954 * it does not cause any audio failure, so do not
4955 * return error in this case, but just print a log
4956 */
4957 dev_warn(codec->dev, "%s: unknown compander: %d\n",
4958 __func__, comp);
4959 };
4960 return 0;
4961}
4962
4963static int tavil_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
4964 struct snd_ctl_elem_value *ucontrol)
4965{
4966 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4967 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4968 int index = -EINVAL;
4969
4970 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
4971 index = ASRC0;
4972 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
4973 index = ASRC1;
4974
4975 if (tavil && (index >= 0) && (index < ASRC_MAX))
4976 tavil->asrc_output_mode[index] =
4977 ucontrol->value.integer.value[0];
4978
4979 return 0;
4980}
4981
4982static int tavil_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
4983 struct snd_ctl_elem_value *ucontrol)
4984{
4985 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
4986 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
4987 int val = 0;
4988 int index = -EINVAL;
4989
4990 if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
4991 index = ASRC0;
4992 if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
4993 index = ASRC1;
4994
4995 if (tavil && (index >= 0) && (index < ASRC_MAX))
4996 val = tavil->asrc_output_mode[index];
4997
4998 ucontrol->value.integer.value[0] = val;
4999
5000 return 0;
5001}
5002
5003static int tavil_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
5004 struct snd_ctl_elem_value *ucontrol)
5005{
5006 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5007 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5008 int val = 0;
5009
5010 if (tavil)
5011 val = tavil->idle_det_cfg.hph_idle_detect_en;
5012
5013 ucontrol->value.integer.value[0] = val;
5014
5015 return 0;
5016}
5017
5018static int tavil_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
5019 struct snd_ctl_elem_value *ucontrol)
5020{
5021 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5022 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5023
5024 if (tavil)
5025 tavil->idle_det_cfg.hph_idle_detect_en =
5026 ucontrol->value.integer.value[0];
5027
5028 return 0;
5029}
5030
5031static int tavil_dmic_pin_mode_get(struct snd_kcontrol *kcontrol,
5032 struct snd_ctl_elem_value *ucontrol)
5033{
5034 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5035 u16 dmic_pin;
5036 u8 reg_val, pinctl_position;
5037
5038 pinctl_position = ((struct soc_multi_mixer_control *)
5039 kcontrol->private_value)->shift;
5040
5041 dmic_pin = pinctl_position & 0x07;
5042 reg_val = snd_soc_read(codec,
5043 WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1);
5044
5045 ucontrol->value.integer.value[0] = !!reg_val;
5046
5047 return 0;
5048}
5049
5050static int tavil_dmic_pin_mode_put(struct snd_kcontrol *kcontrol,
5051 struct snd_ctl_elem_value *ucontrol)
5052{
5053 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5054 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5055 u16 ctl_reg, cfg_reg, dmic_pin;
5056 u8 ctl_val, cfg_val, pinctl_position, pinctl_mode, mask;
5057
5058 /* 0- high or low; 1- high Z */
5059 pinctl_mode = ucontrol->value.integer.value[0];
5060 pinctl_position = ((struct soc_multi_mixer_control *)
5061 kcontrol->private_value)->shift;
5062
5063 switch (pinctl_position >> 3) {
5064 case 0:
5065 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_0;
5066 break;
5067 case 1:
5068 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_1;
5069 break;
5070 case 2:
5071 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_2;
5072 break;
5073 case 3:
5074 ctl_reg = WCD934X_TEST_DEBUG_PIN_CTL_OE_3;
5075 break;
5076 default:
5077 dev_err(codec->dev, "%s: Invalid pinctl position = %d\n",
5078 __func__, pinctl_position);
5079 return -EINVAL;
5080 }
5081
5082 ctl_val = ~(pinctl_mode << (pinctl_position & 0x07));
5083 mask = 1 << (pinctl_position & 0x07);
5084 snd_soc_update_bits(codec, ctl_reg, mask, ctl_val);
5085
5086 dmic_pin = pinctl_position & 0x07;
5087 cfg_reg = WCD934X_TLMM_DMIC1_CLK_PINCFG + dmic_pin - 1;
5088 if (pinctl_mode) {
5089 if (tavil->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
5090 cfg_val = 0x6;
5091 else
5092 cfg_val = 0xD;
5093 } else
5094 cfg_val = 0;
5095 snd_soc_update_bits(codec, cfg_reg, 0x1F, cfg_val);
5096
5097 dev_dbg(codec->dev, "%s: reg=0x%x mask=0x%x val=%d reg=0x%x val=%d\n",
5098 __func__, ctl_reg, mask, ctl_val, cfg_reg, cfg_val);
5099
5100 return 0;
5101}
5102
5103static int tavil_amic_pwr_lvl_get(struct snd_kcontrol *kcontrol,
5104 struct snd_ctl_elem_value *ucontrol)
5105{
5106 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5107 u16 amic_reg;
5108
5109 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5110 amic_reg = WCD934X_ANA_AMIC1;
5111 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5112 amic_reg = WCD934X_ANA_AMIC3;
5113 else
5114 goto ret;
5115
5116 ucontrol->value.integer.value[0] =
5117 (snd_soc_read(codec, amic_reg) & WCD934X_AMIC_PWR_LVL_MASK) >>
5118 WCD934X_AMIC_PWR_LVL_SHIFT;
5119ret:
5120 return 0;
5121}
5122
5123static int tavil_amic_pwr_lvl_put(struct snd_kcontrol *kcontrol,
5124 struct snd_ctl_elem_value *ucontrol)
5125{
5126 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5127 u32 mode_val;
5128 u16 amic_reg;
5129
5130 mode_val = ucontrol->value.enumerated.item[0];
5131
5132 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5133
5134 if (!strcmp(kcontrol->id.name, "AMIC_1_2 PWR MODE"))
5135 amic_reg = WCD934X_ANA_AMIC1;
5136 if (!strcmp(kcontrol->id.name, "AMIC_3_4 PWR MODE"))
5137 amic_reg = WCD934X_ANA_AMIC3;
5138 else
5139 goto ret;
5140
5141 snd_soc_update_bits(codec, amic_reg, WCD934X_AMIC_PWR_LVL_MASK,
5142 mode_val << WCD934X_AMIC_PWR_LVL_SHIFT);
5143ret:
5144 return 0;
5145}
5146
5147static const char *const tavil_conn_mad_text[] = {
5148 "NOTUSED1", "ADC1", "ADC2", "ADC3", "ADC4", "NOTUSED5",
5149 "NOTUSED6", "NOTUSED2", "DMIC0", "DMIC1", "DMIC2", "DMIC3",
5150 "DMIC4", "DMIC5", "NOTUSED3", "NOTUSED4"
5151};
5152
5153static const struct soc_enum tavil_conn_mad_enum =
5154 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tavil_conn_mad_text),
5155 tavil_conn_mad_text);
5156
5157static int tavil_mad_input_get(struct snd_kcontrol *kcontrol,
5158 struct snd_ctl_elem_value *ucontrol)
5159{
5160 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5161 u8 tavil_mad_input;
5162
5163 tavil_mad_input = snd_soc_read(codec, WCD934X_SOC_MAD_INP_SEL) & 0x0F;
5164 ucontrol->value.integer.value[0] = tavil_mad_input;
5165
5166 dev_dbg(codec->dev, "%s: tavil_mad_input = %s\n", __func__,
5167 tavil_conn_mad_text[tavil_mad_input]);
5168
5169 return 0;
5170}
5171
5172static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
5173 struct snd_ctl_elem_value *ucontrol)
5174{
5175 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5176 struct snd_soc_card *card = codec->component.card;
5177 u8 tavil_mad_input;
5178 char mad_amic_input_widget[6];
5179 const char *mad_input_widget;
5180 const char *source_widget = NULL;
5181 u32 adc, i, mic_bias_found = 0;
5182 int ret = 0;
5183 char *mad_input;
5184 bool is_adc2_input = false;
5185
5186 tavil_mad_input = ucontrol->value.integer.value[0];
5187
5188 if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED",
5189 sizeof("NOTUSED"))) {
5190 dev_dbg(codec->dev,
5191 "%s: Unsupported tavil_mad_input = %s\n",
5192 __func__, tavil_conn_mad_text[tavil_mad_input]);
5193 /* Make sure the MAD register is updated */
5194 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5195 0x88, 0x00);
5196 return -EINVAL;
5197 }
5198
5199 if (strnstr(tavil_conn_mad_text[tavil_mad_input],
5200 "ADC", sizeof("ADC"))) {
5201 mad_input = strpbrk(tavil_conn_mad_text[tavil_mad_input],
5202 "1234");
5203 if (!mad_input) {
5204 dev_err(codec->dev, "%s: Invalid MAD input %s\n",
5205 __func__, tavil_conn_mad_text[tavil_mad_input]);
5206 return -EINVAL;
5207 }
5208
5209 ret = kstrtouint(mad_input, 10, &adc);
5210 if ((ret < 0) || (adc > 4)) {
5211 dev_err(codec->dev, "%s: Invalid ADC = %s\n", __func__,
5212 tavil_conn_mad_text[tavil_mad_input]);
5213 return -EINVAL;
5214 }
5215
5216 /*AMIC4 and AMIC5 share ADC4*/
5217 if ((adc == 4) &&
5218 (snd_soc_read(codec, WCD934X_TX_NEW_AMIC_4_5_SEL) & 0x10))
5219 adc = 5;
5220
5221 snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
5222
5223 mad_input_widget = mad_amic_input_widget;
5224 if (adc == 2)
5225 is_adc2_input = true;
5226 } else {
5227 /* DMIC type input widget*/
5228 mad_input_widget = tavil_conn_mad_text[tavil_mad_input];
5229 }
5230
5231 dev_dbg(codec->dev,
5232 "%s: tavil input widget = %s, adc_input = %s\n", __func__,
5233 mad_input_widget, is_adc2_input ? "true" : "false");
5234
5235 for (i = 0; i < card->num_of_dapm_routes; i++) {
5236 if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) {
5237 source_widget = card->of_dapm_routes[i].source;
5238 if (!source_widget) {
5239 dev_err(codec->dev,
5240 "%s: invalid source widget\n",
5241 __func__);
5242 return -EINVAL;
5243 }
5244
5245 if (strnstr(source_widget,
5246 "MIC BIAS1", sizeof("MIC BIAS1"))) {
5247 mic_bias_found = 1;
5248 break;
5249 } else if (strnstr(source_widget,
5250 "MIC BIAS2", sizeof("MIC BIAS2"))) {
5251 mic_bias_found = 2;
5252 break;
5253 } else if (strnstr(source_widget,
5254 "MIC BIAS3", sizeof("MIC BIAS3"))) {
5255 mic_bias_found = 3;
5256 break;
5257 } else if (strnstr(source_widget,
5258 "MIC BIAS4", sizeof("MIC BIAS4"))) {
5259 mic_bias_found = 4;
5260 break;
5261 }
5262 }
5263 }
5264
5265 if (!mic_bias_found) {
5266 dev_err(codec->dev, "%s: mic bias not found for input %s\n",
5267 __func__, mad_input_widget);
5268 return -EINVAL;
5269 }
5270
5271 dev_dbg(codec->dev, "%s: mic_bias found = %d\n", __func__,
5272 mic_bias_found);
5273
5274 snd_soc_update_bits(codec, WCD934X_SOC_MAD_INP_SEL,
5275 0x0F, tavil_mad_input);
5276 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5277 0x07, mic_bias_found);
5278 /* for adc2 input, mad should be in micbias mode with BG enabled */
5279 if (is_adc2_input)
5280 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5281 0x88, 0x88);
5282 else
5283 snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
5284 0x88, 0x00);
5285 return 0;
5286}
5287
5288static int tavil_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
5289 struct snd_ctl_elem_value *ucontrol)
5290{
5291 u8 ear_pa_gain;
5292 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5293
5294 ear_pa_gain = snd_soc_read(codec, WCD934X_ANA_EAR);
5295
5296 ear_pa_gain = (ear_pa_gain & 0x70) >> 4;
5297
5298 ucontrol->value.integer.value[0] = ear_pa_gain;
5299
5300 dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__,
5301 ear_pa_gain);
5302
5303 return 0;
5304}
5305
5306static int tavil_ear_pa_gain_put(struct snd_kcontrol *kcontrol,
5307 struct snd_ctl_elem_value *ucontrol)
5308{
5309 u8 ear_pa_gain;
5310 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5311
5312 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5313 __func__, ucontrol->value.integer.value[0]);
5314
5315 ear_pa_gain = ucontrol->value.integer.value[0] << 4;
5316
5317 snd_soc_update_bits(codec, WCD934X_ANA_EAR, 0x70, ear_pa_gain);
5318 return 0;
5319}
5320
5321static int tavil_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
5322 struct snd_ctl_elem_value *ucontrol)
5323{
5324 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5325 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5326
5327 ucontrol->value.integer.value[0] = tavil->ear_spkr_gain;
5328
5329 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
5330 __func__, ucontrol->value.integer.value[0]);
5331
5332 return 0;
5333}
5334
5335static int tavil_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
5336 struct snd_ctl_elem_value *ucontrol)
5337{
5338 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5339 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5340
5341 tavil->ear_spkr_gain = ucontrol->value.integer.value[0];
5342
5343 dev_dbg(codec->dev, "%s: gain = %d\n", __func__, tavil->ear_spkr_gain);
5344
5345 return 0;
5346}
5347
5348static int tavil_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
5349 struct snd_ctl_elem_value *ucontrol)
5350{
5351 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5352 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5353
5354 ucontrol->value.integer.value[0] = tavil->hph_mode;
5355 return 0;
5356}
5357
5358static int tavil_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
5359 struct snd_ctl_elem_value *ucontrol)
5360{
5361 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
5362 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
5363 u32 mode_val;
5364
5365 mode_val = ucontrol->value.enumerated.item[0];
5366
5367 dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
5368
5369 if (mode_val == 0) {
5370 dev_warn(codec->dev, "%s:Invalid HPH Mode, default to Cls-H LOHiFi\n",
5371 __func__);
5372 mode_val = CLS_H_LOHIFI;
5373 }
5374 tavil->hph_mode = mode_val;
5375 return 0;
5376}
5377
5378static const char * const rx_hph_mode_mux_text[] = {
5379 "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
5380 "CLS_H_ULP", "CLS_AB_HIFI",
5381};
5382
5383static const struct soc_enum rx_hph_mode_mux_enum =
5384 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
5385 rx_hph_mode_mux_text);
5386
5387static const char *const tavil_anc_func_text[] = {"OFF", "ON"};
5388static const struct soc_enum tavil_anc_func_enum =
5389 SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
5390
5391/* Cutoff frequency for high pass filter */
5392static const char * const cf_text[] = {
5393 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
5394};
5395
5396static const char * const rx_cf_text[] = {
5397 "CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
5398 "CF_NEG_3DB_0P48HZ"
5399};
5400
5401static const char * const amic_pwr_lvl_text[] = {
5402 "LOW_PWR", "DEFAULT", "HIGH_PERF"
5403};
5404
5405static const char * const hph_idle_detect_text[] = {
5406 "OFF", "ON"
5407};
5408
5409static const char * const asrc_mode_text[] = {
5410 "INT", "FRAC"
5411};
5412
5413static const char * const tavil_ear_pa_gain_text[] = {
5414 "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
5415 "G_0_DB", "G_M2P5_DB", "UNDEFINED", "G_M12_DB"
5416};
5417
5418static const char * const tavil_ear_spkr_pa_gain_text[] = {
5419 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
5420 "G_4_DB", "G_5_DB", "G_6_DB"
5421};
5422
5423static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_pa_gain_enum, tavil_ear_pa_gain_text);
5424static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_spkr_pa_gain_enum,
5425 tavil_ear_spkr_pa_gain_text);
5426static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
5427static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
5428static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
5429static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, WCD934X_CDC_TX0_TX_PATH_CFG0, 5,
5430 cf_text);
5431static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, WCD934X_CDC_TX1_TX_PATH_CFG0, 5,
5432 cf_text);
5433static SOC_ENUM_SINGLE_DECL(cf_dec2_enum, WCD934X_CDC_TX2_TX_PATH_CFG0, 5,
5434 cf_text);
5435static SOC_ENUM_SINGLE_DECL(cf_dec3_enum, WCD934X_CDC_TX3_TX_PATH_CFG0, 5,
5436 cf_text);
5437static SOC_ENUM_SINGLE_DECL(cf_dec4_enum, WCD934X_CDC_TX4_TX_PATH_CFG0, 5,
5438 cf_text);
5439static SOC_ENUM_SINGLE_DECL(cf_dec5_enum, WCD934X_CDC_TX5_TX_PATH_CFG0, 5,
5440 cf_text);
5441static SOC_ENUM_SINGLE_DECL(cf_dec6_enum, WCD934X_CDC_TX6_TX_PATH_CFG0, 5,
5442 cf_text);
5443static SOC_ENUM_SINGLE_DECL(cf_dec7_enum, WCD934X_CDC_TX7_TX_PATH_CFG0, 5,
5444 cf_text);
5445static SOC_ENUM_SINGLE_DECL(cf_dec8_enum, WCD934X_CDC_TX8_TX_PATH_CFG0, 5,
5446 cf_text);
5447static SOC_ENUM_SINGLE_DECL(cf_int0_1_enum, WCD934X_CDC_RX0_RX_PATH_CFG2, 0,
5448 rx_cf_text);
5449static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD934X_CDC_RX0_RX_PATH_MIX_CFG, 2,
5450 rx_cf_text);
5451static SOC_ENUM_SINGLE_DECL(cf_int1_1_enum, WCD934X_CDC_RX1_RX_PATH_CFG2, 0,
5452 rx_cf_text);
5453static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD934X_CDC_RX1_RX_PATH_MIX_CFG, 2,
5454 rx_cf_text);
5455static SOC_ENUM_SINGLE_DECL(cf_int2_1_enum, WCD934X_CDC_RX2_RX_PATH_CFG2, 0,
5456 rx_cf_text);
5457static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD934X_CDC_RX2_RX_PATH_MIX_CFG, 2,
5458 rx_cf_text);
5459static SOC_ENUM_SINGLE_DECL(cf_int3_1_enum, WCD934X_CDC_RX3_RX_PATH_CFG2, 0,
5460 rx_cf_text);
5461static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD934X_CDC_RX3_RX_PATH_MIX_CFG, 2,
5462 rx_cf_text);
5463static SOC_ENUM_SINGLE_DECL(cf_int4_1_enum, WCD934X_CDC_RX4_RX_PATH_CFG2, 0,
5464 rx_cf_text);
5465static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD934X_CDC_RX4_RX_PATH_MIX_CFG, 2,
5466 rx_cf_text);
5467static SOC_ENUM_SINGLE_DECL(cf_int7_1_enum, WCD934X_CDC_RX7_RX_PATH_CFG2, 0,
5468 rx_cf_text);
5469static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD934X_CDC_RX7_RX_PATH_MIX_CFG, 2,
5470 rx_cf_text);
5471static SOC_ENUM_SINGLE_DECL(cf_int8_1_enum, WCD934X_CDC_RX8_RX_PATH_CFG2, 0,
5472 rx_cf_text);
5473static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD934X_CDC_RX8_RX_PATH_MIX_CFG, 2,
5474 rx_cf_text);
5475
5476static const struct snd_kcontrol_new tavil_snd_controls[] = {
5477 SOC_ENUM_EXT("EAR PA Gain", tavil_ear_pa_gain_enum,
5478 tavil_ear_pa_gain_get, tavil_ear_pa_gain_put),
5479 SOC_ENUM_EXT("EAR SPKR PA Gain", tavil_ear_spkr_pa_gain_enum,
5480 tavil_ear_spkr_pa_gain_get, tavil_ear_spkr_pa_gain_put),
5481 SOC_SINGLE_TLV("HPHL Volume", WCD934X_HPH_L_EN, 0, 20, 1, line_gain),
5482 SOC_SINGLE_TLV("HPHR Volume", WCD934X_HPH_R_EN, 0, 20, 1, line_gain),
5483 SOC_SINGLE_TLV("LINEOUT1 Volume", WCD934X_DIFF_LO_LO1_COMPANDER,
5484 3, 16, 1, line_gain),
5485 SOC_SINGLE_TLV("LINEOUT2 Volume", WCD934X_DIFF_LO_LO2_COMPANDER,
5486 3, 16, 1, line_gain),
5487 SOC_SINGLE_TLV("ADC1 Volume", WCD934X_ANA_AMIC1, 0, 20, 0, analog_gain),
5488 SOC_SINGLE_TLV("ADC2 Volume", WCD934X_ANA_AMIC2, 0, 20, 0, analog_gain),
5489 SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain),
5490 SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain),
5491
5492 SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL,
5493 0, -84, 40, digital_gain), /* -84dB min - 40dB max */
5494 SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL,
5495 0, -84, 40, digital_gain),
5496 SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL,
5497 0, -84, 40, digital_gain),
5498 SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL,
5499 0, -84, 40, digital_gain),
5500 SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL,
5501 0, -84, 40, digital_gain),
5502 SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL,
5503 0, -84, 40, digital_gain),
5504 SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL,
5505 0, -84, 40, digital_gain),
5506 SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume",
5507 WCD934X_CDC_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5508 SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume",
5509 WCD934X_CDC_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5510 SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume",
5511 WCD934X_CDC_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5512 SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume",
5513 WCD934X_CDC_RX3_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5514 SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume",
5515 WCD934X_CDC_RX4_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5516 SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume",
5517 WCD934X_CDC_RX7_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5518 SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume",
5519 WCD934X_CDC_RX8_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain),
5520
5521 SOC_SINGLE_SX_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, 0,
5522 -84, 40, digital_gain),
5523 SOC_SINGLE_SX_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, 0,
5524 -84, 40, digital_gain),
5525 SOC_SINGLE_SX_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, 0,
5526 -84, 40, digital_gain),
5527 SOC_SINGLE_SX_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, 0,
5528 -84, 40, digital_gain),
5529 SOC_SINGLE_SX_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, 0,
5530 -84, 40, digital_gain),
5531 SOC_SINGLE_SX_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, 0,
5532 -84, 40, digital_gain),
5533 SOC_SINGLE_SX_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, 0,
5534 -84, 40, digital_gain),
5535 SOC_SINGLE_SX_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, 0,
5536 -84, 40, digital_gain),
5537 SOC_SINGLE_SX_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, 0,
5538 -84, 40, digital_gain),
5539
5540 SOC_SINGLE_SX_TLV("IIR0 INP0 Volume",
5541 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40,
5542 digital_gain),
5543 SOC_SINGLE_SX_TLV("IIR0 INP1 Volume",
5544 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40,
5545 digital_gain),
5546 SOC_SINGLE_SX_TLV("IIR0 INP2 Volume",
5547 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40,
5548 digital_gain),
5549 SOC_SINGLE_SX_TLV("IIR0 INP3 Volume",
5550 WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40,
5551 digital_gain),
5552 SOC_SINGLE_SX_TLV("IIR1 INP0 Volume",
5553 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40,
5554 digital_gain),
5555 SOC_SINGLE_SX_TLV("IIR1 INP1 Volume",
5556 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40,
5557 digital_gain),
5558 SOC_SINGLE_SX_TLV("IIR1 INP2 Volume",
5559 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40,
5560 digital_gain),
5561 SOC_SINGLE_SX_TLV("IIR1 INP3 Volume",
5562 WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40,
5563 digital_gain),
5564
5565 SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot,
5566 tavil_put_anc_slot),
5567 SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
5568 tavil_put_anc_func),
5569
5570 SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
5571 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
5572 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
5573 SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
5574 SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
5575 SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
5576 SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
5577 SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
5578 SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
5579
5580 SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
5581 SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
5582 SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
5583 SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
5584 SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
5585 SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
5586 SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
5587 SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
5588 SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
5589 SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
5590 SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
5591 SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
5592 SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
5593 SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
5594
5595 SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
5596 tavil_rx_hph_mode_get, tavil_rx_hph_mode_put),
5597
5598 SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
5599 tavil_iir_enable_audio_mixer_get,
5600 tavil_iir_enable_audio_mixer_put),
5601 SOC_SINGLE_EXT("IIR0 Enable Band2", IIR0, BAND2, 1, 0,
5602 tavil_iir_enable_audio_mixer_get,
5603 tavil_iir_enable_audio_mixer_put),
5604 SOC_SINGLE_EXT("IIR0 Enable Band3", IIR0, BAND3, 1, 0,
5605 tavil_iir_enable_audio_mixer_get,
5606 tavil_iir_enable_audio_mixer_put),
5607 SOC_SINGLE_EXT("IIR0 Enable Band4", IIR0, BAND4, 1, 0,
5608 tavil_iir_enable_audio_mixer_get,
5609 tavil_iir_enable_audio_mixer_put),
5610 SOC_SINGLE_EXT("IIR0 Enable Band5", IIR0, BAND5, 1, 0,
5611 tavil_iir_enable_audio_mixer_get,
5612 tavil_iir_enable_audio_mixer_put),
5613 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
5614 tavil_iir_enable_audio_mixer_get,
5615 tavil_iir_enable_audio_mixer_put),
5616 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
5617 tavil_iir_enable_audio_mixer_get,
5618 tavil_iir_enable_audio_mixer_put),
5619 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
5620 tavil_iir_enable_audio_mixer_get,
5621 tavil_iir_enable_audio_mixer_put),
5622 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
5623 tavil_iir_enable_audio_mixer_get,
5624 tavil_iir_enable_audio_mixer_put),
5625 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
5626 tavil_iir_enable_audio_mixer_get,
5627 tavil_iir_enable_audio_mixer_put),
5628
5629 SOC_SINGLE_MULTI_EXT("IIR0 Band1", IIR0, BAND1, 255, 0, 5,
5630 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5631 SOC_SINGLE_MULTI_EXT("IIR0 Band2", IIR0, BAND2, 255, 0, 5,
5632 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5633 SOC_SINGLE_MULTI_EXT("IIR0 Band3", IIR0, BAND3, 255, 0, 5,
5634 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5635 SOC_SINGLE_MULTI_EXT("IIR0 Band4", IIR0, BAND4, 255, 0, 5,
5636 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5637 SOC_SINGLE_MULTI_EXT("IIR0 Band5", IIR0, BAND5, 255, 0, 5,
5638 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5639 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
5640 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5641 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
5642 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5643 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
5644 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5645 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
5646 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5647 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
5648 tavil_iir_band_audio_mixer_get, tavil_iir_band_audio_mixer_put),
5649
5650 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
5651 tavil_compander_get, tavil_compander_put),
5652 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
5653 tavil_compander_get, tavil_compander_put),
5654 SOC_SINGLE_EXT("COMP3 Switch", SND_SOC_NOPM, COMPANDER_3, 1, 0,
5655 tavil_compander_get, tavil_compander_put),
5656 SOC_SINGLE_EXT("COMP4 Switch", SND_SOC_NOPM, COMPANDER_4, 1, 0,
5657 tavil_compander_get, tavil_compander_put),
5658 SOC_SINGLE_EXT("COMP7 Switch", SND_SOC_NOPM, COMPANDER_7, 1, 0,
5659 tavil_compander_get, tavil_compander_put),
5660 SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
5661 tavil_compander_get, tavil_compander_put),
5662
5663 SOC_ENUM_EXT("ASRC0 Output Mode", asrc_mode_enum,
5664 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5665 SOC_ENUM_EXT("ASRC1 Output Mode", asrc_mode_enum,
5666 tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
5667
5668 SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
5669 tavil_hph_idle_detect_get, tavil_hph_idle_detect_put),
5670
5671 SOC_ENUM_EXT("MAD Input", tavil_conn_mad_enum,
5672 tavil_mad_input_get, tavil_mad_input_put),
5673
5674 SOC_SINGLE_EXT("DMIC1_CLK_PIN_MODE", SND_SOC_NOPM, 17, 1, 0,
5675 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5676
5677 SOC_SINGLE_EXT("DMIC1_DATA_PIN_MODE", SND_SOC_NOPM, 18, 1, 0,
5678 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5679
5680 SOC_SINGLE_EXT("DMIC2_CLK_PIN_MODE", SND_SOC_NOPM, 19, 1, 0,
5681 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5682
5683 SOC_SINGLE_EXT("DMIC2_DATA_PIN_MODE", SND_SOC_NOPM, 20, 1, 0,
5684 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5685
5686 SOC_SINGLE_EXT("DMIC3_CLK_PIN_MODE", SND_SOC_NOPM, 21, 1, 0,
5687 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5688
5689 SOC_SINGLE_EXT("DMIC3_DATA_PIN_MODE", SND_SOC_NOPM, 22, 1, 0,
5690 tavil_dmic_pin_mode_get, tavil_dmic_pin_mode_put),
5691 SOC_ENUM_EXT("AMIC_1_2 PWR MODE", amic_pwr_lvl_enum,
5692 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5693 SOC_ENUM_EXT("AMIC_3_4 PWR MODE", amic_pwr_lvl_enum,
5694 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5695 SOC_ENUM_EXT("AMIC_5_6 PWR MODE", amic_pwr_lvl_enum,
5696 tavil_amic_pwr_lvl_get, tavil_amic_pwr_lvl_put),
5697};
5698
5699static int tavil_dec_enum_put(struct snd_kcontrol *kcontrol,
5700 struct snd_ctl_elem_value *ucontrol)
5701{
5702 struct snd_soc_dapm_widget_list *wlist =
5703 dapm_kcontrol_get_wlist(kcontrol);
5704 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
5705 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
5706 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
5707 unsigned int val;
5708 u16 mic_sel_reg = 0;
5709 u8 mic_sel;
5710
5711 val = ucontrol->value.enumerated.item[0];
5712 if (val > e->items - 1)
5713 return -EINVAL;
5714
5715 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
5716 widget->name, val);
5717
5718 switch (e->reg) {
5719 case WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
5720 if (e->shift_l == 0)
5721 mic_sel_reg = WCD934X_CDC_TX0_TX_PATH_CFG0;
5722 else if (e->shift_l == 2)
5723 mic_sel_reg = WCD934X_CDC_TX4_TX_PATH_CFG0;
5724 else if (e->shift_l == 4)
5725 mic_sel_reg = WCD934X_CDC_TX8_TX_PATH_CFG0;
5726 break;
5727 case WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
5728 if (e->shift_l == 0)
5729 mic_sel_reg = WCD934X_CDC_TX1_TX_PATH_CFG0;
5730 else if (e->shift_l == 2)
5731 mic_sel_reg = WCD934X_CDC_TX5_TX_PATH_CFG0;
5732 break;
5733 case WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
5734 if (e->shift_l == 0)
5735 mic_sel_reg = WCD934X_CDC_TX2_TX_PATH_CFG0;
5736 else if (e->shift_l == 2)
5737 mic_sel_reg = WCD934X_CDC_TX6_TX_PATH_CFG0;
5738 break;
5739 case WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
5740 if (e->shift_l == 0)
5741 mic_sel_reg = WCD934X_CDC_TX3_TX_PATH_CFG0;
5742 else if (e->shift_l == 2)
5743 mic_sel_reg = WCD934X_CDC_TX7_TX_PATH_CFG0;
5744 break;
5745 default:
5746 dev_err(codec->dev, "%s: e->reg: 0x%x not expected\n",
5747 __func__, e->reg);
5748 return -EINVAL;
5749 }
5750
5751 /* ADC: 0, DMIC: 1 */
5752 mic_sel = val ? 0x0 : 0x1;
5753 if (mic_sel_reg)
5754 snd_soc_update_bits(codec, mic_sel_reg, 1 << 7, mic_sel << 7);
5755
5756 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
5757}
5758
5759static int tavil_int_dem_inp_mux_put(struct snd_kcontrol *kcontrol,
5760 struct snd_ctl_elem_value *ucontrol)
5761{
5762 struct snd_soc_dapm_widget_list *wlist =
5763 dapm_kcontrol_get_wlist(kcontrol);
5764 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
5765 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
5766 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
5767 unsigned int val;
5768 unsigned short look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
5769
5770 val = ucontrol->value.enumerated.item[0];
5771 if (val >= e->items)
5772 return -EINVAL;
5773
5774 dev_dbg(codec->dev, "%s: wname: %s, val: 0x%x\n", __func__,
5775 widget->name, val);
5776
5777 if (e->reg == WCD934X_CDC_RX0_RX_PATH_SEC0)
5778 look_ahead_dly_reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
5779 else if (e->reg == WCD934X_CDC_RX1_RX_PATH_SEC0)
5780 look_ahead_dly_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
5781 else if (e->reg == WCD934X_CDC_RX2_RX_PATH_SEC0)
5782 look_ahead_dly_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
5783
5784 /* Set Look Ahead Delay */
5785 snd_soc_update_bits(codec, look_ahead_dly_reg,
5786 0x08, (val ? 0x08 : 0x00));
5787 /* Set DEM INP Select */
5788 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
5789}
5790
5791static const char * const rx_int0_7_mix_mux_text[] = {
5792 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
5793 "RX6", "RX7", "PROXIMITY"
5794};
5795
5796static const char * const rx_int_mix_mux_text[] = {
5797 "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
5798 "RX6", "RX7"
5799};
5800
5801static const char * const rx_prim_mix_text[] = {
5802 "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
5803 "RX3", "RX4", "RX5", "RX6", "RX7"
5804};
5805
5806static const char * const rx_sidetone_mix_text[] = {
5807 "ZERO", "SRC0", "SRC1", "SRC_SUM"
5808};
5809
5810static const char * const cdc_if_tx0_mux_text[] = {
5811 "ZERO", "RX_MIX_TX0", "DEC0", "DEC0_192"
5812};
5813static const char * const cdc_if_tx1_mux_text[] = {
5814 "ZERO", "RX_MIX_TX1", "DEC1", "DEC1_192"
5815};
5816static const char * const cdc_if_tx2_mux_text[] = {
5817 "ZERO", "RX_MIX_TX2", "DEC2", "DEC2_192"
5818};
5819static const char * const cdc_if_tx3_mux_text[] = {
5820 "ZERO", "RX_MIX_TX3", "DEC3", "DEC3_192"
5821};
5822static const char * const cdc_if_tx4_mux_text[] = {
5823 "ZERO", "RX_MIX_TX4", "DEC4", "DEC4_192"
5824};
5825static const char * const cdc_if_tx5_mux_text[] = {
5826 "ZERO", "RX_MIX_TX5", "DEC5", "DEC5_192"
5827};
5828static const char * const cdc_if_tx6_mux_text[] = {
5829 "ZERO", "RX_MIX_TX6", "DEC6", "DEC6_192"
5830};
5831static const char * const cdc_if_tx7_mux_text[] = {
5832 "ZERO", "RX_MIX_TX7", "DEC7", "DEC7_192"
5833};
5834static const char * const cdc_if_tx8_mux_text[] = {
5835 "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
5836};
5837static const char * const cdc_if_tx9_mux_text[] = {
5838 "ZERO", "DEC7", "DEC7_192"
5839};
5840static const char * const cdc_if_tx10_mux_text[] = {
5841 "ZERO", "DEC6", "DEC6_192"
5842};
5843static const char * const cdc_if_tx11_mux_text[] = {
5844 "DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
5845};
5846static const char * const cdc_if_tx11_inp1_mux_text[] = {
5847 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4",
5848 "DEC5", "RX_MIX_TX5", "DEC9_10", "DEC11_12"
5849};
5850static const char * const cdc_if_tx13_mux_text[] = {
5851 "CDC_DEC_5", "MAD_BRDCST"
5852};
5853static const char * const cdc_if_tx13_inp1_mux_text[] = {
5854 "ZERO", "DEC5", "DEC5_192"
5855};
5856
5857static const char * const iir_inp_mux_text[] = {
5858 "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6",
5859 "DEC7", "DEC8", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
5860};
5861
5862static const char * const rx_int_dem_inp_mux_text[] = {
5863 "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
5864};
5865
5866static const char * const rx_int0_1_interp_mux_text[] = {
5867 "ZERO", "RX INT0_1 MIX1",
5868};
5869
5870static const char * const rx_int1_1_interp_mux_text[] = {
5871 "ZERO", "RX INT1_1 MIX1",
5872};
5873
5874static const char * const rx_int2_1_interp_mux_text[] = {
5875 "ZERO", "RX INT2_1 MIX1",
5876};
5877
5878static const char * const rx_int3_1_interp_mux_text[] = {
5879 "ZERO", "RX INT3_1 MIX1",
5880};
5881
5882static const char * const rx_int4_1_interp_mux_text[] = {
5883 "ZERO", "RX INT4_1 MIX1",
5884};
5885
5886static const char * const rx_int7_1_interp_mux_text[] = {
5887 "ZERO", "RX INT7_1 MIX1",
5888};
5889
5890static const char * const rx_int8_1_interp_mux_text[] = {
5891 "ZERO", "RX INT8_1 MIX1",
5892};
5893
5894static const char * const rx_int0_2_interp_mux_text[] = {
5895 "ZERO", "RX INT0_2 MUX",
5896};
5897
5898static const char * const rx_int1_2_interp_mux_text[] = {
5899 "ZERO", "RX INT1_2 MUX",
5900};
5901
5902static const char * const rx_int2_2_interp_mux_text[] = {
5903 "ZERO", "RX INT2_2 MUX",
5904};
5905
5906static const char * const rx_int3_2_interp_mux_text[] = {
5907 "ZERO", "RX INT3_2 MUX",
5908};
5909
5910static const char * const rx_int4_2_interp_mux_text[] = {
5911 "ZERO", "RX INT4_2 MUX",
5912};
5913
5914static const char * const rx_int7_2_interp_mux_text[] = {
5915 "ZERO", "RX INT7_2 MUX",
5916};
5917
5918static const char * const rx_int8_2_interp_mux_text[] = {
5919 "ZERO", "RX INT8_2 MUX",
5920};
5921
5922static const char * const mad_sel_txt[] = {
5923 "SPE", "MSM"
5924};
5925
5926static const char * const mad_inp_mux_txt[] = {
5927 "MAD", "DEC1"
5928};
5929
5930static const char * const adc_mux_text[] = {
5931 "DMIC", "AMIC", "ANC_FB_TUNE1", "ANC_FB_TUNE2"
5932};
5933
5934static const char * const dmic_mux_text[] = {
5935 "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5"
5936};
5937
5938static const char * const amic_mux_text[] = {
5939 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4"
5940};
5941
5942static const char * const amic4_5_sel_text[] = {
5943 "AMIC4", "AMIC5"
5944};
5945
5946static const char * const anc0_fb_mux_text[] = {
5947 "ZERO", "ANC_IN_HPHL", "ANC_IN_EAR", "ANC_IN_EAR_SPKR",
5948 "ANC_IN_LO1"
5949};
5950
5951static const char * const anc1_fb_mux_text[] = {
5952 "ZERO", "ANC_IN_HPHR", "ANC_IN_LO2"
5953};
5954
5955static const char * const rx_echo_mux_text[] = {
5956 "ZERO", "RX_MIX0", "RX_MIX1", "RX_MIX2", "RX_MIX3", "RX_MIX4",
5957 "RX_MIX5", "RX_MIX6", "RX_MIX7", "RX_MIX8"
5958};
5959
5960static const char *const slim_rx_mux_text[] = {
5961 "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB"
5962};
5963
5964static const char *const cdc_if_rx0_mux_text[] = {
5965 "SLIM RX0", "I2S_0 RX0"
5966};
5967static const char *const cdc_if_rx1_mux_text[] = {
5968 "SLIM RX1", "I2S_0 RX1"
5969};
5970static const char *const cdc_if_rx2_mux_text[] = {
5971 "SLIM RX2", "I2S_0 RX2"
5972};
5973static const char *const cdc_if_rx3_mux_text[] = {
5974 "SLIM RX3", "I2S_0 RX3"
5975};
5976static const char *const cdc_if_rx4_mux_text[] = {
5977 "SLIM RX4", "I2S_0 RX4"
5978};
5979static const char *const cdc_if_rx5_mux_text[] = {
5980 "SLIM RX5", "I2S_0 RX5"
5981};
5982static const char *const cdc_if_rx6_mux_text[] = {
5983 "SLIM RX6", "I2S_0 RX6"
5984};
5985static const char *const cdc_if_rx7_mux_text[] = {
5986 "SLIM RX7", "I2S_0 RX7"
5987};
5988
5989static const char * const asrc0_mux_text[] = {
5990 "ZERO", "ASRC_IN_HPHL", "ASRC_IN_LO1",
5991};
5992
5993static const char * const asrc1_mux_text[] = {
5994 "ZERO", "ASRC_IN_HPHR", "ASRC_IN_LO2",
5995};
5996
5997static const char * const asrc2_mux_text[] = {
5998 "ZERO", "ASRC_IN_SPKR1",
5999};
6000
6001static const char * const asrc3_mux_text[] = {
6002 "ZERO", "ASRC_IN_SPKR2",
6003};
6004
6005static const char * const native_mux_text[] = {
6006 "OFF", "ON",
6007};
6008
6009static const struct snd_kcontrol_new aif4_vi_mixer[] = {
6010 SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
6011 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6012 SOC_SINGLE_EXT("SPKR_VI_2", SND_SOC_NOPM, WCD934X_TX15, 1, 0,
6013 tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
6014};
6015
6016static const struct snd_kcontrol_new aif1_cap_mixer[] = {
6017 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6018 slim_tx_mixer_get, slim_tx_mixer_put),
6019 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6020 slim_tx_mixer_get, slim_tx_mixer_put),
6021 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6022 slim_tx_mixer_get, slim_tx_mixer_put),
6023 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6024 slim_tx_mixer_get, slim_tx_mixer_put),
6025 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6026 slim_tx_mixer_get, slim_tx_mixer_put),
6027 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6028 slim_tx_mixer_get, slim_tx_mixer_put),
6029 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6030 slim_tx_mixer_get, slim_tx_mixer_put),
6031 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6032 slim_tx_mixer_get, slim_tx_mixer_put),
6033 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6034 slim_tx_mixer_get, slim_tx_mixer_put),
6035 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6036 slim_tx_mixer_get, slim_tx_mixer_put),
6037 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6038 slim_tx_mixer_get, slim_tx_mixer_put),
6039 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6040 slim_tx_mixer_get, slim_tx_mixer_put),
6041 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6042 slim_tx_mixer_get, slim_tx_mixer_put),
6043};
6044
6045static const struct snd_kcontrol_new aif2_cap_mixer[] = {
6046 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6047 slim_tx_mixer_get, slim_tx_mixer_put),
6048 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6049 slim_tx_mixer_get, slim_tx_mixer_put),
6050 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6051 slim_tx_mixer_get, slim_tx_mixer_put),
6052 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6053 slim_tx_mixer_get, slim_tx_mixer_put),
6054 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6055 slim_tx_mixer_get, slim_tx_mixer_put),
6056 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6057 slim_tx_mixer_get, slim_tx_mixer_put),
6058 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6059 slim_tx_mixer_get, slim_tx_mixer_put),
6060 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6061 slim_tx_mixer_get, slim_tx_mixer_put),
6062 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6063 slim_tx_mixer_get, slim_tx_mixer_put),
6064 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6065 slim_tx_mixer_get, slim_tx_mixer_put),
6066 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6067 slim_tx_mixer_get, slim_tx_mixer_put),
6068 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6069 slim_tx_mixer_get, slim_tx_mixer_put),
6070 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6071 slim_tx_mixer_get, slim_tx_mixer_put),
6072};
6073
6074static const struct snd_kcontrol_new aif3_cap_mixer[] = {
6075 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
6076 slim_tx_mixer_get, slim_tx_mixer_put),
6077 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
6078 slim_tx_mixer_get, slim_tx_mixer_put),
6079 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
6080 slim_tx_mixer_get, slim_tx_mixer_put),
6081 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
6082 slim_tx_mixer_get, slim_tx_mixer_put),
6083 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
6084 slim_tx_mixer_get, slim_tx_mixer_put),
6085 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
6086 slim_tx_mixer_get, slim_tx_mixer_put),
6087 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
6088 slim_tx_mixer_get, slim_tx_mixer_put),
6089 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
6090 slim_tx_mixer_get, slim_tx_mixer_put),
6091 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
6092 slim_tx_mixer_get, slim_tx_mixer_put),
6093 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
6094 slim_tx_mixer_get, slim_tx_mixer_put),
6095 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
6096 slim_tx_mixer_get, slim_tx_mixer_put),
6097 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
6098 slim_tx_mixer_get, slim_tx_mixer_put),
6099 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6100 slim_tx_mixer_get, slim_tx_mixer_put),
6101};
6102
6103static const struct snd_kcontrol_new aif4_mad_mixer[] = {
6104 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
6105 slim_tx_mixer_get, slim_tx_mixer_put),
6106};
6107
6108WCD_DAPM_ENUM_EXT(slim_rx0, SND_SOC_NOPM, 0, slim_rx_mux_text,
6109 slim_rx_mux_get, slim_rx_mux_put);
6110WCD_DAPM_ENUM_EXT(slim_rx1, SND_SOC_NOPM, 0, slim_rx_mux_text,
6111 slim_rx_mux_get, slim_rx_mux_put);
6112WCD_DAPM_ENUM_EXT(slim_rx2, SND_SOC_NOPM, 0, slim_rx_mux_text,
6113 slim_rx_mux_get, slim_rx_mux_put);
6114WCD_DAPM_ENUM_EXT(slim_rx3, SND_SOC_NOPM, 0, slim_rx_mux_text,
6115 slim_rx_mux_get, slim_rx_mux_put);
6116WCD_DAPM_ENUM_EXT(slim_rx4, SND_SOC_NOPM, 0, slim_rx_mux_text,
6117 slim_rx_mux_get, slim_rx_mux_put);
6118WCD_DAPM_ENUM_EXT(slim_rx5, SND_SOC_NOPM, 0, slim_rx_mux_text,
6119 slim_rx_mux_get, slim_rx_mux_put);
6120WCD_DAPM_ENUM_EXT(slim_rx6, SND_SOC_NOPM, 0, slim_rx_mux_text,
6121 slim_rx_mux_get, slim_rx_mux_put);
6122WCD_DAPM_ENUM_EXT(slim_rx7, SND_SOC_NOPM, 0, slim_rx_mux_text,
6123 slim_rx_mux_get, slim_rx_mux_put);
6124
6125WCD_DAPM_ENUM(cdc_if_rx0, SND_SOC_NOPM, 0, cdc_if_rx0_mux_text);
6126WCD_DAPM_ENUM(cdc_if_rx1, SND_SOC_NOPM, 0, cdc_if_rx1_mux_text);
6127WCD_DAPM_ENUM(cdc_if_rx2, SND_SOC_NOPM, 0, cdc_if_rx2_mux_text);
6128WCD_DAPM_ENUM(cdc_if_rx3, SND_SOC_NOPM, 0, cdc_if_rx3_mux_text);
6129WCD_DAPM_ENUM(cdc_if_rx4, SND_SOC_NOPM, 0, cdc_if_rx4_mux_text);
6130WCD_DAPM_ENUM(cdc_if_rx5, SND_SOC_NOPM, 0, cdc_if_rx5_mux_text);
6131WCD_DAPM_ENUM(cdc_if_rx6, SND_SOC_NOPM, 0, cdc_if_rx6_mux_text);
6132WCD_DAPM_ENUM(cdc_if_rx7, SND_SOC_NOPM, 0, cdc_if_rx7_mux_text);
6133
6134WCD_DAPM_ENUM(rx_int0_2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 0,
6135 rx_int0_7_mix_mux_text);
6136WCD_DAPM_ENUM(rx_int1_2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 0,
6137 rx_int_mix_mux_text);
6138WCD_DAPM_ENUM(rx_int2_2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 0,
6139 rx_int_mix_mux_text);
6140WCD_DAPM_ENUM(rx_int3_2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 0,
6141 rx_int_mix_mux_text);
6142WCD_DAPM_ENUM(rx_int4_2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0,
6143 rx_int_mix_mux_text);
6144WCD_DAPM_ENUM(rx_int7_2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 0,
6145 rx_int0_7_mix_mux_text);
6146WCD_DAPM_ENUM(rx_int8_2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 0,
6147 rx_int_mix_mux_text);
6148
6149WCD_DAPM_ENUM(rx_int0_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 0,
6150 rx_prim_mix_text);
6151WCD_DAPM_ENUM(rx_int0_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 4,
6152 rx_prim_mix_text);
6153WCD_DAPM_ENUM(rx_int0_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 4,
6154 rx_prim_mix_text);
6155WCD_DAPM_ENUM(rx_int1_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 0,
6156 rx_prim_mix_text);
6157WCD_DAPM_ENUM(rx_int1_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 4,
6158 rx_prim_mix_text);
6159WCD_DAPM_ENUM(rx_int1_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 4,
6160 rx_prim_mix_text);
6161WCD_DAPM_ENUM(rx_int2_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 0,
6162 rx_prim_mix_text);
6163WCD_DAPM_ENUM(rx_int2_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 4,
6164 rx_prim_mix_text);
6165WCD_DAPM_ENUM(rx_int2_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 4,
6166 rx_prim_mix_text);
6167WCD_DAPM_ENUM(rx_int3_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 0,
6168 rx_prim_mix_text);
6169WCD_DAPM_ENUM(rx_int3_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 4,
6170 rx_prim_mix_text);
6171WCD_DAPM_ENUM(rx_int3_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 4,
6172 rx_prim_mix_text);
6173WCD_DAPM_ENUM(rx_int4_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 0,
6174 rx_prim_mix_text);
6175WCD_DAPM_ENUM(rx_int4_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 4,
6176 rx_prim_mix_text);
6177WCD_DAPM_ENUM(rx_int4_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4,
6178 rx_prim_mix_text);
6179WCD_DAPM_ENUM(rx_int7_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 0,
6180 rx_prim_mix_text);
6181WCD_DAPM_ENUM(rx_int7_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 4,
6182 rx_prim_mix_text);
6183WCD_DAPM_ENUM(rx_int7_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 4,
6184 rx_prim_mix_text);
6185WCD_DAPM_ENUM(rx_int8_1_mix_inp0, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 0,
6186 rx_prim_mix_text);
6187WCD_DAPM_ENUM(rx_int8_1_mix_inp1, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 4,
6188 rx_prim_mix_text);
6189WCD_DAPM_ENUM(rx_int8_1_mix_inp2, WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4,
6190 rx_prim_mix_text);
6191
6192WCD_DAPM_ENUM(rx_int0_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0,
6193 rx_sidetone_mix_text);
6194WCD_DAPM_ENUM(rx_int1_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2,
6195 rx_sidetone_mix_text);
6196WCD_DAPM_ENUM(rx_int2_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4,
6197 rx_sidetone_mix_text);
6198WCD_DAPM_ENUM(rx_int3_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6,
6199 rx_sidetone_mix_text);
6200WCD_DAPM_ENUM(rx_int4_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0,
6201 rx_sidetone_mix_text);
6202WCD_DAPM_ENUM(rx_int7_mix2_inp, WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2,
6203 rx_sidetone_mix_text);
6204
6205WCD_DAPM_ENUM(tx_adc_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
6206 adc_mux_text);
6207WCD_DAPM_ENUM(tx_adc_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 4,
6208 adc_mux_text);
6209WCD_DAPM_ENUM(tx_adc_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 4,
6210 adc_mux_text);
6211WCD_DAPM_ENUM(tx_adc_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 6,
6212 adc_mux_text);
6213
6214
6215WCD_DAPM_ENUM(tx_dmic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3,
6216 dmic_mux_text);
6217WCD_DAPM_ENUM(tx_dmic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3,
6218 dmic_mux_text);
6219WCD_DAPM_ENUM(tx_dmic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3,
6220 dmic_mux_text);
6221WCD_DAPM_ENUM(tx_dmic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3,
6222 dmic_mux_text);
6223WCD_DAPM_ENUM(tx_dmic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3,
6224 dmic_mux_text);
6225WCD_DAPM_ENUM(tx_dmic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3,
6226 dmic_mux_text);
6227WCD_DAPM_ENUM(tx_dmic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3,
6228 dmic_mux_text);
6229WCD_DAPM_ENUM(tx_dmic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3,
6230 dmic_mux_text);
6231WCD_DAPM_ENUM(tx_dmic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3,
6232 dmic_mux_text);
6233WCD_DAPM_ENUM(tx_dmic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 3,
6234 dmic_mux_text);
6235WCD_DAPM_ENUM(tx_dmic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 3,
6236 dmic_mux_text);
6237WCD_DAPM_ENUM(tx_dmic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 3,
6238 dmic_mux_text);
6239WCD_DAPM_ENUM(tx_dmic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 3,
6240 dmic_mux_text);
6241
6242
6243WCD_DAPM_ENUM(tx_amic_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0,
6244 amic_mux_text);
6245WCD_DAPM_ENUM(tx_amic_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0,
6246 amic_mux_text);
6247WCD_DAPM_ENUM(tx_amic_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0,
6248 amic_mux_text);
6249WCD_DAPM_ENUM(tx_amic_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0,
6250 amic_mux_text);
6251WCD_DAPM_ENUM(tx_amic_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0,
6252 amic_mux_text);
6253WCD_DAPM_ENUM(tx_amic_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0,
6254 amic_mux_text);
6255WCD_DAPM_ENUM(tx_amic_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0,
6256 amic_mux_text);
6257WCD_DAPM_ENUM(tx_amic_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0,
6258 amic_mux_text);
6259WCD_DAPM_ENUM(tx_amic_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0,
6260 amic_mux_text);
6261WCD_DAPM_ENUM(tx_amic_mux10, WCD934X_CDC_TX_INP_MUX_ADC_MUX10_CFG0, 0,
6262 amic_mux_text);
6263WCD_DAPM_ENUM(tx_amic_mux11, WCD934X_CDC_TX_INP_MUX_ADC_MUX11_CFG0, 0,
6264 amic_mux_text);
6265WCD_DAPM_ENUM(tx_amic_mux12, WCD934X_CDC_TX_INP_MUX_ADC_MUX12_CFG0, 0,
6266 amic_mux_text);
6267WCD_DAPM_ENUM(tx_amic_mux13, WCD934X_CDC_TX_INP_MUX_ADC_MUX13_CFG0, 0,
6268 amic_mux_text);
6269
6270WCD_DAPM_ENUM(tx_amic4_5, WCD934X_TX_NEW_AMIC_4_5_SEL, 7, amic4_5_sel_text);
6271
6272WCD_DAPM_ENUM(cdc_if_tx0, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
6273 cdc_if_tx0_mux_text);
6274WCD_DAPM_ENUM(cdc_if_tx1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
6275 cdc_if_tx1_mux_text);
6276WCD_DAPM_ENUM(cdc_if_tx2, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
6277 cdc_if_tx2_mux_text);
6278WCD_DAPM_ENUM(cdc_if_tx3, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
6279 cdc_if_tx3_mux_text);
6280WCD_DAPM_ENUM(cdc_if_tx4, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
6281 cdc_if_tx4_mux_text);
6282WCD_DAPM_ENUM(cdc_if_tx5, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
6283 cdc_if_tx5_mux_text);
6284WCD_DAPM_ENUM(cdc_if_tx6, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
6285 cdc_if_tx6_mux_text);
6286WCD_DAPM_ENUM(cdc_if_tx7, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
6287 cdc_if_tx7_mux_text);
6288WCD_DAPM_ENUM(cdc_if_tx8, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
6289 cdc_if_tx8_mux_text);
6290WCD_DAPM_ENUM(cdc_if_tx9, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
6291 cdc_if_tx9_mux_text);
6292WCD_DAPM_ENUM(cdc_if_tx10, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
6293 cdc_if_tx10_mux_text);
6294WCD_DAPM_ENUM(cdc_if_tx11_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
6295 cdc_if_tx11_inp1_mux_text);
6296WCD_DAPM_ENUM(cdc_if_tx11, WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
6297 cdc_if_tx11_mux_text);
6298WCD_DAPM_ENUM(cdc_if_tx13_inp1, WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
6299 cdc_if_tx13_inp1_mux_text);
6300WCD_DAPM_ENUM(cdc_if_tx13, WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
6301 cdc_if_tx13_mux_text);
6302
6303WCD_DAPM_ENUM(rx_mix_tx0, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 0,
6304 rx_echo_mux_text);
6305WCD_DAPM_ENUM(rx_mix_tx1, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG0, 4,
6306 rx_echo_mux_text);
6307WCD_DAPM_ENUM(rx_mix_tx2, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 0,
6308 rx_echo_mux_text);
6309WCD_DAPM_ENUM(rx_mix_tx3, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG1, 4,
6310 rx_echo_mux_text);
6311WCD_DAPM_ENUM(rx_mix_tx4, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 0,
6312 rx_echo_mux_text);
6313WCD_DAPM_ENUM(rx_mix_tx5, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG2, 4,
6314 rx_echo_mux_text);
6315WCD_DAPM_ENUM(rx_mix_tx6, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 0,
6316 rx_echo_mux_text);
6317WCD_DAPM_ENUM(rx_mix_tx7, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG3, 4,
6318 rx_echo_mux_text);
6319WCD_DAPM_ENUM(rx_mix_tx8, WCD934X_CDC_RX_INP_MUX_RX_MIX_CFG4, 0,
6320 rx_echo_mux_text);
6321
6322WCD_DAPM_ENUM(iir0_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0, 0,
6323 iir_inp_mux_text);
6324WCD_DAPM_ENUM(iir0_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1, 0,
6325 iir_inp_mux_text);
6326WCD_DAPM_ENUM(iir0_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2, 0,
6327 iir_inp_mux_text);
6328WCD_DAPM_ENUM(iir0_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3, 0,
6329 iir_inp_mux_text);
6330WCD_DAPM_ENUM(iir1_inp0, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0, 0,
6331 iir_inp_mux_text);
6332WCD_DAPM_ENUM(iir1_inp1, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1, 0,
6333 iir_inp_mux_text);
6334WCD_DAPM_ENUM(iir1_inp2, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2, 0,
6335 iir_inp_mux_text);
6336WCD_DAPM_ENUM(iir1_inp3, WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3, 0,
6337 iir_inp_mux_text);
6338
6339WCD_DAPM_ENUM(rx_int0_1_interp, SND_SOC_NOPM, 0, rx_int0_1_interp_mux_text);
6340WCD_DAPM_ENUM(rx_int1_1_interp, SND_SOC_NOPM, 0, rx_int1_1_interp_mux_text);
6341WCD_DAPM_ENUM(rx_int2_1_interp, SND_SOC_NOPM, 0, rx_int2_1_interp_mux_text);
6342WCD_DAPM_ENUM(rx_int3_1_interp, SND_SOC_NOPM, 0, rx_int3_1_interp_mux_text);
6343WCD_DAPM_ENUM(rx_int4_1_interp, SND_SOC_NOPM, 0, rx_int4_1_interp_mux_text);
6344WCD_DAPM_ENUM(rx_int7_1_interp, SND_SOC_NOPM, 0, rx_int7_1_interp_mux_text);
6345WCD_DAPM_ENUM(rx_int8_1_interp, SND_SOC_NOPM, 0, rx_int8_1_interp_mux_text);
6346
6347WCD_DAPM_ENUM(rx_int0_2_interp, SND_SOC_NOPM, 0, rx_int0_2_interp_mux_text);
6348WCD_DAPM_ENUM(rx_int1_2_interp, SND_SOC_NOPM, 0, rx_int1_2_interp_mux_text);
6349WCD_DAPM_ENUM(rx_int2_2_interp, SND_SOC_NOPM, 0, rx_int2_2_interp_mux_text);
6350WCD_DAPM_ENUM(rx_int3_2_interp, SND_SOC_NOPM, 0, rx_int3_2_interp_mux_text);
6351WCD_DAPM_ENUM(rx_int4_2_interp, SND_SOC_NOPM, 0, rx_int4_2_interp_mux_text);
6352WCD_DAPM_ENUM(rx_int7_2_interp, SND_SOC_NOPM, 0, rx_int7_2_interp_mux_text);
6353WCD_DAPM_ENUM(rx_int8_2_interp, SND_SOC_NOPM, 0, rx_int8_2_interp_mux_text);
6354
6355WCD_DAPM_ENUM(mad_sel, WCD934X_CPE_SS_SVA_CFG, 0,
6356 mad_sel_txt);
6357
6358WCD_DAPM_ENUM(mad_inp_mux, WCD934X_CPE_SS_SVA_CFG, 2,
6359 mad_inp_mux_txt);
6360
6361WCD_DAPM_ENUM_EXT(rx_int0_dem_inp, WCD934X_CDC_RX0_RX_PATH_SEC0, 0,
6362 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6363 tavil_int_dem_inp_mux_put);
6364WCD_DAPM_ENUM_EXT(rx_int1_dem_inp, WCD934X_CDC_RX1_RX_PATH_SEC0, 0,
6365 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6366 tavil_int_dem_inp_mux_put);
6367WCD_DAPM_ENUM_EXT(rx_int2_dem_inp, WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
6368 rx_int_dem_inp_mux_text, snd_soc_dapm_get_enum_double,
6369 tavil_int_dem_inp_mux_put);
6370
6371WCD_DAPM_ENUM_EXT(tx_adc_mux0, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
6372 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6373WCD_DAPM_ENUM_EXT(tx_adc_mux1, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
6374 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6375WCD_DAPM_ENUM_EXT(tx_adc_mux2, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
6376 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6377WCD_DAPM_ENUM_EXT(tx_adc_mux3, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
6378 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6379WCD_DAPM_ENUM_EXT(tx_adc_mux4, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
6380 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6381WCD_DAPM_ENUM_EXT(tx_adc_mux5, WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
6382 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6383WCD_DAPM_ENUM_EXT(tx_adc_mux6, WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
6384 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6385WCD_DAPM_ENUM_EXT(tx_adc_mux7, WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
6386 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6387WCD_DAPM_ENUM_EXT(tx_adc_mux8, WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 4,
6388 adc_mux_text, snd_soc_dapm_get_enum_double, tavil_dec_enum_put);
6389
6390WCD_DAPM_ENUM(asrc0, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 0,
6391 asrc0_mux_text);
6392WCD_DAPM_ENUM(asrc1, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 2,
6393 asrc1_mux_text);
6394WCD_DAPM_ENUM(asrc2, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 4,
6395 asrc2_mux_text);
6396WCD_DAPM_ENUM(asrc3, WCD934X_CDC_RX_INP_MUX_SPLINE_ASRC_CFG0, 6,
6397 asrc3_mux_text);
6398
6399WCD_DAPM_ENUM(int1_1_native, SND_SOC_NOPM, 0, native_mux_text);
6400WCD_DAPM_ENUM(int2_1_native, SND_SOC_NOPM, 0, native_mux_text);
6401WCD_DAPM_ENUM(int3_1_native, SND_SOC_NOPM, 0, native_mux_text);
6402WCD_DAPM_ENUM(int4_1_native, SND_SOC_NOPM, 0, native_mux_text);
6403
6404WCD_DAPM_ENUM(int1_2_native, SND_SOC_NOPM, 0, native_mux_text);
6405WCD_DAPM_ENUM(int2_2_native, SND_SOC_NOPM, 0, native_mux_text);
6406WCD_DAPM_ENUM(int3_2_native, SND_SOC_NOPM, 0, native_mux_text);
6407WCD_DAPM_ENUM(int4_2_native, SND_SOC_NOPM, 0, native_mux_text);
6408WCD_DAPM_ENUM(int7_2_native, SND_SOC_NOPM, 0, native_mux_text);
6409WCD_DAPM_ENUM(int8_2_native, SND_SOC_NOPM, 0, native_mux_text);
6410
6411WCD_DAPM_ENUM(anc0_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
6412WCD_DAPM_ENUM(anc1_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
6413
6414static const struct snd_kcontrol_new anc_ear_switch =
6415 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6416
6417static const struct snd_kcontrol_new anc_ear_spkr_switch =
6418 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6419
6420static const struct snd_kcontrol_new anc_spkr_pa_switch =
6421 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6422
6423static const struct snd_kcontrol_new mad_cpe1_switch =
6424 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6425
6426static const struct snd_kcontrol_new mad_cpe2_switch =
6427 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6428
6429static const struct snd_kcontrol_new mad_brdcst_switch =
6430 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
6431
6432static const struct snd_kcontrol_new adc_us_mux0_switch =
6433 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6434
6435static const struct snd_kcontrol_new adc_us_mux1_switch =
6436 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6437
6438static const struct snd_kcontrol_new adc_us_mux2_switch =
6439 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6440
6441static const struct snd_kcontrol_new adc_us_mux3_switch =
6442 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6443
6444static const struct snd_kcontrol_new adc_us_mux4_switch =
6445 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6446
6447static const struct snd_kcontrol_new adc_us_mux5_switch =
6448 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6449
6450static const struct snd_kcontrol_new adc_us_mux6_switch =
6451 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6452
6453static const struct snd_kcontrol_new adc_us_mux7_switch =
6454 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6455
6456static const struct snd_kcontrol_new adc_us_mux8_switch =
6457 SOC_DAPM_SINGLE("US_Switch", SND_SOC_NOPM, 0, 1, 0);
6458
6459static const struct snd_kcontrol_new rx_int1_asrc_switch[] = {
6460 SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
6461};
6462
6463static const struct snd_kcontrol_new rx_int2_asrc_switch[] = {
6464 SOC_DAPM_SINGLE("HPHR Switch", SND_SOC_NOPM, 0, 1, 0),
6465};
6466
6467static const struct snd_kcontrol_new rx_int3_asrc_switch[] = {
6468 SOC_DAPM_SINGLE("LO1 Switch", SND_SOC_NOPM, 0, 1, 0),
6469};
6470
6471static const struct snd_kcontrol_new rx_int4_asrc_switch[] = {
6472 SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
6473};
6474
6475static int tavil_dsd_mixer_get(struct snd_kcontrol *kcontrol,
6476 struct snd_ctl_elem_value *ucontrol)
6477{
6478 struct snd_soc_dapm_context *dapm =
6479 snd_soc_dapm_kcontrol_dapm(kcontrol);
6480 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6481 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6482 struct soc_mixer_control *mc =
6483 (struct soc_mixer_control *)kcontrol->private_value;
6484 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6485 int val;
6486
6487 val = tavil_dsd_get_current_mixer_value(dsd_conf, mc->shift);
6488
6489 ucontrol->value.integer.value[0] = ((val < 0) ? 0 : val);
6490
6491 return 0;
6492}
6493
6494static int tavil_dsd_mixer_put(struct snd_kcontrol *kcontrol,
6495 struct snd_ctl_elem_value *ucontrol)
6496{
6497 struct soc_mixer_control *mc =
6498 (struct soc_mixer_control *)kcontrol->private_value;
6499 struct snd_soc_dapm_context *dapm =
6500 snd_soc_dapm_kcontrol_dapm(kcontrol);
6501 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
6502 struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
6503 unsigned int wval = ucontrol->value.integer.value[0];
6504 struct tavil_dsd_config *dsd_conf = tavil_p->dsd_config;
6505
6506 if (!dsd_conf)
6507 return 0;
6508
6509 mutex_lock(&tavil_p->codec_mutex);
6510
6511 tavil_dsd_set_out_select(dsd_conf, mc->shift);
6512 tavil_dsd_set_mixer_value(dsd_conf, mc->shift, wval);
6513
6514 mutex_unlock(&tavil_p->codec_mutex);
6515 snd_soc_dapm_mixer_update_power(dapm, kcontrol, wval, NULL);
6516
6517 return 0;
6518}
6519
6520static const struct snd_kcontrol_new hphl_mixer[] = {
6521 SOC_SINGLE_EXT("DSD HPHL Switch", SND_SOC_NOPM, INTERP_HPHL, 1, 0,
6522 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6523};
6524
6525static const struct snd_kcontrol_new hphr_mixer[] = {
6526 SOC_SINGLE_EXT("DSD HPHR Switch", SND_SOC_NOPM, INTERP_HPHR, 1, 0,
6527 tavil_dsd_mixer_get, tavil_dsd_mixer_put),
6528};
6529
6530static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
6531 SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
6532 AIF1_PB, 0, tavil_codec_enable_slimrx,
6533 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6534 SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
6535 AIF2_PB, 0, tavil_codec_enable_slimrx,
6536 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6537 SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
6538 AIF3_PB, 0, tavil_codec_enable_slimrx,
6539 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6540 SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
6541 AIF4_PB, 0, tavil_codec_enable_slimrx,
6542 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6543
6544 WCD_DAPM_MUX("SLIM RX0 MUX", WCD934X_RX0, slim_rx0),
6545 WCD_DAPM_MUX("SLIM RX1 MUX", WCD934X_RX1, slim_rx1),
6546 WCD_DAPM_MUX("SLIM RX2 MUX", WCD934X_RX2, slim_rx2),
6547 WCD_DAPM_MUX("SLIM RX3 MUX", WCD934X_RX3, slim_rx3),
6548 WCD_DAPM_MUX("SLIM RX4 MUX", WCD934X_RX4, slim_rx4),
6549 WCD_DAPM_MUX("SLIM RX5 MUX", WCD934X_RX5, slim_rx5),
6550 WCD_DAPM_MUX("SLIM RX6 MUX", WCD934X_RX6, slim_rx6),
6551 WCD_DAPM_MUX("SLIM RX7 MUX", WCD934X_RX7, slim_rx7),
6552
6553 SND_SOC_DAPM_MIXER("SLIM RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
6554 SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6555 SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6556 SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
6557 SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
6558 SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
6559 SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
6560 SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
6561
6562 WCD_DAPM_MUX("CDC_IF RX0 MUX", WCD934X_RX0, cdc_if_rx0),
6563 WCD_DAPM_MUX("CDC_IF RX1 MUX", WCD934X_RX1, cdc_if_rx1),
6564 WCD_DAPM_MUX("CDC_IF RX2 MUX", WCD934X_RX2, cdc_if_rx2),
6565 WCD_DAPM_MUX("CDC_IF RX3 MUX", WCD934X_RX3, cdc_if_rx3),
6566 WCD_DAPM_MUX("CDC_IF RX4 MUX", WCD934X_RX4, cdc_if_rx4),
6567 WCD_DAPM_MUX("CDC_IF RX5 MUX", WCD934X_RX5, cdc_if_rx5),
6568 WCD_DAPM_MUX("CDC_IF RX6 MUX", WCD934X_RX6, cdc_if_rx6),
6569 WCD_DAPM_MUX("CDC_IF RX7 MUX", WCD934X_RX7, cdc_if_rx7),
6570
6571 SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_EAR, 0,
6572 &rx_int0_2_mux, tavil_codec_enable_mix_path,
6573 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6574 SND_SOC_DAPM_POST_PMD),
6575 SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
6576 &rx_int1_2_mux, tavil_codec_enable_mix_path,
6577 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6578 SND_SOC_DAPM_POST_PMD),
6579 SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
6580 &rx_int2_2_mux, tavil_codec_enable_mix_path,
6581 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6582 SND_SOC_DAPM_POST_PMD),
6583 SND_SOC_DAPM_MUX_E("RX INT3_2 MUX", SND_SOC_NOPM, INTERP_LO1, 0,
6584 &rx_int3_2_mux, tavil_codec_enable_mix_path,
6585 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6586 SND_SOC_DAPM_POST_PMD),
6587 SND_SOC_DAPM_MUX_E("RX INT4_2 MUX", SND_SOC_NOPM, INTERP_LO2, 0,
6588 &rx_int4_2_mux, tavil_codec_enable_mix_path,
6589 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6590 SND_SOC_DAPM_POST_PMD),
6591 SND_SOC_DAPM_MUX_E("RX INT7_2 MUX", SND_SOC_NOPM, INTERP_SPKR1, 0,
6592 &rx_int7_2_mux, tavil_codec_enable_mix_path,
6593 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6594 SND_SOC_DAPM_POST_PMD),
6595 SND_SOC_DAPM_MUX_E("RX INT8_2 MUX", SND_SOC_NOPM, INTERP_SPKR2, 0,
6596 &rx_int8_2_mux, tavil_codec_enable_mix_path,
6597 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6598 SND_SOC_DAPM_POST_PMD),
6599
6600 WCD_DAPM_MUX("RX INT0_1 MIX1 INP0", 0, rx_int0_1_mix_inp0),
6601 WCD_DAPM_MUX("RX INT0_1 MIX1 INP1", 0, rx_int0_1_mix_inp1),
6602 WCD_DAPM_MUX("RX INT0_1 MIX1 INP2", 0, rx_int0_1_mix_inp2),
6603 WCD_DAPM_MUX("RX INT1_1 MIX1 INP0", 0, rx_int1_1_mix_inp0),
6604 WCD_DAPM_MUX("RX INT1_1 MIX1 INP1", 0, rx_int1_1_mix_inp1),
6605 WCD_DAPM_MUX("RX INT1_1 MIX1 INP2", 0, rx_int1_1_mix_inp2),
6606 WCD_DAPM_MUX("RX INT2_1 MIX1 INP0", 0, rx_int2_1_mix_inp0),
6607 WCD_DAPM_MUX("RX INT2_1 MIX1 INP1", 0, rx_int2_1_mix_inp1),
6608 WCD_DAPM_MUX("RX INT2_1 MIX1 INP2", 0, rx_int2_1_mix_inp2),
6609 WCD_DAPM_MUX("RX INT3_1 MIX1 INP0", 0, rx_int3_1_mix_inp0),
6610 WCD_DAPM_MUX("RX INT3_1 MIX1 INP1", 0, rx_int3_1_mix_inp1),
6611 WCD_DAPM_MUX("RX INT3_1 MIX1 INP2", 0, rx_int3_1_mix_inp2),
6612 WCD_DAPM_MUX("RX INT4_1 MIX1 INP0", 0, rx_int4_1_mix_inp0),
6613 WCD_DAPM_MUX("RX INT4_1 MIX1 INP1", 0, rx_int4_1_mix_inp1),
6614 WCD_DAPM_MUX("RX INT4_1 MIX1 INP2", 0, rx_int4_1_mix_inp2),
6615
6616 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6617 &rx_int7_1_mix_inp0_mux, tavil_codec_enable_swr,
6618 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6619 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6620 &rx_int7_1_mix_inp1_mux, tavil_codec_enable_swr,
6621 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6622 SND_SOC_DAPM_MUX_E("RX INT7_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6623 &rx_int7_1_mix_inp2_mux, tavil_codec_enable_swr,
6624 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6625 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
6626 &rx_int8_1_mix_inp0_mux, tavil_codec_enable_swr,
6627 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6628 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
6629 &rx_int8_1_mix_inp1_mux, tavil_codec_enable_swr,
6630 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6631 SND_SOC_DAPM_MUX_E("RX INT8_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
6632 &rx_int8_1_mix_inp2_mux, tavil_codec_enable_swr,
6633 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6634
6635 SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6636 SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6637 SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6638 SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0,
6639 rx_int1_asrc_switch, ARRAY_SIZE(rx_int1_asrc_switch)),
6640 SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6641 SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0,
6642 rx_int2_asrc_switch, ARRAY_SIZE(rx_int2_asrc_switch)),
6643 SND_SOC_DAPM_MIXER("RX INT3_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6644 SND_SOC_DAPM_MIXER("RX INT3 SEC MIX", SND_SOC_NOPM, 0, 0,
6645 rx_int3_asrc_switch, ARRAY_SIZE(rx_int3_asrc_switch)),
6646 SND_SOC_DAPM_MIXER("RX INT4_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6647 SND_SOC_DAPM_MIXER("RX INT4 SEC MIX", SND_SOC_NOPM, 0, 0,
6648 rx_int4_asrc_switch, ARRAY_SIZE(rx_int4_asrc_switch)),
6649 SND_SOC_DAPM_MIXER("RX INT7_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6650 SND_SOC_DAPM_MIXER("RX INT7 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6651 SND_SOC_DAPM_MIXER("RX INT8_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6652 SND_SOC_DAPM_MIXER("RX INT8 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
6653
6654 SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6655 SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6656 SND_SOC_DAPM_MIXER("RX INT1 MIX3", SND_SOC_NOPM, 0, 0, hphl_mixer,
6657 ARRAY_SIZE(hphl_mixer)),
6658 SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6659 SND_SOC_DAPM_MIXER("RX INT2 MIX3", SND_SOC_NOPM, 0, 0, hphr_mixer,
6660 ARRAY_SIZE(hphr_mixer)),
6661 SND_SOC_DAPM_MIXER("RX INT3 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6662 SND_SOC_DAPM_MIXER("RX INT4 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6663 SND_SOC_DAPM_MIXER("RX INT7 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6664 SND_SOC_DAPM_MIXER_E("RX INT7 CHAIN", SND_SOC_NOPM, 0, 0,
6665 NULL, 0, tavil_codec_spk_boost_event,
6666 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6667 SND_SOC_DAPM_MIXER_E("RX INT8 CHAIN", SND_SOC_NOPM, 0, 0,
6668 NULL, 0, tavil_codec_spk_boost_event,
6669 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6670
6671 SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_EAR,
6672 0, &rx_int0_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6673 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6674 SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
6675 0, &rx_int1_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6676 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6677 SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
6678 0, &rx_int2_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6679 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6680 SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", SND_SOC_NOPM, INTERP_LO1,
6681 0, &rx_int3_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6682 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6683 SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", SND_SOC_NOPM, INTERP_LO2,
6684 0, &rx_int4_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6685 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6686 SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", SND_SOC_NOPM, INTERP_SPKR1,
6687 0, &rx_int7_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
6688 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6689
6690 WCD_DAPM_MUX("CDC_IF TX0 MUX", WCD934X_TX0, cdc_if_tx0),
6691 WCD_DAPM_MUX("CDC_IF TX1 MUX", WCD934X_TX1, cdc_if_tx1),
6692 WCD_DAPM_MUX("CDC_IF TX2 MUX", WCD934X_TX2, cdc_if_tx2),
6693 WCD_DAPM_MUX("CDC_IF TX3 MUX", WCD934X_TX3, cdc_if_tx3),
6694 WCD_DAPM_MUX("CDC_IF TX4 MUX", WCD934X_TX4, cdc_if_tx4),
6695 WCD_DAPM_MUX("CDC_IF TX5 MUX", WCD934X_TX5, cdc_if_tx5),
6696 WCD_DAPM_MUX("CDC_IF TX6 MUX", WCD934X_TX6, cdc_if_tx6),
6697 WCD_DAPM_MUX("CDC_IF TX7 MUX", WCD934X_TX7, cdc_if_tx7),
6698 WCD_DAPM_MUX("CDC_IF TX8 MUX", WCD934X_TX8, cdc_if_tx8),
6699 WCD_DAPM_MUX("CDC_IF TX9 MUX", WCD934X_TX9, cdc_if_tx9),
6700 WCD_DAPM_MUX("CDC_IF TX10 MUX", WCD934X_TX10, cdc_if_tx10),
6701 WCD_DAPM_MUX("CDC_IF TX11 MUX", WCD934X_TX11, cdc_if_tx11),
6702 WCD_DAPM_MUX("CDC_IF TX11 INP1 MUX", WCD934X_TX11, cdc_if_tx11_inp1),
6703 WCD_DAPM_MUX("CDC_IF TX13 MUX", WCD934X_TX13, cdc_if_tx13),
6704 WCD_DAPM_MUX("CDC_IF TX13 INP1 MUX", WCD934X_TX13, cdc_if_tx13_inp1),
6705
6706 SND_SOC_DAPM_MUX_E("ADC MUX0", WCD934X_CDC_TX0_TX_PATH_CTL, 5, 0,
6707 &tx_adc_mux0_mux, tavil_codec_enable_dec,
6708 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6709 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6710
6711 SND_SOC_DAPM_MUX_E("ADC MUX1", WCD934X_CDC_TX1_TX_PATH_CTL, 5, 0,
6712 &tx_adc_mux1_mux, tavil_codec_enable_dec,
6713 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6714 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6715
6716 SND_SOC_DAPM_MUX_E("ADC MUX2", WCD934X_CDC_TX2_TX_PATH_CTL, 5, 0,
6717 &tx_adc_mux2_mux, tavil_codec_enable_dec,
6718 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6719 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6720
6721 SND_SOC_DAPM_MUX_E("ADC MUX3", WCD934X_CDC_TX3_TX_PATH_CTL, 5, 0,
6722 &tx_adc_mux3_mux, tavil_codec_enable_dec,
6723 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6724 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6725
6726 SND_SOC_DAPM_MUX_E("ADC MUX4", WCD934X_CDC_TX4_TX_PATH_CTL, 5, 0,
6727 &tx_adc_mux4_mux, tavil_codec_enable_dec,
6728 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6729 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6730
6731 SND_SOC_DAPM_MUX_E("ADC MUX5", WCD934X_CDC_TX5_TX_PATH_CTL, 5, 0,
6732 &tx_adc_mux5_mux, tavil_codec_enable_dec,
6733 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6734 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6735
6736 SND_SOC_DAPM_MUX_E("ADC MUX6", WCD934X_CDC_TX6_TX_PATH_CTL, 5, 0,
6737 &tx_adc_mux6_mux, tavil_codec_enable_dec,
6738 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6739 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6740
6741 SND_SOC_DAPM_MUX_E("ADC MUX7", WCD934X_CDC_TX7_TX_PATH_CTL, 5, 0,
6742 &tx_adc_mux7_mux, tavil_codec_enable_dec,
6743 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6744 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6745
6746 SND_SOC_DAPM_MUX_E("ADC MUX8", WCD934X_CDC_TX8_TX_PATH_CTL, 5, 0,
6747 &tx_adc_mux8_mux, tavil_codec_enable_dec,
6748 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6749 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
6750
6751 SND_SOC_DAPM_MUX_E("ADC MUX10", SND_SOC_NOPM, 10, 0, &tx_adc_mux10_mux,
6752 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
6753
6754 SND_SOC_DAPM_MUX_E("ADC MUX11", SND_SOC_NOPM, 11, 0, &tx_adc_mux11_mux,
6755 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
6756
6757 SND_SOC_DAPM_MUX_E("ADC MUX12", SND_SOC_NOPM, 12, 0, &tx_adc_mux12_mux,
6758 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
6759
6760 SND_SOC_DAPM_MUX_E("ADC MUX13", SND_SOC_NOPM, 13, 0, &tx_adc_mux13_mux,
6761 tavil_codec_tx_adc_cfg, SND_SOC_DAPM_POST_PMU),
6762
6763 WCD_DAPM_MUX("DMIC MUX0", 0, tx_dmic_mux0),
6764 WCD_DAPM_MUX("DMIC MUX1", 0, tx_dmic_mux1),
6765 WCD_DAPM_MUX("DMIC MUX2", 0, tx_dmic_mux2),
6766 WCD_DAPM_MUX("DMIC MUX3", 0, tx_dmic_mux3),
6767 WCD_DAPM_MUX("DMIC MUX4", 0, tx_dmic_mux4),
6768 WCD_DAPM_MUX("DMIC MUX5", 0, tx_dmic_mux5),
6769 WCD_DAPM_MUX("DMIC MUX6", 0, tx_dmic_mux6),
6770 WCD_DAPM_MUX("DMIC MUX7", 0, tx_dmic_mux7),
6771 WCD_DAPM_MUX("DMIC MUX8", 0, tx_dmic_mux8),
6772 WCD_DAPM_MUX("DMIC MUX10", 0, tx_dmic_mux10),
6773 WCD_DAPM_MUX("DMIC MUX11", 0, tx_dmic_mux11),
6774 WCD_DAPM_MUX("DMIC MUX12", 0, tx_dmic_mux12),
6775 WCD_DAPM_MUX("DMIC MUX13", 0, tx_dmic_mux13),
6776
6777 WCD_DAPM_MUX("AMIC MUX0", 0, tx_amic_mux0),
6778 WCD_DAPM_MUX("AMIC MUX1", 0, tx_amic_mux1),
6779 WCD_DAPM_MUX("AMIC MUX2", 0, tx_amic_mux2),
6780 WCD_DAPM_MUX("AMIC MUX3", 0, tx_amic_mux3),
6781 WCD_DAPM_MUX("AMIC MUX4", 0, tx_amic_mux4),
6782 WCD_DAPM_MUX("AMIC MUX5", 0, tx_amic_mux5),
6783 WCD_DAPM_MUX("AMIC MUX6", 0, tx_amic_mux6),
6784 WCD_DAPM_MUX("AMIC MUX7", 0, tx_amic_mux7),
6785 WCD_DAPM_MUX("AMIC MUX8", 0, tx_amic_mux8),
6786 WCD_DAPM_MUX("AMIC MUX10", 0, tx_amic_mux10),
6787 WCD_DAPM_MUX("AMIC MUX11", 0, tx_amic_mux11),
6788 WCD_DAPM_MUX("AMIC MUX12", 0, tx_amic_mux12),
6789 WCD_DAPM_MUX("AMIC MUX13", 0, tx_amic_mux13),
6790
6791 SND_SOC_DAPM_ADC_E("ADC1", NULL, WCD934X_ANA_AMIC1, 7, 0,
6792 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
6793 SND_SOC_DAPM_ADC_E("ADC2", NULL, WCD934X_ANA_AMIC2, 7, 0,
6794 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
6795 SND_SOC_DAPM_ADC_E("ADC3", NULL, WCD934X_ANA_AMIC3, 7, 0,
6796 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
6797 SND_SOC_DAPM_ADC_E("ADC4", NULL, WCD934X_ANA_AMIC4, 7, 0,
6798 tavil_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
6799
6800 WCD_DAPM_MUX("AMIC4_5 SEL", 0, tx_amic4_5),
6801
6802 WCD_DAPM_MUX("ANC0 FB MUX", 0, anc0_fb),
6803 WCD_DAPM_MUX("ANC1 FB MUX", 0, anc1_fb),
6804
6805 SND_SOC_DAPM_INPUT("AMIC1"),
6806 SND_SOC_DAPM_INPUT("AMIC2"),
6807 SND_SOC_DAPM_INPUT("AMIC3"),
6808 SND_SOC_DAPM_INPUT("AMIC4"),
6809 SND_SOC_DAPM_INPUT("AMIC5"),
6810
6811 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
6812 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
6813 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6814 SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
6815 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
6816 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6817 SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
6818 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
6819 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6820 SND_SOC_DAPM_MICBIAS_E("MIC BIAS4", SND_SOC_NOPM, 0, 0,
6821 tavil_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
6822 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6823
6824 /*
6825 * Not supply widget, this is used to recover HPH registers.
6826 * It is not connected to any other widgets
6827 */
6828 SND_SOC_DAPM_SUPPLY("RESET_HPH_REGISTERS", SND_SOC_NOPM,
6829 0, 0, tavil_codec_reset_hph_registers,
6830 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6831
6832 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS1_STANDALONE, SND_SOC_NOPM, 0, 0,
6833 tavil_codec_force_enable_micbias,
6834 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6835 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_STANDALONE, SND_SOC_NOPM, 0, 0,
6836 tavil_codec_force_enable_micbias,
6837 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6838 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS3_STANDALONE, SND_SOC_NOPM, 0, 0,
6839 tavil_codec_force_enable_micbias,
6840 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6841 SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS4_STANDALONE, SND_SOC_NOPM, 0, 0,
6842 tavil_codec_force_enable_micbias,
6843 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6844
6845 SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
6846 AIF1_CAP, 0, tavil_codec_enable_slimtx,
6847 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6848 SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
6849 AIF2_CAP, 0, tavil_codec_enable_slimtx,
6850 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6851 SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
6852 AIF3_CAP, 0, tavil_codec_enable_slimtx,
6853 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6854 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
6855 aif1_cap_mixer, ARRAY_SIZE(aif1_cap_mixer)),
6856 SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
6857 aif2_cap_mixer, ARRAY_SIZE(aif2_cap_mixer)),
6858 SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
6859 aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),
6860 SND_SOC_DAPM_MIXER("AIF4_MAD Mixer", SND_SOC_NOPM, AIF4_MAD_TX, 0,
6861 aif4_mad_mixer, ARRAY_SIZE(aif4_mad_mixer)),
6862
6863 SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
6864 AIF4_VIFEED, 0, tavil_codec_enable_slimvi_feedback,
6865 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
6866
6867 SND_SOC_DAPM_AIF_OUT("AIF4 MAD", "AIF4 MAD TX", 0,
6868 SND_SOC_NOPM, 0, 0),
6869
6870 SND_SOC_DAPM_MIXER("AIF4_VI Mixer", SND_SOC_NOPM, AIF4_VIFEED, 0,
6871 aif4_vi_mixer, ARRAY_SIZE(aif4_vi_mixer)),
6872 SND_SOC_DAPM_INPUT("VIINPUT"),
6873
6874 SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
6875 SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
6876 SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
6877 SND_SOC_DAPM_MIXER("SLIM TX3", SND_SOC_NOPM, 0, 0, NULL, 0),
6878 SND_SOC_DAPM_MIXER("SLIM TX4", SND_SOC_NOPM, 0, 0, NULL, 0),
6879 SND_SOC_DAPM_MIXER("SLIM TX5", SND_SOC_NOPM, 0, 0, NULL, 0),
6880 SND_SOC_DAPM_MIXER("SLIM TX6", SND_SOC_NOPM, 0, 0, NULL, 0),
6881 SND_SOC_DAPM_MIXER("SLIM TX7", SND_SOC_NOPM, 0, 0, NULL, 0),
6882 SND_SOC_DAPM_MIXER("SLIM TX8", SND_SOC_NOPM, 0, 0, NULL, 0),
6883 SND_SOC_DAPM_MIXER("SLIM TX9", SND_SOC_NOPM, 0, 0, NULL, 0),
6884 SND_SOC_DAPM_MIXER("SLIM TX10", SND_SOC_NOPM, 0, 0, NULL, 0),
6885 SND_SOC_DAPM_MIXER("SLIM TX11", SND_SOC_NOPM, 0, 0, NULL, 0),
6886 SND_SOC_DAPM_MIXER("SLIM TX13", SND_SOC_NOPM, 0, 0, NULL, 0),
6887
6888 /* Digital Mic Inputs */
6889 SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
6890 tavil_codec_enable_dmic,
6891 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6892 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
6893 tavil_codec_enable_dmic,
6894 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6895 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
6896 tavil_codec_enable_dmic,
6897 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6898 SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
6899 tavil_codec_enable_dmic,
6900 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6901 SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
6902 tavil_codec_enable_dmic,
6903 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6904 SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
6905 tavil_codec_enable_dmic,
6906 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
6907
6908 WCD_DAPM_MUX("IIR0 INP0 MUX", 0, iir0_inp0),
6909 WCD_DAPM_MUX("IIR0 INP1 MUX", 0, iir0_inp1),
6910 WCD_DAPM_MUX("IIR0 INP2 MUX", 0, iir0_inp2),
6911 WCD_DAPM_MUX("IIR0 INP3 MUX", 0, iir0_inp3),
6912 WCD_DAPM_MUX("IIR1 INP0 MUX", 0, iir1_inp0),
6913 WCD_DAPM_MUX("IIR1 INP1 MUX", 0, iir1_inp1),
6914 WCD_DAPM_MUX("IIR1 INP2 MUX", 0, iir1_inp2),
6915 WCD_DAPM_MUX("IIR1 INP3 MUX", 0, iir1_inp3),
6916
6917 SND_SOC_DAPM_MIXER_E("IIR0", WCD934X_CDC_SIDETONE_IIR0_IIR_PATH_CTL,
6918 4, 0, NULL, 0, tavil_codec_set_iir_gain,
6919 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
6920 SND_SOC_DAPM_MIXER_E("IIR1", WCD934X_CDC_SIDETONE_IIR1_IIR_PATH_CTL,
6921 4, 0, NULL, 0, tavil_codec_set_iir_gain,
6922 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
6923 SND_SOC_DAPM_MIXER("SRC0", WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
6924 4, 0, NULL, 0),
6925 SND_SOC_DAPM_MIXER("SRC1", WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,
6926 4, 0, NULL, 0),
6927
6928 WCD_DAPM_MUX("RX MIX TX0 MUX", 0, rx_mix_tx0),
6929 WCD_DAPM_MUX("RX MIX TX1 MUX", 0, rx_mix_tx1),
6930 WCD_DAPM_MUX("RX MIX TX2 MUX", 0, rx_mix_tx2),
6931 WCD_DAPM_MUX("RX MIX TX3 MUX", 0, rx_mix_tx3),
6932 WCD_DAPM_MUX("RX MIX TX4 MUX", 0, rx_mix_tx4),
6933 WCD_DAPM_MUX("RX MIX TX5 MUX", 0, rx_mix_tx5),
6934 WCD_DAPM_MUX("RX MIX TX6 MUX", 0, rx_mix_tx6),
6935 WCD_DAPM_MUX("RX MIX TX7 MUX", 0, rx_mix_tx7),
6936 WCD_DAPM_MUX("RX MIX TX8 MUX", 0, rx_mix_tx8),
6937 WCD_DAPM_MUX("RX INT0 DEM MUX", 0, rx_int0_dem_inp),
6938 WCD_DAPM_MUX("RX INT1 DEM MUX", 0, rx_int1_dem_inp),
6939 WCD_DAPM_MUX("RX INT2 DEM MUX", 0, rx_int2_dem_inp),
6940
6941 SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_EAR, 0,
6942 &rx_int0_1_interp_mux, tavil_codec_enable_main_path,
6943 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6944 SND_SOC_DAPM_POST_PMD),
6945 SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
6946 &rx_int1_1_interp_mux, tavil_codec_enable_main_path,
6947 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6948 SND_SOC_DAPM_POST_PMD),
6949 SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
6950 &rx_int2_1_interp_mux, tavil_codec_enable_main_path,
6951 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6952 SND_SOC_DAPM_POST_PMD),
6953 SND_SOC_DAPM_MUX_E("RX INT3_1 INTERP", SND_SOC_NOPM, INTERP_LO1, 0,
6954 &rx_int3_1_interp_mux, tavil_codec_enable_main_path,
6955 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6956 SND_SOC_DAPM_POST_PMD),
6957 SND_SOC_DAPM_MUX_E("RX INT4_1 INTERP", SND_SOC_NOPM, INTERP_LO2, 0,
6958 &rx_int4_1_interp_mux, tavil_codec_enable_main_path,
6959 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6960 SND_SOC_DAPM_POST_PMD),
6961 SND_SOC_DAPM_MUX_E("RX INT7_1 INTERP", SND_SOC_NOPM, INTERP_SPKR1, 0,
6962 &rx_int7_1_interp_mux, tavil_codec_enable_main_path,
6963 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6964 SND_SOC_DAPM_POST_PMD),
6965 SND_SOC_DAPM_MUX_E("RX INT8_1 INTERP", SND_SOC_NOPM, INTERP_SPKR2, 0,
6966 &rx_int8_1_interp_mux, tavil_codec_enable_main_path,
6967 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
6968 SND_SOC_DAPM_POST_PMD),
6969
6970 WCD_DAPM_MUX("RX INT0_2 INTERP", 0, rx_int0_2_interp),
6971 WCD_DAPM_MUX("RX INT1_2 INTERP", 0, rx_int1_2_interp),
6972 WCD_DAPM_MUX("RX INT2_2 INTERP", 0, rx_int2_2_interp),
6973 WCD_DAPM_MUX("RX INT3_2 INTERP", 0, rx_int3_2_interp),
6974 WCD_DAPM_MUX("RX INT4_2 INTERP", 0, rx_int4_2_interp),
6975 WCD_DAPM_MUX("RX INT7_2 INTERP", 0, rx_int7_2_interp),
6976 WCD_DAPM_MUX("RX INT8_2 INTERP", 0, rx_int8_2_interp),
6977
6978 SND_SOC_DAPM_SWITCH("ADC US MUX0", WCD934X_CDC_TX0_TX_PATH_192_CTL, 0,
6979 0, &adc_us_mux0_switch),
6980 SND_SOC_DAPM_SWITCH("ADC US MUX1", WCD934X_CDC_TX1_TX_PATH_192_CTL, 0,
6981 0, &adc_us_mux1_switch),
6982 SND_SOC_DAPM_SWITCH("ADC US MUX2", WCD934X_CDC_TX2_TX_PATH_192_CTL, 0,
6983 0, &adc_us_mux2_switch),
6984 SND_SOC_DAPM_SWITCH("ADC US MUX3", WCD934X_CDC_TX3_TX_PATH_192_CTL, 0,
6985 0, &adc_us_mux3_switch),
6986 SND_SOC_DAPM_SWITCH("ADC US MUX4", WCD934X_CDC_TX4_TX_PATH_192_CTL, 0,
6987 0, &adc_us_mux4_switch),
6988 SND_SOC_DAPM_SWITCH("ADC US MUX5", WCD934X_CDC_TX5_TX_PATH_192_CTL, 0,
6989 0, &adc_us_mux5_switch),
6990 SND_SOC_DAPM_SWITCH("ADC US MUX6", WCD934X_CDC_TX6_TX_PATH_192_CTL, 0,
6991 0, &adc_us_mux6_switch),
6992 SND_SOC_DAPM_SWITCH("ADC US MUX7", WCD934X_CDC_TX7_TX_PATH_192_CTL, 0,
6993 0, &adc_us_mux7_switch),
6994 SND_SOC_DAPM_SWITCH("ADC US MUX8", WCD934X_CDC_TX8_TX_PATH_192_CTL, 0,
6995 0, &adc_us_mux8_switch),
6996
6997 /* MAD related widgets */
6998 SND_SOC_DAPM_INPUT("MAD_CPE_INPUT"),
6999 SND_SOC_DAPM_INPUT("MADINPUT"),
7000
7001 WCD_DAPM_MUX("MAD_SEL MUX", 0, mad_sel),
7002 WCD_DAPM_MUX("MAD_INP MUX", 0, mad_inp_mux),
7003
7004 SND_SOC_DAPM_SWITCH_E("MAD_BROADCAST", SND_SOC_NOPM, 0, 0,
7005 &mad_brdcst_switch, tavil_codec_ape_enable_mad,
7006 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7007
7008 SND_SOC_DAPM_SWITCH_E("MAD_CPE1", SND_SOC_NOPM, 0, 0,
7009 &mad_cpe1_switch, tavil_codec_cpe_mad_ctl,
7010 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7011 SND_SOC_DAPM_SWITCH_E("MAD_CPE2", SND_SOC_NOPM, 0, 0,
7012 &mad_cpe2_switch, tavil_codec_cpe_mad_ctl,
7013 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7014
7015 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT1"),
7016 SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT2"),
7017
7018 SND_SOC_DAPM_DAC_E("RX INT0 DAC", NULL, SND_SOC_NOPM,
7019 0, 0, tavil_codec_ear_dac_event,
7020 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7021 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7022 SND_SOC_DAPM_DAC_E("RX INT1 DAC", NULL, WCD934X_ANA_HPH,
7023 5, 0, tavil_codec_hphl_dac_event,
7024 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7025 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7026 SND_SOC_DAPM_DAC_E("RX INT2 DAC", NULL, WCD934X_ANA_HPH,
7027 4, 0, tavil_codec_hphr_dac_event,
7028 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7029 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7030 SND_SOC_DAPM_DAC_E("RX INT3 DAC", NULL, SND_SOC_NOPM,
7031 0, 0, tavil_codec_lineout_dac_event,
7032 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7033 SND_SOC_DAPM_DAC_E("RX INT4 DAC", NULL, SND_SOC_NOPM,
7034 0, 0, tavil_codec_lineout_dac_event,
7035 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7036
7037 SND_SOC_DAPM_PGA_E("EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7038 tavil_codec_enable_ear_pa,
7039 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
7040 SND_SOC_DAPM_PGA_E("HPHL PA", WCD934X_ANA_HPH, 7, 0, NULL, 0,
7041 tavil_codec_enable_hphl_pa,
7042 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7043 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7044 SND_SOC_DAPM_PGA_E("HPHR PA", WCD934X_ANA_HPH, 6, 0, NULL, 0,
7045 tavil_codec_enable_hphr_pa,
7046 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7047 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7048 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
7049 tavil_codec_enable_lineout_pa,
7050 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7051 SND_SOC_DAPM_POST_PMD),
7052 SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
7053 tavil_codec_enable_lineout_pa,
7054 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
7055 SND_SOC_DAPM_POST_PMD),
7056 SND_SOC_DAPM_PGA_E("ANC EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
7057 tavil_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
7058 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
7059 SND_SOC_DAPM_PGA_E("ANC SPK1 PA", SND_SOC_NOPM, 0, 0, NULL, 0,
7060 tavil_codec_enable_spkr_anc,
7061 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7062
7063 SND_SOC_DAPM_OUTPUT("EAR"),
7064 SND_SOC_DAPM_OUTPUT("HPHL"),
7065 SND_SOC_DAPM_OUTPUT("HPHR"),
7066 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
7067 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
7068 SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
7069 SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
7070 SND_SOC_DAPM_OUTPUT("ANC EAR"),
7071
7072 SND_SOC_DAPM_SWITCH("ANC OUT EAR Enable", SND_SOC_NOPM, 0, 0,
7073 &anc_ear_switch),
7074 SND_SOC_DAPM_SWITCH("ANC OUT EAR SPKR Enable", SND_SOC_NOPM, 0, 0,
7075 &anc_ear_spkr_switch),
7076 SND_SOC_DAPM_SWITCH("ANC SPKR PA Enable", SND_SOC_NOPM, 0, 0,
7077 &anc_spkr_pa_switch),
7078
7079 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
7080 tavil_codec_enable_rx_bias,
7081 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7082
7083 SND_SOC_DAPM_SUPPLY("RX INT1 NATIVE SUPPLY", SND_SOC_NOPM,
7084 INTERP_HPHL, 0, tavil_enable_native_supply,
7085 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7086 SND_SOC_DAPM_SUPPLY("RX INT2 NATIVE SUPPLY", SND_SOC_NOPM,
7087 INTERP_HPHR, 0, tavil_enable_native_supply,
7088 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7089 SND_SOC_DAPM_SUPPLY("RX INT3 NATIVE SUPPLY", SND_SOC_NOPM,
7090 INTERP_LO1, 0, tavil_enable_native_supply,
7091 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7092 SND_SOC_DAPM_SUPPLY("RX INT4 NATIVE SUPPLY", SND_SOC_NOPM,
7093 INTERP_LO2, 0, tavil_enable_native_supply,
7094 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7095 SND_SOC_DAPM_SUPPLY("RX INT7 NATIVE SUPPLY", SND_SOC_NOPM,
7096 INTERP_SPKR1, 0, tavil_enable_native_supply,
7097 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7098 SND_SOC_DAPM_SUPPLY("RX INT8 NATIVE SUPPLY", SND_SOC_NOPM,
7099 INTERP_SPKR2, 0, tavil_enable_native_supply,
7100 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
7101
7102 WCD_DAPM_MUX("RX INT1_1 NATIVE MUX", 0, int1_1_native),
7103 WCD_DAPM_MUX("RX INT2_1 NATIVE MUX", 0, int2_1_native),
7104 WCD_DAPM_MUX("RX INT3_1 NATIVE MUX", 0, int3_1_native),
7105 WCD_DAPM_MUX("RX INT4_1 NATIVE MUX", 0, int4_1_native),
7106
7107 WCD_DAPM_MUX("RX INT1_2 NATIVE MUX", 0, int1_2_native),
7108 WCD_DAPM_MUX("RX INT2_2 NATIVE MUX", 0, int2_2_native),
7109 WCD_DAPM_MUX("RX INT3_2 NATIVE MUX", 0, int3_2_native),
7110 WCD_DAPM_MUX("RX INT4_2 NATIVE MUX", 0, int4_2_native),
7111 WCD_DAPM_MUX("RX INT7_2 NATIVE MUX", 0, int7_2_native),
7112 WCD_DAPM_MUX("RX INT8_2 NATIVE MUX", 0, int8_2_native),
7113
7114 SND_SOC_DAPM_MUX_E("ASRC0 MUX", SND_SOC_NOPM, ASRC0, 0,
7115 &asrc0_mux, tavil_codec_enable_asrc_resampler,
7116 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7117 SND_SOC_DAPM_MUX_E("ASRC1 MUX", SND_SOC_NOPM, ASRC1, 0,
7118 &asrc1_mux, tavil_codec_enable_asrc_resampler,
7119 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7120 SND_SOC_DAPM_MUX_E("ASRC2 MUX", SND_SOC_NOPM, ASRC2, 0,
7121 &asrc2_mux, tavil_codec_enable_asrc_resampler,
7122 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7123 SND_SOC_DAPM_MUX_E("ASRC3 MUX", SND_SOC_NOPM, ASRC3, 0,
7124 &asrc3_mux, tavil_codec_enable_asrc_resampler,
7125 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
7126};
7127
7128static int tavil_get_channel_map(struct snd_soc_dai *dai,
7129 unsigned int *tx_num, unsigned int *tx_slot,
7130 unsigned int *rx_num, unsigned int *rx_slot)
7131{
7132 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7133 u32 i = 0;
7134 struct wcd9xxx_ch *ch;
7135 int ret = 0;
7136
7137 switch (dai->id) {
7138 case AIF1_PB:
7139 case AIF2_PB:
7140 case AIF3_PB:
7141 case AIF4_PB:
7142 if (!rx_slot || !rx_num) {
7143 dev_err(tavil->dev, "%s: Invalid rx_slot 0x%pK or rx_num 0x%pK\n",
7144 __func__, rx_slot, rx_num);
7145 ret = -EINVAL;
7146 break;
7147 }
7148 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7149 list) {
7150 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7151 __func__, i, ch->ch_num);
7152 rx_slot[i++] = ch->ch_num;
7153 }
7154 *rx_num = i;
7155 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x rx_num = %d\n",
7156 __func__, dai->name, dai->id, i);
7157 if (*rx_num == 0) {
7158 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7159 __func__, dai->name, dai->id);
7160 ret = -EINVAL;
7161 }
7162 break;
7163 case AIF1_CAP:
7164 case AIF2_CAP:
7165 case AIF3_CAP:
7166 case AIF4_MAD_TX:
7167 case AIF4_VIFEED:
7168 if (!tx_slot || !tx_num) {
7169 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK or tx_num 0x%pK\n",
7170 __func__, tx_slot, tx_num);
7171 ret = -EINVAL;
7172 break;
7173 }
7174 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list,
7175 list) {
7176 dev_dbg(tavil->dev, "%s: slot_num %u ch->ch_num %d\n",
7177 __func__, i, ch->ch_num);
7178 tx_slot[i++] = ch->ch_num;
7179 }
7180 *tx_num = i;
7181 dev_dbg(tavil->dev, "%s: dai_name = %s dai_id = %x tx_num = %d\n",
7182 __func__, dai->name, dai->id, i);
7183 if (*tx_num == 0) {
7184 dev_err(tavil->dev, "%s: Channel list empty for dai_name = %s dai_id = %x\n",
7185 __func__, dai->name, dai->id);
7186 ret = -EINVAL;
7187 }
7188 break;
7189 default:
7190 dev_err(tavil->dev, "%s: Invalid DAI ID %x\n",
7191 __func__, dai->id);
7192 ret = -EINVAL;
7193 break;
7194 }
7195
7196 return ret;
7197}
7198
7199static int tavil_set_channel_map(struct snd_soc_dai *dai,
7200 unsigned int tx_num, unsigned int *tx_slot,
7201 unsigned int rx_num, unsigned int *rx_slot)
7202{
7203 struct tavil_priv *tavil;
7204 struct wcd9xxx *core;
7205 struct wcd9xxx_codec_dai_data *dai_data = NULL;
7206
7207 tavil = snd_soc_codec_get_drvdata(dai->codec);
7208 core = dev_get_drvdata(dai->codec->dev->parent);
7209
7210 if (!tx_slot || !rx_slot) {
7211 dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK, rx_slot 0x%pK\n",
7212 __func__, tx_slot, rx_slot);
7213 return -EINVAL;
7214 }
7215 dev_dbg(tavil->dev, "%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
7216 __func__, dai->name, dai->id, tx_num, rx_num);
7217
7218 wcd9xxx_init_slimslave(core, core->slim->laddr,
7219 tx_num, tx_slot, rx_num, rx_slot);
7220 /* Reserve TX13 for MAD data channel */
7221 dai_data = &tavil->dai[AIF4_MAD_TX];
7222 if (dai_data)
7223 list_add_tail(&core->tx_chs[WCD934X_TX13].list,
7224 &dai_data->wcd9xxx_ch_list);
7225
7226 return 0;
7227}
7228
7229static int tavil_startup(struct snd_pcm_substream *substream,
7230 struct snd_soc_dai *dai)
7231{
7232 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7233 substream->name, substream->stream);
7234
7235 return 0;
7236}
7237
7238static void tavil_shutdown(struct snd_pcm_substream *substream,
7239 struct snd_soc_dai *dai)
7240{
7241 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7242 substream->name, substream->stream);
7243}
7244
7245static int tavil_set_decimator_rate(struct snd_soc_dai *dai,
7246 u32 sample_rate)
7247{
7248 struct snd_soc_codec *codec = dai->codec;
7249 struct wcd9xxx_ch *ch;
7250 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7251 u32 tx_port = 0, tx_fs_rate = 0;
7252 u8 shift = 0, shift_val = 0, tx_mux_sel = 0;
7253 int decimator = -1;
7254 u16 tx_port_reg = 0, tx_fs_reg = 0;
7255
7256 switch (sample_rate) {
7257 case 8000:
7258 tx_fs_rate = 0;
7259 break;
7260 case 16000:
7261 tx_fs_rate = 1;
7262 break;
7263 case 32000:
7264 tx_fs_rate = 3;
7265 break;
7266 case 48000:
7267 tx_fs_rate = 4;
7268 break;
7269 case 96000:
7270 tx_fs_rate = 5;
7271 break;
7272 case 192000:
7273 tx_fs_rate = 6;
7274 break;
7275 default:
7276 dev_err(tavil->dev, "%s: Invalid TX sample rate: %d\n",
7277 __func__, sample_rate);
7278 return -EINVAL;
7279
7280 };
7281
7282 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7283 tx_port = ch->port;
7284 dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
7285 __func__, dai->id, tx_port);
7286
7287 if ((tx_port < 0) || (tx_port == 12) || (tx_port >= 14)) {
7288 dev_err(codec->dev, "%s: Invalid SLIM TX%u port. DAI ID: %d\n",
7289 __func__, tx_port, dai->id);
7290 return -EINVAL;
7291 }
7292 /* Find the SB TX MUX input - which decimator is connected */
7293 if (tx_port < 4) {
7294 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0;
7295 shift = (tx_port << 1);
7296 shift_val = 0x03;
7297 } else if ((tx_port >= 4) && (tx_port < 8)) {
7298 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1;
7299 shift = ((tx_port - 4) << 1);
7300 shift_val = 0x03;
7301 } else if ((tx_port >= 8) && (tx_port < 11)) {
7302 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2;
7303 shift = ((tx_port - 8) << 1);
7304 shift_val = 0x03;
7305 } else if (tx_port == 11) {
7306 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7307 shift = 0;
7308 shift_val = 0x0F;
7309 } else if (tx_port == 13) {
7310 tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
7311 shift = 4;
7312 shift_val = 0x03;
7313 }
7314 tx_mux_sel = snd_soc_read(codec, tx_port_reg) &
7315 (shift_val << shift);
7316 tx_mux_sel = tx_mux_sel >> shift;
7317
7318 if (tx_port <= 8) {
7319 if ((tx_mux_sel == 0x2) || (tx_mux_sel == 0x3))
7320 decimator = tx_port;
7321 } else if (tx_port <= 10) {
7322 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7323 decimator = ((tx_port == 9) ? 7 : 6);
7324 } else if (tx_port == 11) {
7325 if ((tx_mux_sel >= 1) && (tx_mux_sel < 7))
7326 decimator = tx_mux_sel - 1;
7327 } else if (tx_port == 13) {
7328 if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
7329 decimator = 5;
7330 }
7331
7332 if (decimator >= 0) {
7333 tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL +
7334 16 * decimator;
7335 dev_dbg(codec->dev, "%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
7336 __func__, decimator, tx_port, sample_rate);
7337 snd_soc_update_bits(codec, tx_fs_reg, 0x0F, tx_fs_rate);
7338 } else if ((tx_port <= 8) && (tx_mux_sel == 0x01)) {
7339 /* Check if the TX Mux input is RX MIX TXn */
7340 dev_dbg(codec->dev, "%s: RX_MIX_TX%u going to CDC_IF TX%u\n",
7341 __func__, tx_port, tx_port);
7342 } else {
7343 dev_err(codec->dev, "%s: ERROR: Invalid decimator: %d\n",
7344 __func__, decimator);
7345 return -EINVAL;
7346 }
7347 }
7348 return 0;
7349}
7350
7351static int tavil_set_mix_interpolator_rate(struct snd_soc_dai *dai,
7352 u8 rate_reg_val,
7353 u32 sample_rate)
7354{
7355 u8 int_2_inp;
7356 u32 j;
7357 u16 int_mux_cfg1, int_fs_reg;
7358 u8 int_mux_cfg1_val;
7359 struct snd_soc_codec *codec = dai->codec;
7360 struct wcd9xxx_ch *ch;
7361 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7362
7363 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7364 int_2_inp = INTn_2_INP_SEL_RX0 + ch->port -
7365 WCD934X_RX_PORT_START_NUMBER;
7366 if ((int_2_inp < INTn_2_INP_SEL_RX0) ||
7367 (int_2_inp > INTn_2_INP_SEL_RX7)) {
7368 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7369 __func__,
7370 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7371 dai->id);
7372 return -EINVAL;
7373 }
7374
7375 int_mux_cfg1 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1;
7376 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7377 /* Interpolators 5 and 6 are not aviliable in Tavil */
7378 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7379 int_mux_cfg1 += 2;
7380 continue;
7381 }
7382 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1) &
7383 0x0F;
7384 if (int_mux_cfg1_val == int_2_inp) {
7385 /*
7386 * Ear mix path supports only 48, 96, 192,
7387 * 384KHz only
7388 */
7389 if ((j == INTERP_EAR) &&
7390 (rate_reg_val < 0x4 ||
7391 rate_reg_val > 0x7)) {
7392 dev_err_ratelimited(codec->dev,
7393 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7394 __func__, dai->id);
7395 return -EINVAL;
7396 }
7397
7398 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
7399 20 * j;
7400 dev_dbg(codec->dev, "%s: AIF_PB DAI(%d) connected to INT%u_2\n",
7401 __func__, dai->id, j);
7402 dev_dbg(codec->dev, "%s: set INT%u_2 sample rate to %u\n",
7403 __func__, j, sample_rate);
7404 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7405 rate_reg_val);
7406 }
7407 int_mux_cfg1 += 2;
7408 }
7409 }
7410 return 0;
7411}
7412
7413static int tavil_set_prim_interpolator_rate(struct snd_soc_dai *dai,
7414 u8 rate_reg_val,
7415 u32 sample_rate)
7416{
7417 u8 int_1_mix1_inp;
7418 u32 j;
7419 u16 int_mux_cfg0, int_mux_cfg1;
7420 u16 int_fs_reg;
7421 u8 int_mux_cfg0_val, int_mux_cfg1_val;
7422 u8 inp0_sel, inp1_sel, inp2_sel;
7423 struct snd_soc_codec *codec = dai->codec;
7424 struct wcd9xxx_ch *ch;
7425 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7426 struct tavil_dsd_config *dsd_conf = tavil->dsd_config;
7427
7428 list_for_each_entry(ch, &tavil->dai[dai->id].wcd9xxx_ch_list, list) {
7429 int_1_mix1_inp = INTn_1_INP_SEL_RX0 + ch->port -
7430 WCD934X_RX_PORT_START_NUMBER;
7431 if ((int_1_mix1_inp < INTn_1_INP_SEL_RX0) ||
7432 (int_1_mix1_inp > INTn_1_INP_SEL_RX7)) {
7433 dev_err(codec->dev, "%s: Invalid RX%u port, Dai ID is %d\n",
7434 __func__,
7435 (ch->port - WCD934X_RX_PORT_START_NUMBER),
7436 dai->id);
7437 return -EINVAL;
7438 }
7439
7440 int_mux_cfg0 = WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0;
7441
7442 /*
7443 * Loop through all interpolator MUX inputs and find out
7444 * to which interpolator input, the slim rx port
7445 * is connected
7446 */
7447 for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
7448 /* Interpolators 5 and 6 are not aviliable in Tavil */
7449 if (j == INTERP_LO3_NA || j == INTERP_LO4_NA) {
7450 int_mux_cfg0 += 2;
7451 continue;
7452 }
7453 int_mux_cfg1 = int_mux_cfg0 + 1;
7454
7455 int_mux_cfg0_val = snd_soc_read(codec, int_mux_cfg0);
7456 int_mux_cfg1_val = snd_soc_read(codec, int_mux_cfg1);
7457 inp0_sel = int_mux_cfg0_val & 0x0F;
7458 inp1_sel = (int_mux_cfg0_val >> 4) & 0x0F;
7459 inp2_sel = (int_mux_cfg1_val >> 4) & 0x0F;
7460 if ((inp0_sel == int_1_mix1_inp) ||
7461 (inp1_sel == int_1_mix1_inp) ||
7462 (inp2_sel == int_1_mix1_inp)) {
7463 /*
7464 * Ear and speaker primary path does not support
7465 * native sample rates
7466 */
7467 if ((j == INTERP_EAR || j == INTERP_SPKR1 ||
7468 j == INTERP_SPKR2) &&
7469 (rate_reg_val > 0x7)) {
7470 dev_err_ratelimited(codec->dev,
7471 "%s: Invalid rate for AIF_PB DAI(%d)\n",
7472 __func__, dai->id);
7473 return -EINVAL;
7474 }
7475
7476 int_fs_reg = WCD934X_CDC_RX0_RX_PATH_CTL +
7477 20 * j;
7478 dev_dbg(codec->dev,
7479 "%s: AIF_PB DAI(%d) connected to INT%u_1\n",
7480 __func__, dai->id, j);
7481 dev_dbg(codec->dev,
7482 "%s: set INT%u_1 sample rate to %u\n",
7483 __func__, j, sample_rate);
7484 snd_soc_update_bits(codec, int_fs_reg, 0x0F,
7485 rate_reg_val);
7486 }
7487 int_mux_cfg0 += 2;
7488 }
7489 if (dsd_conf)
7490 tavil_dsd_set_interp_rate(dsd_conf, ch->port,
7491 sample_rate, rate_reg_val);
7492 }
7493
7494 return 0;
7495}
7496
7497
7498static int tavil_set_interpolator_rate(struct snd_soc_dai *dai,
7499 u32 sample_rate)
7500{
7501 struct snd_soc_codec *codec = dai->codec;
7502 int rate_val = 0;
7503 int i, ret;
7504
7505 for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) {
7506 if (sample_rate == sr_val_tbl[i].sample_rate) {
7507 rate_val = sr_val_tbl[i].rate_val;
7508 break;
7509 }
7510 }
7511 if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
7512 dev_err(codec->dev, "%s: Unsupported sample rate: %d\n",
7513 __func__, sample_rate);
7514 return -EINVAL;
7515 }
7516
7517 ret = tavil_set_prim_interpolator_rate(dai, (u8)rate_val, sample_rate);
7518 if (ret)
7519 return ret;
7520 ret = tavil_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate);
7521 if (ret)
7522 return ret;
7523
7524 return ret;
7525}
7526
7527static int tavil_prepare(struct snd_pcm_substream *substream,
7528 struct snd_soc_dai *dai)
7529{
7530 pr_debug("%s(): substream = %s stream = %d\n", __func__,
7531 substream->name, substream->stream);
7532 return 0;
7533}
7534
7535static int tavil_vi_hw_params(struct snd_pcm_substream *substream,
7536 struct snd_pcm_hw_params *params,
7537 struct snd_soc_dai *dai)
7538{
7539 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7540
7541 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7542 __func__, dai->name, dai->id, params_rate(params),
7543 params_channels(params));
7544
7545 tavil->dai[dai->id].rate = params_rate(params);
7546 tavil->dai[dai->id].bit_width = 32;
7547
7548 return 0;
7549}
7550
7551static int tavil_hw_params(struct snd_pcm_substream *substream,
7552 struct snd_pcm_hw_params *params,
7553 struct snd_soc_dai *dai)
7554{
7555 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
7556 int ret = 0;
7557
7558 dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
7559 __func__, dai->name, dai->id, params_rate(params),
7560 params_channels(params));
7561
7562 switch (substream->stream) {
7563 case SNDRV_PCM_STREAM_PLAYBACK:
7564 ret = tavil_set_interpolator_rate(dai, params_rate(params));
7565 if (ret) {
7566 dev_err(tavil->dev, "%s: cannot set sample rate: %u\n",
7567 __func__, params_rate(params));
7568 return ret;
7569 }
7570 switch (params_width(params)) {
7571 case 16:
7572 tavil->dai[dai->id].bit_width = 16;
7573 break;
7574 case 24:
7575 tavil->dai[dai->id].bit_width = 24;
7576 break;
7577 case 32:
7578 tavil->dai[dai->id].bit_width = 32;
7579 break;
7580 default:
7581 return -EINVAL;
7582 }
7583 tavil->dai[dai->id].rate = params_rate(params);
7584 break;
7585 case SNDRV_PCM_STREAM_CAPTURE:
7586 if (dai->id != AIF4_MAD_TX)
7587 ret = tavil_set_decimator_rate(dai,
7588 params_rate(params));
7589 if (ret) {
7590 dev_err(tavil->dev, "%s: cannot set TX Decimator rate: %d\n",
7591 __func__, ret);
7592 return ret;
7593 }
7594 switch (params_width(params)) {
7595 case 16:
7596 tavil->dai[dai->id].bit_width = 16;
7597 break;
7598 case 24:
7599 tavil->dai[dai->id].bit_width = 24;
7600 break;
7601 default:
7602 dev_err(tavil->dev, "%s: Invalid format 0x%x\n",
7603 __func__, params_width(params));
7604 return -EINVAL;
7605 };
7606 tavil->dai[dai->id].rate = params_rate(params);
7607 break;
7608 default:
7609 dev_err(tavil->dev, "%s: Invalid stream type %d\n", __func__,
7610 substream->stream);
7611 return -EINVAL;
7612 };
7613
7614 return 0;
7615}
7616
7617static struct snd_soc_dai_ops tavil_dai_ops = {
7618 .startup = tavil_startup,
7619 .shutdown = tavil_shutdown,
7620 .hw_params = tavil_hw_params,
7621 .prepare = tavil_prepare,
7622 .set_channel_map = tavil_set_channel_map,
7623 .get_channel_map = tavil_get_channel_map,
7624};
7625
7626static struct snd_soc_dai_ops tavil_vi_dai_ops = {
7627 .hw_params = tavil_vi_hw_params,
7628 .set_channel_map = tavil_set_channel_map,
7629 .get_channel_map = tavil_get_channel_map,
7630};
7631
7632static struct snd_soc_dai_driver tavil_dai[] = {
7633 {
7634 .name = "tavil_rx1",
7635 .id = AIF1_PB,
7636 .playback = {
7637 .stream_name = "AIF1 Playback",
7638 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7639 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7640 .rate_min = 8000,
7641 .rate_max = 384000,
7642 .channels_min = 1,
7643 .channels_max = 2,
7644 },
7645 .ops = &tavil_dai_ops,
7646 },
7647 {
7648 .name = "tavil_tx1",
7649 .id = AIF1_CAP,
7650 .capture = {
7651 .stream_name = "AIF1 Capture",
7652 .rates = WCD934X_RATES_MASK,
7653 .formats = WCD934X_FORMATS_S16_S24_LE,
7654 .rate_min = 8000,
7655 .rate_max = 192000,
7656 .channels_min = 1,
7657 .channels_max = 4,
7658 },
7659 .ops = &tavil_dai_ops,
7660 },
7661 {
7662 .name = "tavil_rx2",
7663 .id = AIF2_PB,
7664 .playback = {
7665 .stream_name = "AIF2 Playback",
7666 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7667 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7668 .rate_min = 8000,
7669 .rate_max = 384000,
7670 .channels_min = 1,
7671 .channels_max = 2,
7672 },
7673 .ops = &tavil_dai_ops,
7674 },
7675 {
7676 .name = "tavil_tx2",
7677 .id = AIF2_CAP,
7678 .capture = {
7679 .stream_name = "AIF2 Capture",
7680 .rates = WCD934X_RATES_MASK,
7681 .formats = WCD934X_FORMATS_S16_S24_LE,
7682 .rate_min = 8000,
7683 .rate_max = 192000,
7684 .channels_min = 1,
7685 .channels_max = 4,
7686 },
7687 .ops = &tavil_dai_ops,
7688 },
7689 {
7690 .name = "tavil_rx3",
7691 .id = AIF3_PB,
7692 .playback = {
7693 .stream_name = "AIF3 Playback",
7694 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7695 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7696 .rate_min = 8000,
7697 .rate_max = 384000,
7698 .channels_min = 1,
7699 .channels_max = 2,
7700 },
7701 .ops = &tavil_dai_ops,
7702 },
7703 {
7704 .name = "tavil_tx3",
7705 .id = AIF3_CAP,
7706 .capture = {
7707 .stream_name = "AIF3 Capture",
7708 .rates = WCD934X_RATES_MASK,
7709 .formats = WCD934X_FORMATS_S16_S24_LE,
7710 .rate_min = 8000,
7711 .rate_max = 192000,
7712 .channels_min = 1,
7713 .channels_max = 4,
7714 },
7715 .ops = &tavil_dai_ops,
7716 },
7717 {
7718 .name = "tavil_rx4",
7719 .id = AIF4_PB,
7720 .playback = {
7721 .stream_name = "AIF4 Playback",
7722 .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
7723 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7724 .rate_min = 8000,
7725 .rate_max = 384000,
7726 .channels_min = 1,
7727 .channels_max = 2,
7728 },
7729 .ops = &tavil_dai_ops,
7730 },
7731 {
7732 .name = "tavil_vifeedback",
7733 .id = AIF4_VIFEED,
7734 .capture = {
7735 .stream_name = "VIfeed",
7736 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
7737 .formats = WCD934X_FORMATS_S16_S24_S32_LE,
7738 .rate_min = 8000,
7739 .rate_max = 48000,
7740 .channels_min = 1,
7741 .channels_max = 4,
7742 },
7743 .ops = &tavil_vi_dai_ops,
7744 },
7745 {
7746 .name = "tavil_mad1",
7747 .id = AIF4_MAD_TX,
7748 .capture = {
7749 .stream_name = "AIF4 MAD TX",
7750 .rates = SNDRV_PCM_RATE_16000,
7751 .formats = WCD934X_FORMATS_S16_LE,
7752 .rate_min = 16000,
7753 .rate_max = 16000,
7754 .channels_min = 1,
7755 .channels_max = 1,
7756 },
7757 .ops = &tavil_dai_ops,
7758 },
7759};
7760
7761static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil)
7762{
7763 struct snd_soc_codec *codec = tavil->codec;
7764
7765 if (!codec)
7766 return;
7767
7768 mutex_lock(&tavil->power_lock);
7769 dev_dbg(codec->dev, "%s: Entering power gating function, %d\n",
7770 __func__, tavil->power_active_ref);
7771
7772 if (tavil->power_active_ref > 0)
7773 goto exit;
7774
7775 wcd9xxx_set_power_state(tavil->wcd9xxx,
7776 WCD_REGION_POWER_COLLAPSE_BEGIN,
7777 WCD9XXX_DIG_CORE_REGION_1);
7778 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
7779 0x04, 0x04);
7780 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
7781 0x01, 0x00);
7782 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
7783 0x02, 0x00);
7784 wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_DOWN,
7785 WCD9XXX_DIG_CORE_REGION_1);
7786exit:
7787 dev_dbg(codec->dev, "%s: Exiting power gating function, %d\n",
7788 __func__, tavil->power_active_ref);
7789 mutex_unlock(&tavil->power_lock);
7790}
7791
7792static void tavil_codec_power_gate_work(struct work_struct *work)
7793{
7794 struct tavil_priv *tavil;
7795 struct delayed_work *dwork;
7796 struct snd_soc_codec *codec;
7797
7798 dwork = to_delayed_work(work);
7799 tavil = container_of(dwork, struct tavil_priv, power_gate_work);
7800 codec = tavil->codec;
7801
7802 if (!codec)
7803 return;
7804
7805 tavil_codec_power_gate_digital_core(tavil);
7806}
7807
7808/* called under power_lock acquisition */
7809static int tavil_dig_core_remove_power_collapse(struct snd_soc_codec *codec)
7810{
7811 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
7812
7813 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
7814 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
7815 snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
7816 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00);
7817 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02);
7818
7819 wcd9xxx_set_power_state(tavil->wcd9xxx,
7820 WCD_REGION_POWER_COLLAPSE_REMOVE,
7821 WCD9XXX_DIG_CORE_REGION_1);
7822 regcache_mark_dirty(codec->component.regmap);
7823 regcache_sync_region(codec->component.regmap,
7824 WCD934X_DIG_CORE_REG_MIN,
7825 WCD934X_DIG_CORE_REG_MAX);
7826
7827 return 0;
7828}
7829
7830static int tavil_dig_core_power_collapse(struct tavil_priv *tavil,
7831 int req_state)
7832{
7833 struct snd_soc_codec *codec;
7834 int cur_state;
7835
7836 /* Exit if feature is disabled */
7837 if (!dig_core_collapse_enable)
7838 return 0;
7839
7840 mutex_lock(&tavil->power_lock);
7841 if (req_state == POWER_COLLAPSE)
7842 tavil->power_active_ref--;
7843 else if (req_state == POWER_RESUME)
7844 tavil->power_active_ref++;
7845 else
7846 goto unlock_mutex;
7847
7848 if (tavil->power_active_ref < 0) {
7849 dev_dbg(tavil->dev, "%s: power_active_ref is negative\n",
7850 __func__);
7851 goto unlock_mutex;
7852 }
7853
7854 codec = tavil->codec;
7855 if (!codec)
7856 goto unlock_mutex;
7857
7858 if (req_state == POWER_COLLAPSE) {
7859 if (tavil->power_active_ref == 0) {
7860 schedule_delayed_work(&tavil->power_gate_work,
7861 msecs_to_jiffies(dig_core_collapse_timer * 1000));
7862 }
7863 } else if (req_state == POWER_RESUME) {
7864 if (tavil->power_active_ref == 1) {
7865 /*
7866 * At this point, there can be two cases:
7867 * 1. Core already in power collapse state
7868 * 2. Timer kicked in and still did not expire or
7869 * waiting for the power_lock
7870 */
7871 cur_state = wcd9xxx_get_current_power_state(
7872 tavil->wcd9xxx,
7873 WCD9XXX_DIG_CORE_REGION_1);
7874 if (cur_state == WCD_REGION_POWER_DOWN) {
7875 tavil_dig_core_remove_power_collapse(codec);
7876 } else {
7877 mutex_unlock(&tavil->power_lock);
7878 cancel_delayed_work_sync(
7879 &tavil->power_gate_work);
7880 mutex_lock(&tavil->power_lock);
7881 }
7882 }
7883 }
7884
7885unlock_mutex:
7886 mutex_unlock(&tavil->power_lock);
7887
7888 return 0;
7889}
7890
7891static int tavil_cdc_req_mclk_enable(struct tavil_priv *tavil,
7892 bool enable)
7893{
7894 int ret = 0;
7895
7896 if (enable) {
7897 ret = clk_prepare_enable(tavil->wcd_ext_clk);
7898 if (ret) {
7899 dev_err(tavil->dev, "%s: ext clk enable failed\n",
7900 __func__);
7901 goto done;
7902 }
7903 /* get BG */
7904 wcd_resmgr_enable_master_bias(tavil->resmgr);
7905 /* get MCLK */
7906 wcd_resmgr_enable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
7907 } else {
7908 /* put MCLK */
7909 wcd_resmgr_disable_clk_block(tavil->resmgr, WCD_CLK_MCLK);
7910 /* put BG */
7911 wcd_resmgr_disable_master_bias(tavil->resmgr);
7912 clk_disable_unprepare(tavil->wcd_ext_clk);
7913 }
7914
7915done:
7916 return ret;
7917}
7918
7919static int __tavil_cdc_mclk_enable_locked(struct tavil_priv *tavil,
7920 bool enable)
7921{
7922 int ret = 0;
7923
7924 if (!tavil->wcd_ext_clk) {
7925 dev_err(tavil->dev, "%s: wcd ext clock is NULL\n", __func__);
7926 return -EINVAL;
7927 }
7928
7929 dev_dbg(tavil->dev, "%s: mclk_enable = %u\n", __func__, enable);
7930
7931 if (enable) {
7932 tavil_dig_core_power_collapse(tavil, POWER_RESUME);
7933 tavil_vote_svs(tavil, true);
7934 ret = tavil_cdc_req_mclk_enable(tavil, true);
7935 if (ret)
7936 goto done;
7937 } else {
7938 tavil_cdc_req_mclk_enable(tavil, false);
7939 tavil_vote_svs(tavil, false);
7940 tavil_dig_core_power_collapse(tavil, POWER_COLLAPSE);
7941 }
7942
7943done:
7944 return ret;
7945}
7946
7947static int __tavil_cdc_mclk_enable(struct tavil_priv *tavil,
7948 bool enable)
7949{
7950 int ret;
7951
7952 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
7953 ret = __tavil_cdc_mclk_enable_locked(tavil, enable);
7954 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
7955
7956 return ret;
7957}
7958
7959static ssize_t tavil_codec_version_read(struct snd_info_entry *entry,
7960 void *file_private_data,
7961 struct file *file,
7962 char __user *buf, size_t count,
7963 loff_t pos)
7964{
7965 struct tavil_priv *tavil;
7966 struct wcd9xxx *wcd9xxx;
7967 char buffer[TAVIL_VERSION_ENTRY_SIZE];
7968 int len = 0;
7969
7970 tavil = (struct tavil_priv *) entry->private_data;
7971 if (!tavil) {
7972 pr_err("%s: tavil priv is null\n", __func__);
7973 return -EINVAL;
7974 }
7975
7976 wcd9xxx = tavil->wcd9xxx;
7977
7978 switch (wcd9xxx->version) {
7979 case TAVIL_VERSION_WCD9340_1_0:
7980 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_0\n");
7981 break;
7982 case TAVIL_VERSION_WCD9341_1_0:
7983 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_0\n");
7984 break;
7985 case TAVIL_VERSION_WCD9340_1_1:
7986 len = snprintf(buffer, sizeof(buffer), "WCD9340_1_1\n");
7987 break;
7988 case TAVIL_VERSION_WCD9341_1_1:
7989 len = snprintf(buffer, sizeof(buffer), "WCD9341_1_1\n");
7990 break;
7991 default:
7992 len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
7993 }
7994
7995 return simple_read_from_buffer(buf, count, &pos, buffer, len);
7996}
7997
7998static struct snd_info_entry_ops tavil_codec_info_ops = {
7999 .read = tavil_codec_version_read,
8000};
8001
8002/*
8003 * tavil_codec_info_create_codec_entry - creates wcd934x module
8004 * @codec_root: The parent directory
8005 * @codec: Codec instance
8006 *
8007 * Creates wcd934x module and version entry under the given
8008 * parent directory.
8009 *
8010 * Return: 0 on success or negative error code on failure.
8011 */
8012int tavil_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
8013 struct snd_soc_codec *codec)
8014{
8015 struct snd_info_entry *version_entry;
8016 struct tavil_priv *tavil;
8017 struct snd_soc_card *card;
8018
8019 if (!codec_root || !codec)
8020 return -EINVAL;
8021
8022 tavil = snd_soc_codec_get_drvdata(codec);
8023 card = codec->component.card;
8024 tavil->entry = snd_register_module_info(codec_root->module,
8025 "tavil",
8026 codec_root);
8027 if (!tavil->entry) {
8028 dev_dbg(codec->dev, "%s: failed to create wcd934x entry\n",
8029 __func__);
8030 return -ENOMEM;
8031 }
8032
8033 version_entry = snd_info_create_card_entry(card->snd_card,
8034 "version",
8035 tavil->entry);
8036 if (!version_entry) {
8037 dev_dbg(codec->dev, "%s: failed to create wcd934x version entry\n",
8038 __func__);
8039 return -ENOMEM;
8040 }
8041
8042 version_entry->private_data = tavil;
8043 version_entry->size = TAVIL_VERSION_ENTRY_SIZE;
8044 version_entry->content = SNDRV_INFO_CONTENT_DATA;
8045 version_entry->c.ops = &tavil_codec_info_ops;
8046
8047 if (snd_info_register(version_entry) < 0) {
8048 snd_info_free_entry(version_entry);
8049 return -ENOMEM;
8050 }
8051 tavil->version_entry = version_entry;
8052
8053 return 0;
8054}
8055EXPORT_SYMBOL(tavil_codec_info_create_codec_entry);
8056
8057/**
8058 * tavil_cdc_mclk_enable - Enable/disable codec mclk
8059 *
8060 * @codec: codec instance
8061 * @enable: Indicates clk enable or disable
8062 *
8063 * Returns 0 on Success and error on failure
8064 */
8065int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
8066{
8067 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8068
8069 return __tavil_cdc_mclk_enable(tavil, enable);
8070}
8071EXPORT_SYMBOL(tavil_cdc_mclk_enable);
8072
8073static int __tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8074 bool enable)
8075{
8076 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8077 int ret = 0;
8078
8079 if (enable) {
8080 if (wcd_resmgr_get_clk_type(tavil->resmgr) ==
8081 WCD_CLK_RCO) {
8082 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8083 WCD_CLK_RCO);
8084 } else {
8085 ret = tavil_cdc_req_mclk_enable(tavil, true);
8086 if (ret) {
8087 dev_err(codec->dev,
8088 "%s: mclk_enable failed, err = %d\n",
8089 __func__, ret);
8090 goto done;
8091 }
8092 ret = wcd_resmgr_enable_clk_block(tavil->resmgr,
8093 WCD_CLK_RCO);
8094 ret |= tavil_cdc_req_mclk_enable(tavil, false);
8095 }
8096
8097 } else {
8098 ret = wcd_resmgr_disable_clk_block(tavil->resmgr,
8099 WCD_CLK_RCO);
8100 }
8101
8102 if (ret) {
8103 dev_err(codec->dev, "%s: Error in %s RCO\n",
8104 __func__, (enable ? "enabling" : "disabling"));
8105 ret = -EINVAL;
8106 }
8107
8108done:
8109 return ret;
8110}
8111
8112/*
8113 * tavil_codec_internal_rco_ctrl: Enable/Disable codec's RCO clock
8114 * @codec: Handle to the codec
8115 * @enable: Indicates whether clock should be enabled or disabled
8116 */
8117static int tavil_codec_internal_rco_ctrl(struct snd_soc_codec *codec,
8118 bool enable)
8119{
8120 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8121 int ret = 0;
8122
8123 WCD9XXX_V2_BG_CLK_LOCK(tavil->resmgr);
8124 ret = __tavil_codec_internal_rco_ctrl(codec, enable);
8125 WCD9XXX_V2_BG_CLK_UNLOCK(tavil->resmgr);
8126 return ret;
8127}
8128
8129static const struct wcd_resmgr_cb tavil_resmgr_cb = {
8130 .cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
8131};
8132
8133static const struct tavil_reg_mask_val tavil_codec_mclk2_1_1_defaults[] = {
8134 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8135};
8136
8137static const struct tavil_reg_mask_val tavil_codec_mclk2_1_0_defaults[] = {
8138 /*
8139 * PLL Settings:
8140 * Clock Root: MCLK2,
8141 * Clock Source: EXT_CLK,
8142 * Clock Destination: MCLK2
8143 * Clock Freq In: 19.2MHz,
8144 * Clock Freq Out: 11.2896MHz
8145 */
8146 {WCD934X_CLK_SYS_MCLK2_PRG1, 0x60, 0x20},
8147 {WCD934X_CLK_SYS_INT_POST_DIV_REG0, 0xFF, 0x5E},
8148 {WCD934X_CLK_SYS_INT_POST_DIV_REG1, 0x1F, 0x1F},
8149 {WCD934X_CLK_SYS_INT_REF_DIV_REG0, 0xFF, 0x54},
8150 {WCD934X_CLK_SYS_INT_REF_DIV_REG1, 0xFF, 0x01},
8151 {WCD934X_CLK_SYS_INT_FILTER_REG1, 0x07, 0x04},
8152 {WCD934X_CLK_SYS_INT_PLL_L_VAL, 0xFF, 0x93},
8153 {WCD934X_CLK_SYS_INT_PLL_N_VAL, 0xFF, 0xFA},
8154 {WCD934X_CLK_SYS_INT_TEST_REG0, 0xFF, 0x90},
8155 {WCD934X_CLK_SYS_INT_PFD_CP_DSM_PROG, 0xFF, 0x7E},
8156 {WCD934X_CLK_SYS_INT_VCO_PROG, 0xFF, 0xF8},
8157 {WCD934X_CLK_SYS_INT_TEST_REG1, 0xFF, 0x68},
8158 {WCD934X_CLK_SYS_INT_LDO_LOCK_CFG, 0xFF, 0x40},
8159 {WCD934X_CLK_SYS_INT_DIG_LOCK_DET_CFG, 0xFF, 0x32},
8160};
8161
8162static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
8163 {WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
8164 {WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
8165 {WCD934X_CODEC_CPR_SVS2_CX_VDD, 0xFF, 0x58}, /* value in svs2 mode */
8166 {WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8167 {WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8168 {WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8169 {WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8170 {WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8171 {WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8172 {WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
8173 {WCD934X_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
8174 {WCD934X_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
8175 {WCD934X_CDC_RX0_RX_PATH_SEC0, 0x08, 0x0},
8176 {WCD934X_CDC_CLSH_DECAY_CTRL, 0x03, 0x0},
8177 {WCD934X_MICB1_TEST_CTL_2, 0x07, 0x01},
8178 {WCD934X_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
8179 {WCD934X_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
8180 {WCD934X_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12},
8181 {WCD934X_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08},
8182 {WCD934X_CPE_SS_CPARMAD_BUFRDY_INT_PERIOD, 0x1F, 0x09},
8183 {WCD934X_CDC_TX0_TX_PATH_CFG1, 0x01, 0x00},
8184 {WCD934X_CDC_TX1_TX_PATH_CFG1, 0x01, 0x00},
8185 {WCD934X_CDC_TX2_TX_PATH_CFG1, 0x01, 0x00},
8186 {WCD934X_CDC_TX3_TX_PATH_CFG1, 0x01, 0x00},
8187 {WCD934X_CDC_TX4_TX_PATH_CFG1, 0x01, 0x00},
8188 {WCD934X_CDC_TX5_TX_PATH_CFG1, 0x01, 0x00},
8189 {WCD934X_CDC_TX6_TX_PATH_CFG1, 0x01, 0x00},
8190 {WCD934X_CDC_TX7_TX_PATH_CFG1, 0x01, 0x00},
8191 {WCD934X_CDC_TX8_TX_PATH_CFG1, 0x01, 0x00},
8192 {WCD934X_RX_OCP_CTL, 0x0F, 0x02}, /* OCP number of attempts is 2 */
8193 {WCD934X_HPH_OCP_CTL, 0xFF, 0x3A}, /* OCP current limit */
8194 {WCD934X_HPH_L_TEST, 0x01, 0x01},
8195 {WCD934X_HPH_R_TEST, 0x01, 0x01},
8196 {WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
8197};
8198
8199static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
8200 {WCD934X_CDC_COMPANDER1_CTL7, 0x1E, 0x06},
8201 {WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06},
8202 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84},
8203 {WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84},
8204 {WCD934X_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
8205 {WCD934X_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
8206};
8207
8208static const struct tavil_cpr_reg_defaults cpr_defaults[] = {
8209 { 0x00000820, 0x00000094 },
8210 { 0x00000fC0, 0x00000048 },
8211 { 0x0000f000, 0x00000044 },
8212 { 0x0000bb80, 0xC0000178 },
8213 { 0x00000000, 0x00000160 },
8214 { 0x10854522, 0x00000060 },
8215 { 0x10854509, 0x00000064 },
8216 { 0x108544dd, 0x00000068 },
8217 { 0x108544ad, 0x0000006C },
8218 { 0x0000077E, 0x00000070 },
8219 { 0x000007da, 0x00000074 },
8220 { 0x00000000, 0x00000078 },
8221 { 0x00000000, 0x0000007C },
8222 { 0x00042029, 0x00000080 },
8223 { 0x4002002A, 0x00000090 },
8224 { 0x4002002B, 0x00000090 },
8225};
8226
8227static const struct tavil_reg_mask_val tavil_codec_reg_init_common_val[] = {
8228 {WCD934X_CDC_CLSH_K2_MSB, 0x0F, 0x00},
8229 {WCD934X_CDC_CLSH_K2_LSB, 0xFF, 0x60},
8230 {WCD934X_CPE_SS_DMIC_CFG, 0x80, 0x00},
8231 {WCD934X_CDC_BOOST0_BOOST_CTL, 0x70, 0x50},
8232 {WCD934X_CDC_BOOST1_BOOST_CTL, 0x70, 0x50},
8233 {WCD934X_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08},
8234 {WCD934X_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
8235 {WCD934X_CDC_TOP_TOP_CFG1, 0x02, 0x02},
8236 {WCD934X_CDC_TOP_TOP_CFG1, 0x01, 0x01},
8237 {WCD934X_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8238 {WCD934X_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8239 {WCD934X_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8240 {WCD934X_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
8241 {WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0x01, 0x01},
8242 {WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL, 0x01, 0x01},
8243 {WCD934X_CDC_COMPANDER7_CTL3, 0x80, 0x80},
8244 {WCD934X_CDC_COMPANDER8_CTL3, 0x80, 0x80},
8245 {WCD934X_CDC_COMPANDER7_CTL7, 0x01, 0x01},
8246 {WCD934X_CDC_COMPANDER8_CTL7, 0x01, 0x01},
8247 {WCD934X_CODEC_RPM_CLK_GATE, 0x08, 0x00},
8248 {WCD934X_TLMM_DMIC3_CLK_PINCFG, 0xFF, 0x0a},
8249 {WCD934X_TLMM_DMIC3_DATA_PINCFG, 0xFF, 0x0a},
8250 {WCD934X_CPE_SS_SVA_CFG, 0x60, 0x00},
8251};
8252
8253static void tavil_codec_init_reg(struct tavil_priv *priv)
8254{
8255 struct snd_soc_codec *codec = priv->codec;
8256 u32 i;
8257
8258 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_common_val); i++)
8259 snd_soc_update_bits(codec,
8260 tavil_codec_reg_init_common_val[i].reg,
8261 tavil_codec_reg_init_common_val[i].mask,
8262 tavil_codec_reg_init_common_val[i].val);
8263
8264 if (TAVIL_IS_1_1(priv->wcd9xxx)) {
8265 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_init_1_1_val); i++)
8266 snd_soc_update_bits(codec,
8267 tavil_codec_reg_init_1_1_val[i].reg,
8268 tavil_codec_reg_init_1_1_val[i].mask,
8269 tavil_codec_reg_init_1_1_val[i].val);
8270 }
8271}
8272
8273static void tavil_update_reg_defaults(struct tavil_priv *tavil)
8274{
8275 u32 i;
8276 struct wcd9xxx *wcd9xxx;
8277
8278 wcd9xxx = tavil->wcd9xxx;
8279 for (i = 0; i < ARRAY_SIZE(tavil_codec_reg_defaults); i++)
8280 regmap_update_bits(wcd9xxx->regmap,
8281 tavil_codec_reg_defaults[i].reg,
8282 tavil_codec_reg_defaults[i].mask,
8283 tavil_codec_reg_defaults[i].val);
8284}
8285
8286static void tavil_update_cpr_defaults(struct tavil_priv *tavil)
8287{
8288 int i;
8289 struct wcd9xxx *wcd9xxx;
8290
8291 wcd9xxx = tavil->wcd9xxx;
8292 if (!TAVIL_IS_1_1(wcd9xxx))
8293 return;
8294
8295 __tavil_cdc_mclk_enable(tavil, true);
8296
8297 regmap_write(wcd9xxx->regmap, WCD934X_CODEC_CPR_SVS2_MIN_CX_VDD, 0x2C);
8298 regmap_update_bits(wcd9xxx->regmap, WCD934X_CODEC_RPM_CLK_GATE,
8299 0x10, 0x00);
8300
8301 for (i = 0; i < ARRAY_SIZE(cpr_defaults); i++) {
8302 regmap_bulk_write(wcd9xxx->regmap,
8303 WCD934X_CODEC_CPR_WR_DATA_0,
8304 (u8 *)&cpr_defaults[i].wr_data, 4);
8305 regmap_bulk_write(wcd9xxx->regmap,
8306 WCD934X_CODEC_CPR_WR_ADDR_0,
8307 (u8 *)&cpr_defaults[i].wr_addr, 4);
8308 }
8309
8310 __tavil_cdc_mclk_enable(tavil, false);
8311}
8312
8313static void tavil_slim_interface_init_reg(struct snd_soc_codec *codec)
8314{
8315 int i;
8316 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8317
8318 for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
8319 wcd9xxx_interface_reg_write(priv->wcd9xxx,
8320 WCD934X_SLIM_PGD_PORT_INT_RX_EN0 + i,
8321 0xFF);
8322}
8323
8324static irqreturn_t tavil_misc_irq(int irq, void *data)
8325{
8326 struct tavil_priv *tavil = data;
8327 int misc_val;
8328
8329 /* Find source of interrupt */
8330 regmap_read(tavil->wcd9xxx->regmap, WCD934X_INTR_CODEC_MISC_STATUS,
8331 &misc_val);
8332
8333 if (misc_val & 0x08) {
8334 dev_info(tavil->dev, "%s: irq: %d, DSD DC detected!\n",
8335 __func__, irq);
8336 /* DSD DC interrupt, reset DSD path */
8337 tavil_dsd_reset(tavil->dsd_config);
8338 } else {
8339 dev_err(tavil->dev, "%s: Codec misc irq: %d, val: 0x%x\n",
8340 __func__, irq, misc_val);
8341 }
8342
8343 /* Clear interrupt status */
8344 regmap_update_bits(tavil->wcd9xxx->regmap,
8345 WCD934X_INTR_CODEC_MISC_CLEAR, misc_val, 0x00);
8346
8347 return IRQ_HANDLED;
8348}
8349
8350static irqreturn_t tavil_slimbus_irq(int irq, void *data)
8351{
8352 struct tavil_priv *tavil = data;
8353 unsigned long status = 0;
8354 int i, j, port_id, k;
8355 u32 bit;
8356 u8 val, int_val = 0;
8357 bool tx, cleared;
8358 unsigned short reg = 0;
8359
8360 for (i = WCD934X_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
8361 i <= WCD934X_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
8362 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx, i);
8363 status |= ((u32)val << (8 * j));
8364 }
8365
8366 for_each_set_bit(j, &status, 32) {
8367 tx = (j >= 16 ? true : false);
8368 port_id = (tx ? j - 16 : j);
8369 val = wcd9xxx_interface_reg_read(tavil->wcd9xxx,
8370 WCD934X_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
8371 if (val) {
8372 if (!tx)
8373 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8374 (port_id / 8);
8375 else
8376 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8377 (port_id / 8);
8378 int_val = wcd9xxx_interface_reg_read(
8379 tavil->wcd9xxx, reg);
8380 /*
8381 * Ignore interrupts for ports for which the
8382 * interrupts are not specifically enabled.
8383 */
8384 if (!(int_val & (1 << (port_id % 8))))
8385 continue;
8386 }
8387 if (val & WCD934X_SLIM_IRQ_OVERFLOW)
8388 dev_err_ratelimited(tavil->dev, "%s: overflow error on %s port %d, value %x\n",
8389 __func__, (tx ? "TX" : "RX"), port_id, val);
8390 if (val & WCD934X_SLIM_IRQ_UNDERFLOW)
8391 dev_err_ratelimited(tavil->dev, "%s: underflow error on %s port %d, value %x\n",
8392 __func__, (tx ? "TX" : "RX"), port_id, val);
8393 if ((val & WCD934X_SLIM_IRQ_OVERFLOW) ||
8394 (val & WCD934X_SLIM_IRQ_UNDERFLOW)) {
8395 if (!tx)
8396 reg = WCD934X_SLIM_PGD_PORT_INT_RX_EN0 +
8397 (port_id / 8);
8398 else
8399 reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 +
8400 (port_id / 8);
8401 int_val = wcd9xxx_interface_reg_read(
8402 tavil->wcd9xxx, reg);
8403 if (int_val & (1 << (port_id % 8))) {
8404 int_val = int_val ^ (1 << (port_id % 8));
8405 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8406 reg, int_val);
8407 }
8408 }
8409 if (val & WCD934X_SLIM_IRQ_PORT_CLOSED) {
8410 /*
8411 * INT SOURCE register starts from RX to TX
8412 * but port number in the ch_mask is in opposite way
8413 */
8414 bit = (tx ? j - 16 : j + 16);
8415 dev_dbg(tavil->dev, "%s: %s port %d closed value %x, bit %u\n",
8416 __func__, (tx ? "TX" : "RX"), port_id, val,
8417 bit);
8418 for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
8419 dev_dbg(tavil->dev, "%s: tavil->dai[%d].ch_mask = 0x%lx\n",
8420 __func__, k, tavil->dai[k].ch_mask);
8421 if (test_and_clear_bit(bit,
8422 &tavil->dai[k].ch_mask)) {
8423 cleared = true;
8424 if (!tavil->dai[k].ch_mask)
8425 wake_up(
8426 &tavil->dai[k].dai_wait);
8427 /*
8428 * There are cases when multiple DAIs
8429 * might be using the same slimbus
8430 * channel. Hence don't break here.
8431 */
8432 }
8433 }
8434 WARN(!cleared,
8435 "Couldn't find slimbus %s port %d for closing\n",
8436 (tx ? "TX" : "RX"), port_id);
8437 }
8438 wcd9xxx_interface_reg_write(tavil->wcd9xxx,
8439 WCD934X_SLIM_PGD_PORT_INT_CLR_RX_0 +
8440 (j / 8),
8441 1 << (j % 8));
8442 }
8443
8444 return IRQ_HANDLED;
8445}
8446
8447static int tavil_setup_irqs(struct tavil_priv *tavil)
8448{
8449 int ret = 0;
8450 struct snd_soc_codec *codec = tavil->codec;
8451 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8452 struct wcd9xxx_core_resource *core_res =
8453 &wcd9xxx->core_res;
8454
8455 ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_SLIMBUS,
8456 tavil_slimbus_irq, "SLIMBUS Slave", tavil);
8457 if (ret)
8458 dev_err(codec->dev, "%s: Failed to request irq %d\n", __func__,
8459 WCD9XXX_IRQ_SLIMBUS);
8460 else
8461 tavil_slim_interface_init_reg(codec);
8462
8463 /* Register for misc interrupts as well */
8464 ret = wcd9xxx_request_irq(core_res, WCD934X_IRQ_MISC,
8465 tavil_misc_irq, "CDC MISC Irq", tavil);
8466 if (ret)
8467 dev_err(codec->dev, "%s: Failed to request cdc misc irq\n",
8468 __func__);
8469
8470 return ret;
8471}
8472
8473static void tavil_init_slim_slave_cfg(struct snd_soc_codec *codec)
8474{
8475 struct tavil_priv *priv = snd_soc_codec_get_drvdata(codec);
8476 struct afe_param_cdc_slimbus_slave_cfg *cfg;
8477 struct wcd9xxx *wcd9xxx = priv->wcd9xxx;
8478 uint64_t eaddr = 0;
8479
8480 cfg = &priv->slimbus_slave_cfg;
8481 cfg->minor_version = 1;
8482 cfg->tx_slave_port_offset = 0;
8483 cfg->rx_slave_port_offset = 16;
8484
8485 memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
8486 WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
8487 cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
8488 cfg->device_enum_addr_msw = eaddr >> 32;
8489
8490 dev_dbg(codec->dev, "%s: slimbus logical address 0x%llx\n",
8491 __func__, eaddr);
8492}
8493
8494static void tavil_cleanup_irqs(struct tavil_priv *tavil)
8495{
8496 struct wcd9xxx *wcd9xxx = tavil->wcd9xxx;
8497 struct wcd9xxx_core_resource *core_res =
8498 &wcd9xxx->core_res;
8499
8500 wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_SLIMBUS, tavil);
8501 wcd9xxx_free_irq(core_res, WCD934X_IRQ_MISC, tavil);
8502}
8503
8504/*
8505 * wcd934x_get_micb_vout_ctl_val: converts micbias from volts to register value
8506 * @micb_mv: micbias in mv
8507 *
8508 * return register value converted
8509 */
8510int wcd934x_get_micb_vout_ctl_val(u32 micb_mv)
8511{
8512 /* min micbias voltage is 1V and maximum is 2.85V */
8513 if (micb_mv < 1000 || micb_mv > 2850) {
8514 pr_err("%s: unsupported micbias voltage\n", __func__);
8515 return -EINVAL;
8516 }
8517
8518 return (micb_mv - 1000) / 50;
8519}
8520EXPORT_SYMBOL(wcd934x_get_micb_vout_ctl_val);
8521
8522static int tavil_handle_pdata(struct tavil_priv *tavil,
8523 struct wcd9xxx_pdata *pdata)
8524{
8525 struct snd_soc_codec *codec = tavil->codec;
8526 u8 mad_dmic_ctl_val;
8527 u8 anc_ctl_value;
8528 u32 def_dmic_rate, dmic_clk_drv;
8529 int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
8530 int rc = 0;
8531
8532 if (!pdata) {
8533 dev_err(codec->dev, "%s: NULL pdata\n", __func__);
8534 return -ENODEV;
8535 }
8536
8537 /* set micbias voltage */
8538 vout_ctl_1 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb1_mv);
8539 vout_ctl_2 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb2_mv);
8540 vout_ctl_3 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb3_mv);
8541 vout_ctl_4 = wcd934x_get_micb_vout_ctl_val(pdata->micbias.micb4_mv);
8542
8543 if (IS_ERR_VALUE(vout_ctl_1) || IS_ERR_VALUE(vout_ctl_2) ||
8544 IS_ERR_VALUE(vout_ctl_3) || IS_ERR_VALUE(vout_ctl_4)) {
8545 rc = -EINVAL;
8546 goto done;
8547 }
8548 snd_soc_update_bits(codec, WCD934X_ANA_MICB1, 0x3F, vout_ctl_1);
8549 snd_soc_update_bits(codec, WCD934X_ANA_MICB2, 0x3F, vout_ctl_2);
8550 snd_soc_update_bits(codec, WCD934X_ANA_MICB3, 0x3F, vout_ctl_3);
8551 snd_soc_update_bits(codec, WCD934X_ANA_MICB4, 0x3F, vout_ctl_4);
8552
8553 /* Set the DMIC sample rate */
8554 switch (pdata->mclk_rate) {
8555 case WCD934X_MCLK_CLK_9P6MHZ:
8556 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
8557 break;
8558 case WCD934X_MCLK_CLK_12P288MHZ:
8559 def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ;
8560 break;
8561 default:
8562 /* should never happen */
8563 dev_err(codec->dev, "%s: Invalid mclk_rate %d\n",
8564 __func__, pdata->mclk_rate);
8565 rc = -EINVAL;
8566 goto done;
8567 };
8568
8569 if (pdata->dmic_sample_rate ==
8570 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8571 dev_info(codec->dev, "%s: dmic_rate invalid default = %d\n",
8572 __func__, def_dmic_rate);
8573 pdata->dmic_sample_rate = def_dmic_rate;
8574 }
8575 if (pdata->mad_dmic_sample_rate ==
8576 WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED) {
8577 dev_info(codec->dev, "%s: mad_dmic_rate invalid default = %d\n",
8578 __func__, def_dmic_rate);
8579 /*
8580 * use dmic_sample_rate as the default for MAD
8581 * if mad dmic sample rate is undefined
8582 */
8583 pdata->mad_dmic_sample_rate = pdata->dmic_sample_rate;
8584 }
8585
8586 if (pdata->dmic_clk_drv ==
8587 WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED) {
8588 pdata->dmic_clk_drv = WCD934X_DMIC_CLK_DRIVE_DEFAULT;
8589 dev_info(codec->dev,
8590 "%s: dmic_clk_strength invalid, default = %d\n",
8591 __func__, pdata->dmic_clk_drv);
8592 }
8593
8594 switch (pdata->dmic_clk_drv) {
8595 case 2:
8596 dmic_clk_drv = 0;
8597 break;
8598 case 4:
8599 dmic_clk_drv = 1;
8600 break;
8601 case 8:
8602 dmic_clk_drv = 2;
8603 break;
8604 case 16:
8605 dmic_clk_drv = 3;
8606 break;
8607 default:
8608 dev_err(codec->dev,
8609 "%s: invalid dmic_clk_drv %d, using default\n",
8610 __func__, pdata->dmic_clk_drv);
8611 dmic_clk_drv = 0;
8612 break;
8613 }
8614
8615 snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_PAD_DRVCTL_0,
8616 0x0C, dmic_clk_drv << 2);
8617
8618 /*
8619 * Default the DMIC clk rates to mad_dmic_sample_rate,
8620 * whereas, the anc/txfe dmic rates to dmic_sample_rate
8621 * since the anc/txfe are independent of mad block.
8622 */
8623 mad_dmic_ctl_val = tavil_get_dmic_clk_val(tavil->codec,
8624 pdata->mclk_rate,
8625 pdata->mad_dmic_sample_rate);
8626 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC0_CTL,
8627 0x0E, mad_dmic_ctl_val << 1);
8628 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC1_CTL,
8629 0x0E, mad_dmic_ctl_val << 1);
8630 snd_soc_update_bits(codec, WCD934X_CPE_SS_DMIC2_CTL,
8631 0x0E, mad_dmic_ctl_val << 1);
8632
8633 if (dmic_clk_drv == WCD934X_DMIC_CLK_DIV_2)
8634 anc_ctl_value = WCD934X_ANC_DMIC_X2_FULL_RATE;
8635 else
8636 anc_ctl_value = WCD934X_ANC_DMIC_X2_HALF_RATE;
8637
8638 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8639 0x40, anc_ctl_value << 6);
8640 snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_2_CTL,
8641 0x20, anc_ctl_value << 5);
8642 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8643 0x40, anc_ctl_value << 6);
8644 snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_2_CTL,
8645 0x20, anc_ctl_value << 5);
8646
8647done:
8648 return rc;
8649}
8650
8651static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote)
8652{
8653 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
8654
8655 return tavil_vote_svs(tavil, vote);
8656}
8657
8658struct wcd_dsp_cdc_cb cdc_cb = {
8659 .cdc_clk_en = tavil_codec_internal_rco_ctrl,
8660 .cdc_vote_svs = tavil_cdc_vote_svs,
8661};
8662
8663static int tavil_wdsp_initialize(struct snd_soc_codec *codec)
8664{
8665 struct wcd9xxx *control;
8666 struct tavil_priv *tavil;
8667 struct wcd_dsp_params params;
8668 int ret = 0;
8669
8670 control = dev_get_drvdata(codec->dev->parent);
8671 tavil = snd_soc_codec_get_drvdata(codec);
8672
8673 params.cb = &cdc_cb;
8674 params.irqs.cpe_ipc1_irq = WCD934X_IRQ_CPE1_INTR;
8675 params.irqs.cpe_err_irq = WCD934X_IRQ_CPE_ERROR;
8676 params.irqs.fatal_irqs = CPE_FATAL_IRQS;
8677 params.clk_rate = control->mclk_rate;
8678 params.dsp_instance = 0;
8679
8680 wcd_dsp_cntl_init(codec, &params, &tavil->wdsp_cntl);
8681 if (!tavil->wdsp_cntl) {
8682 dev_err(tavil->dev, "%s: wcd-dsp-control init failed\n",
8683 __func__);
8684 ret = -EINVAL;
8685 }
8686
8687 return ret;
8688}
8689
8690/*
8691 * tavil_soc_get_mbhc: get wcd934x_mbhc handle of corresponding codec
8692 * @codec: handle to snd_soc_codec *
8693 *
8694 * return wcd934x_mbhc handle or error code in case of failure
8695 */
8696struct wcd934x_mbhc *tavil_soc_get_mbhc(struct snd_soc_codec *codec)
8697{
8698 struct tavil_priv *tavil;
8699
8700 if (!codec) {
8701 pr_err("%s: Invalid params, NULL codec\n", __func__);
8702 return NULL;
8703 }
8704 tavil = snd_soc_codec_get_drvdata(codec);
8705
8706 if (!tavil) {
8707 pr_err("%s: Invalid params, NULL tavil\n", __func__);
8708 return NULL;
8709 }
8710
8711 return tavil->mbhc;
8712}
8713EXPORT_SYMBOL(tavil_soc_get_mbhc);
8714
8715static void tavil_mclk2_reg_defaults(struct tavil_priv *tavil)
8716{
8717 int i;
8718 struct snd_soc_codec *codec = tavil->codec;
8719
8720 if (TAVIL_IS_1_0(tavil->wcd9xxx)) {
8721 /* MCLK2 configuration */
8722 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_0_defaults); i++)
8723 snd_soc_update_bits(codec,
8724 tavil_codec_mclk2_1_0_defaults[i].reg,
8725 tavil_codec_mclk2_1_0_defaults[i].mask,
8726 tavil_codec_mclk2_1_0_defaults[i].val);
8727 }
8728 if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
8729 /* MCLK2 configuration */
8730 for (i = 0; i < ARRAY_SIZE(tavil_codec_mclk2_1_1_defaults); i++)
8731 snd_soc_update_bits(codec,
8732 tavil_codec_mclk2_1_1_defaults[i].reg,
8733 tavil_codec_mclk2_1_1_defaults[i].mask,
8734 tavil_codec_mclk2_1_1_defaults[i].val);
8735 }
8736}
8737
8738static int tavil_device_down(struct wcd9xxx *wcd9xxx)
8739{
8740 struct snd_soc_codec *codec;
8741 struct tavil_priv *priv;
8742 int count;
8743
8744 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
8745 priv = snd_soc_codec_get_drvdata(codec);
8746 swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev,
8747 SWR_DEVICE_DOWN, NULL);
8748 tavil_dsd_reset(priv->dsd_config);
8749 snd_soc_card_change_online_state(codec->component.card, 0);
8750 for (count = 0; count < NUM_CODEC_DAIS; count++)
8751 priv->dai[count].bus_down_in_recovery = true;
8752 wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT);
8753 wcd_resmgr_set_sido_input_src_locked(priv->resmgr,
8754 SIDO_SOURCE_INTERNAL);
8755
8756 return 0;
8757}
8758
8759static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx)
8760{
8761 int i, ret = 0;
8762 struct wcd9xxx *control;
8763 struct snd_soc_codec *codec;
8764 struct tavil_priv *tavil;
8765 struct wcd9xxx_pdata *pdata;
8766 struct wcd_mbhc *mbhc;
8767
8768 codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv);
8769 tavil = snd_soc_codec_get_drvdata(codec);
8770 control = dev_get_drvdata(codec->dev->parent);
8771
8772 wcd9xxx_set_power_state(tavil->wcd9xxx,
8773 WCD_REGION_POWER_COLLAPSE_REMOVE,
8774 WCD9XXX_DIG_CORE_REGION_1);
8775
8776 mutex_lock(&tavil->codec_mutex);
8777 /*
8778 * Codec hardware by default comes up in SVS mode.
8779 * Initialize the svs_ref_cnt to 1 to reflect the hardware
8780 * state in the driver.
8781 */
8782 tavil->svs_ref_cnt = 1;
8783
8784 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
8785 control->slim_slave->laddr;
8786 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
8787 control->slim->laddr;
8788 tavil_init_slim_slave_cfg(codec);
8789 snd_soc_card_change_online_state(codec->component.card, 1);
8790
8791 /* Class-H Init */
8792 wcd_clsh_init(&tavil->clsh_d);
8793 /* Default HPH Mode to Class-H LOHiFi */
8794 tavil->hph_mode = CLS_H_LOHIFI;
8795
8796 for (i = 0; i < TAVIL_MAX_MICBIAS; i++)
8797 tavil->micb_ref[i] = 0;
8798
8799 for (i = 0; i < COMPANDER_MAX; i++)
8800 tavil->comp_enabled[i] = 0;
8801
8802 dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
8803 __func__, control->mclk_rate);
8804
8805 if (control->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
8806 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
8807 0x03, 0x00);
8808 else if (control->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
8809 snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
8810 0x03, 0x01);
8811 wcd_resmgr_post_ssr_v2(tavil->resmgr);
8812 tavil_update_reg_defaults(tavil);
8813 tavil_codec_init_reg(tavil);
8814 __tavil_enable_efuse_sensing(tavil);
8815 tavil_mclk2_reg_defaults(tavil);
8816
8817 __tavil_cdc_mclk_enable(tavil, true);
8818 regcache_mark_dirty(codec->component.regmap);
8819 regcache_sync(codec->component.regmap);
8820 __tavil_cdc_mclk_enable(tavil, false);
8821
8822 tavil_update_cpr_defaults(tavil);
8823
8824 pdata = dev_get_platdata(codec->dev->parent);
8825 ret = tavil_handle_pdata(tavil, pdata);
8826 if (IS_ERR_VALUE(ret))
8827 dev_err(codec->dev, "%s: invalid pdata\n", __func__);
8828
8829 /* Initialize MBHC module */
8830 mbhc = &tavil->mbhc->wcd_mbhc;
8831 ret = tavil_mbhc_post_ssr_init(tavil->mbhc, codec);
8832 if (ret) {
8833 dev_err(codec->dev, "%s: mbhc initialization failed\n",
8834 __func__);
8835 goto done;
8836 } else {
8837 tavil_mbhc_hs_detect(codec, mbhc->mbhc_cfg);
8838 }
8839
8840 /* DSD initialization */
8841 ret = tavil_dsd_post_ssr_init(tavil->dsd_config);
8842 if (ret)
8843 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
8844
8845 tavil_cleanup_irqs(tavil);
8846 ret = tavil_setup_irqs(tavil);
8847 if (ret) {
8848 dev_err(codec->dev, "%s: tavil irq setup failed %d\n",
8849 __func__, ret);
8850 goto done;
8851 }
8852
8853 tavil_set_spkr_mode(codec, tavil->swr.spkr_mode);
8854 /*
8855 * Once the codec initialization is completed, the svs vote
8856 * can be released allowing the codec to go to SVS2.
8857 */
8858 tavil_vote_svs(tavil, false);
8859 wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT);
8860
8861done:
8862 mutex_unlock(&tavil->codec_mutex);
8863 return ret;
8864}
8865
8866static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
8867{
8868 struct wcd9xxx *control;
8869 struct tavil_priv *tavil;
8870 struct wcd9xxx_pdata *pdata;
8871 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
8872 int i, ret;
8873 void *ptr = NULL;
8874
8875 control = dev_get_drvdata(codec->dev->parent);
8876
8877 dev_info(codec->dev, "%s()\n", __func__);
8878 tavil = snd_soc_codec_get_drvdata(codec);
8879 tavil->intf_type = wcd9xxx_get_intf_type();
8880
8881 control->dev_down = tavil_device_down;
8882 control->post_reset = tavil_post_reset_cb;
8883 control->ssr_priv = (void *)codec;
8884
8885 /* Resource Manager post Init */
8886 ret = wcd_resmgr_post_init(tavil->resmgr, &tavil_resmgr_cb, codec);
8887 if (ret) {
8888 dev_err(codec->dev, "%s: wcd resmgr post init failed\n",
8889 __func__);
8890 goto err;
8891 }
8892 /* Class-H Init */
8893 wcd_clsh_init(&tavil->clsh_d);
8894 /* Default HPH Mode to Class-H Low HiFi */
8895 tavil->hph_mode = CLS_H_LOHIFI;
8896
8897 tavil->fw_data = devm_kzalloc(codec->dev, sizeof(*(tavil->fw_data)),
8898 GFP_KERNEL);
8899 if (!tavil->fw_data)
8900 goto err;
8901
8902 set_bit(WCD9XXX_ANC_CAL, tavil->fw_data->cal_bit);
8903 set_bit(WCD9XXX_MBHC_CAL, tavil->fw_data->cal_bit);
8904 set_bit(WCD9XXX_MAD_CAL, tavil->fw_data->cal_bit);
8905 set_bit(WCD9XXX_VBAT_CAL, tavil->fw_data->cal_bit);
8906
8907 ret = wcd_cal_create_hwdep(tavil->fw_data,
8908 WCD9XXX_CODEC_HWDEP_NODE, codec);
8909 if (IS_ERR_VALUE(ret)) {
8910 dev_err(codec->dev, "%s hwdep failed %d\n", __func__, ret);
8911 goto err_hwdep;
8912 }
8913
8914 /* Initialize MBHC module */
8915 ret = tavil_mbhc_init(&tavil->mbhc, codec, tavil->fw_data);
8916 if (ret) {
8917 pr_err("%s: mbhc initialization failed\n", __func__);
8918 goto err_hwdep;
8919 }
8920
8921 tavil->codec = codec;
8922 for (i = 0; i < COMPANDER_MAX; i++)
8923 tavil->comp_enabled[i] = 0;
8924
8925 tavil_codec_init_reg(tavil);
8926
8927 pdata = dev_get_platdata(codec->dev->parent);
8928 ret = tavil_handle_pdata(tavil, pdata);
8929 if (IS_ERR_VALUE(ret)) {
8930 dev_err(codec->dev, "%s: bad pdata\n", __func__);
8931 goto err_hwdep;
8932 }
8933
8934 ptr = devm_kzalloc(codec->dev, (sizeof(tavil_rx_chs) +
8935 sizeof(tavil_tx_chs)), GFP_KERNEL);
8936 if (!ptr) {
8937 ret = -ENOMEM;
8938 goto err_hwdep;
8939 }
8940
8941 snd_soc_dapm_add_routes(dapm, tavil_slim_audio_map,
8942 ARRAY_SIZE(tavil_slim_audio_map));
8943 for (i = 0; i < NUM_CODEC_DAIS; i++) {
8944 INIT_LIST_HEAD(&tavil->dai[i].wcd9xxx_ch_list);
8945 init_waitqueue_head(&tavil->dai[i].dai_wait);
8946 }
8947 tavil_slimbus_slave_port_cfg.slave_dev_intfdev_la =
8948 control->slim_slave->laddr;
8949 tavil_slimbus_slave_port_cfg.slave_dev_pgd_la =
8950 control->slim->laddr;
8951 tavil_slimbus_slave_port_cfg.slave_port_mapping[0] =
8952 WCD934X_TX13;
8953 tavil_init_slim_slave_cfg(codec);
8954
8955 control->num_rx_port = WCD934X_RX_MAX;
8956 control->rx_chs = ptr;
8957 memcpy(control->rx_chs, tavil_rx_chs, sizeof(tavil_rx_chs));
8958 control->num_tx_port = WCD934X_TX_MAX;
8959 control->tx_chs = ptr + sizeof(tavil_rx_chs);
8960 memcpy(control->tx_chs, tavil_tx_chs, sizeof(tavil_tx_chs));
8961
8962 ret = tavil_setup_irqs(tavil);
8963 if (ret) {
8964 dev_err(tavil->dev, "%s: tavil irq setup failed %d\n",
8965 __func__, ret);
8966 goto err_pdata;
8967 }
8968
8969 for (i = 0; i < WCD934X_NUM_DECIMATORS; i++) {
8970 tavil->tx_hpf_work[i].tavil = tavil;
8971 tavil->tx_hpf_work[i].decimator = i;
8972 INIT_DELAYED_WORK(&tavil->tx_hpf_work[i].dwork,
8973 tavil_tx_hpf_corner_freq_callback);
8974
8975 tavil->tx_mute_dwork[i].tavil = tavil;
8976 tavil->tx_mute_dwork[i].decimator = i;
8977 INIT_DELAYED_WORK(&tavil->tx_mute_dwork[i].dwork,
8978 tavil_tx_mute_update_callback);
8979 }
8980
8981 tavil->spk_anc_dwork.tavil = tavil;
8982 INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork,
8983 tavil_spk_anc_update_callback);
8984
8985 tavil_mclk2_reg_defaults(tavil);
8986
8987 /* DSD initialization */
8988 tavil->dsd_config = tavil_dsd_init(codec);
8989 if (IS_ERR_OR_NULL(tavil->dsd_config))
8990 dev_dbg(tavil->dev, "%s: DSD init failed\n", __func__);
8991
8992 mutex_lock(&tavil->codec_mutex);
8993 snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
8994 snd_soc_dapm_disable_pin(dapm, "ANC EAR");
8995 snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA");
8996 mutex_unlock(&tavil->codec_mutex);
8997
8998 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
8999 snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
9000 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Playback");
9001 snd_soc_dapm_ignore_suspend(dapm, "AIF2 Capture");
9002 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback");
9003 snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture");
9004 snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback");
9005 snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
9006
9007 snd_soc_dapm_sync(dapm);
9008
9009 tavil_wdsp_initialize(codec);
9010
9011 /*
9012 * Once the codec initialization is completed, the svs vote
9013 * can be released allowing the codec to go to SVS2.
9014 */
9015 tavil_vote_svs(tavil, false);
9016
9017 return ret;
9018
9019err_pdata:
9020 devm_kfree(codec->dev, ptr);
9021 control->rx_chs = NULL;
9022 control->tx_chs = NULL;
9023err_hwdep:
9024 devm_kfree(codec->dev, tavil->fw_data);
9025 tavil->fw_data = NULL;
9026err:
9027 return ret;
9028}
9029
9030static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
9031{
9032 struct wcd9xxx *control;
9033 struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
9034
9035 control = dev_get_drvdata(codec->dev->parent);
9036 devm_kfree(codec->dev, control->rx_chs);
9037 control->rx_chs = NULL;
9038 control->tx_chs = NULL;
9039 tavil_cleanup_irqs(tavil);
9040
9041 if (tavil->wdsp_cntl)
9042 wcd_dsp_cntl_deinit(&tavil->wdsp_cntl);
9043
9044 /* Deinitialize MBHC module */
9045 tavil_mbhc_deinit(codec);
9046 tavil->mbhc = NULL;
9047
9048 return 0;
9049}
9050
9051static struct regmap *tavil_get_regmap(struct device *dev)
9052{
9053 struct wcd9xxx *control = dev_get_drvdata(dev->parent);
9054
9055 return control->regmap;
9056}
9057
9058static struct snd_soc_codec_driver soc_codec_dev_tavil = {
9059 .probe = tavil_soc_codec_probe,
9060 .remove = tavil_soc_codec_remove,
9061 .controls = tavil_snd_controls,
9062 .num_controls = ARRAY_SIZE(tavil_snd_controls),
9063 .dapm_widgets = tavil_dapm_widgets,
9064 .num_dapm_widgets = ARRAY_SIZE(tavil_dapm_widgets),
9065 .dapm_routes = tavil_audio_map,
9066 .num_dapm_routes = ARRAY_SIZE(tavil_audio_map),
9067 .get_regmap = tavil_get_regmap,
9068};
9069
9070#ifdef CONFIG_PM
9071static int tavil_suspend(struct device *dev)
9072{
9073 struct platform_device *pdev = to_platform_device(dev);
9074 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9075
9076 if (!tavil) {
9077 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9078 return -EINVAL;
9079 }
9080 dev_dbg(dev, "%s: system suspend\n", __func__);
9081 if (delayed_work_pending(&tavil->power_gate_work) &&
9082 cancel_delayed_work_sync(&tavil->power_gate_work))
9083 tavil_codec_power_gate_digital_core(tavil);
9084 return 0;
9085}
9086
9087static int tavil_resume(struct device *dev)
9088{
9089 struct platform_device *pdev = to_platform_device(dev);
9090 struct tavil_priv *tavil = platform_get_drvdata(pdev);
9091
9092 if (!tavil) {
9093 dev_err(dev, "%s: tavil private data is NULL\n", __func__);
9094 return -EINVAL;
9095 }
9096 dev_dbg(dev, "%s: system resume\n", __func__);
9097 return 0;
9098}
9099
9100static const struct dev_pm_ops tavil_pm_ops = {
9101 .suspend = tavil_suspend,
9102 .resume = tavil_resume,
9103};
9104#endif
9105
9106static int tavil_swrm_read(void *handle, int reg)
9107{
9108 struct tavil_priv *tavil;
9109 struct wcd9xxx *wcd9xxx;
9110 unsigned short swr_rd_addr_base;
9111 unsigned short swr_rd_data_base;
9112 int val, ret;
9113
9114 if (!handle) {
9115 pr_err("%s: NULL handle\n", __func__);
9116 return -EINVAL;
9117 }
9118 tavil = (struct tavil_priv *)handle;
9119 wcd9xxx = tavil->wcd9xxx;
9120
9121 dev_dbg(tavil->dev, "%s: Reading soundwire register, 0x%x\n",
9122 __func__, reg);
9123 swr_rd_addr_base = WCD934X_SWR_AHB_BRIDGE_RD_ADDR_0;
9124 swr_rd_data_base = WCD934X_SWR_AHB_BRIDGE_RD_DATA_0;
9125
9126 mutex_lock(&tavil->swr.read_mutex);
9127 ret = regmap_bulk_write(wcd9xxx->regmap, swr_rd_addr_base,
9128 (u8 *)&reg, 4);
9129 if (ret < 0) {
9130 dev_err(tavil->dev, "%s: RD Addr Failure\n", __func__);
9131 goto done;
9132 }
9133 ret = regmap_bulk_read(wcd9xxx->regmap, swr_rd_data_base,
9134 (u8 *)&val, 4);
9135 if (ret < 0) {
9136 dev_err(tavil->dev, "%s: RD Data Failure\n", __func__);
9137 goto done;
9138 }
9139 ret = val;
9140done:
9141 mutex_unlock(&tavil->swr.read_mutex);
9142
9143 return ret;
9144}
9145
9146static int tavil_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
9147{
9148 struct tavil_priv *tavil;
9149 struct wcd9xxx *wcd9xxx;
9150 struct wcd9xxx_reg_val *bulk_reg;
9151 unsigned short swr_wr_addr_base;
9152 unsigned short swr_wr_data_base;
9153 int i, j, ret;
9154
9155 if (!handle || !reg || !val) {
9156 pr_err("%s: NULL parameter\n", __func__);
9157 return -EINVAL;
9158 }
9159 if (len <= 0) {
9160 pr_err("%s: Invalid size: %zu\n", __func__, len);
9161 return -EINVAL;
9162 }
9163 tavil = (struct tavil_priv *)handle;
9164 wcd9xxx = tavil->wcd9xxx;
9165
9166 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9167 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9168
9169 bulk_reg = kzalloc((2 * len * sizeof(struct wcd9xxx_reg_val)),
9170 GFP_KERNEL);
9171 if (!bulk_reg)
9172 return -ENOMEM;
9173
9174 for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
9175 bulk_reg[i].reg = swr_wr_data_base;
9176 bulk_reg[i].buf = (u8 *)(&val[j]);
9177 bulk_reg[i].bytes = 4;
9178 bulk_reg[i+1].reg = swr_wr_addr_base;
9179 bulk_reg[i+1].buf = (u8 *)(&reg[j]);
9180 bulk_reg[i+1].bytes = 4;
9181 }
9182
9183 mutex_lock(&tavil->swr.write_mutex);
9184 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg,
9185 (len * 2), false);
9186 if (ret) {
9187 dev_err(tavil->dev, "%s: swrm bulk write failed, ret: %d\n",
9188 __func__, ret);
9189 }
9190 mutex_unlock(&tavil->swr.write_mutex);
9191
9192 kfree(bulk_reg);
9193 return ret;
9194}
9195
9196static int tavil_swrm_write(void *handle, int reg, int val)
9197{
9198 struct tavil_priv *tavil;
9199 struct wcd9xxx *wcd9xxx;
9200 unsigned short swr_wr_addr_base;
9201 unsigned short swr_wr_data_base;
9202 struct wcd9xxx_reg_val bulk_reg[2];
9203 int ret;
9204
9205 if (!handle) {
9206 pr_err("%s: NULL handle\n", __func__);
9207 return -EINVAL;
9208 }
9209 tavil = (struct tavil_priv *)handle;
9210 wcd9xxx = tavil->wcd9xxx;
9211
9212 swr_wr_addr_base = WCD934X_SWR_AHB_BRIDGE_WR_ADDR_0;
9213 swr_wr_data_base = WCD934X_SWR_AHB_BRIDGE_WR_DATA_0;
9214
9215 /* First Write the Data to register */
9216 bulk_reg[0].reg = swr_wr_data_base;
9217 bulk_reg[0].buf = (u8 *)(&val);
9218 bulk_reg[0].bytes = 4;
9219 bulk_reg[1].reg = swr_wr_addr_base;
9220 bulk_reg[1].buf = (u8 *)(&reg);
9221 bulk_reg[1].bytes = 4;
9222
9223 mutex_lock(&tavil->swr.write_mutex);
9224 ret = wcd9xxx_slim_bulk_write(wcd9xxx, bulk_reg, 2, false);
9225 if (ret < 0)
9226 dev_err(tavil->dev, "%s: WR Data Failure\n", __func__);
9227 mutex_unlock(&tavil->swr.write_mutex);
9228
9229 return ret;
9230}
9231
9232static int tavil_swrm_clock(void *handle, bool enable)
9233{
9234 struct tavil_priv *tavil;
9235
9236 if (!handle) {
9237 pr_err("%s: NULL handle\n", __func__);
9238 return -EINVAL;
9239 }
9240 tavil = (struct tavil_priv *)handle;
9241
9242 mutex_lock(&tavil->swr.clk_mutex);
9243 dev_dbg(tavil->dev, "%s: swrm clock %s\n",
9244 __func__, (enable?"enable" : "disable"));
9245 if (enable) {
9246 tavil->swr.clk_users++;
9247 if (tavil->swr.clk_users == 1) {
9248 regmap_update_bits(tavil->wcd9xxx->regmap,
9249 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9250 0x10, 0x00);
9251 __tavil_cdc_mclk_enable(tavil, true);
9252 regmap_update_bits(tavil->wcd9xxx->regmap,
9253 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9254 0x01, 0x01);
9255 }
9256 } else {
9257 tavil->swr.clk_users--;
9258 if (tavil->swr.clk_users == 0) {
9259 regmap_update_bits(tavil->wcd9xxx->regmap,
9260 WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
9261 0x01, 0x00);
9262 __tavil_cdc_mclk_enable(tavil, false);
9263 regmap_update_bits(tavil->wcd9xxx->regmap,
9264 WCD934X_TEST_DEBUG_NPL_DLY_TEST_1,
9265 0x10, 0x10);
9266 }
9267 }
9268 dev_dbg(tavil->dev, "%s: swrm clock users %d\n",
9269 __func__, tavil->swr.clk_users);
9270 mutex_unlock(&tavil->swr.clk_mutex);
9271
9272 return 0;
9273}
9274
9275static int tavil_swrm_handle_irq(void *handle,
9276 irqreturn_t (*swrm_irq_handler)(int irq,
9277 void *data),
9278 void *swrm_handle,
9279 int action)
9280{
9281 struct tavil_priv *tavil;
9282 int ret = 0;
9283 struct wcd9xxx *wcd9xxx;
9284
9285 if (!handle) {
9286 pr_err("%s: NULL handle\n", __func__);
9287 return -EINVAL;
9288 }
9289 tavil = (struct tavil_priv *) handle;
9290 wcd9xxx = tavil->wcd9xxx;
9291
9292 if (action) {
9293 ret = wcd9xxx_request_irq(&wcd9xxx->core_res,
9294 WCD934X_IRQ_SOUNDWIRE,
9295 swrm_irq_handler,
9296 "Tavil SWR Master", swrm_handle);
9297 if (ret)
9298 dev_err(tavil->dev, "%s: Failed to request irq %d\n",
9299 __func__, WCD934X_IRQ_SOUNDWIRE);
9300 } else
9301 wcd9xxx_free_irq(&wcd9xxx->core_res, WCD934X_IRQ_SOUNDWIRE,
9302 swrm_handle);
9303
9304 return ret;
9305}
9306
9307static void tavil_codec_add_spi_device(struct tavil_priv *tavil,
9308 struct device_node *node)
9309{
9310 struct spi_master *master;
9311 struct spi_device *spi;
9312 u32 prop_value;
9313 int rc;
9314
9315 /* Read the master bus num from DT node */
9316 rc = of_property_read_u32(node, "qcom,master-bus-num",
9317 &prop_value);
9318 if (IS_ERR_VALUE(rc)) {
9319 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9320 __func__, "qcom,master-bus-num", node->full_name);
9321 goto done;
9322 }
9323
9324 /* Get the reference to SPI master */
9325 master = spi_busnum_to_master(prop_value);
9326 if (!master) {
9327 dev_err(tavil->dev, "%s: Invalid spi_master for bus_num %u\n",
9328 __func__, prop_value);
9329 goto done;
9330 }
9331
9332 /* Allocate the spi device */
9333 spi = spi_alloc_device(master);
9334 if (!spi) {
9335 dev_err(tavil->dev, "%s: spi_alloc_device failed\n",
9336 __func__);
9337 goto err_spi_alloc_dev;
9338 }
9339
9340 /* Initialize device properties */
9341 if (of_modalias_node(node, spi->modalias,
9342 sizeof(spi->modalias)) < 0) {
9343 dev_err(tavil->dev, "%s: cannot find modalias for %s\n",
9344 __func__, node->full_name);
9345 goto err_dt_parse;
9346 }
9347
9348 rc = of_property_read_u32(node, "qcom,chip-select",
9349 &prop_value);
9350 if (IS_ERR_VALUE(rc)) {
9351 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9352 __func__, "qcom,chip-select", node->full_name);
9353 goto err_dt_parse;
9354 }
9355 spi->chip_select = prop_value;
9356
9357 rc = of_property_read_u32(node, "qcom,max-frequency",
9358 &prop_value);
9359 if (IS_ERR_VALUE(rc)) {
9360 dev_err(tavil->dev, "%s: prop %s not found in node %s",
9361 __func__, "qcom,max-frequency", node->full_name);
9362 goto err_dt_parse;
9363 }
9364 spi->max_speed_hz = prop_value;
9365
9366 spi->dev.of_node = node;
9367
9368 rc = spi_add_device(spi);
9369 if (IS_ERR_VALUE(rc)) {
9370 dev_err(tavil->dev, "%s: spi_add_device failed\n", __func__);
9371 goto err_dt_parse;
9372 }
9373
9374 /* Put the reference to SPI master */
9375 put_device(&master->dev);
9376
9377 return;
9378
9379err_dt_parse:
9380 spi_dev_put(spi);
9381
9382err_spi_alloc_dev:
9383 /* Put the reference to SPI master */
9384 put_device(&master->dev);
9385done:
9386 return;
9387}
9388
9389static void tavil_add_child_devices(struct work_struct *work)
9390{
9391 struct tavil_priv *tavil;
9392 struct platform_device *pdev;
9393 struct device_node *node;
9394 struct wcd9xxx *wcd9xxx;
9395 struct tavil_swr_ctrl_data *swr_ctrl_data = NULL, *temp;
9396 int ret, ctrl_num = 0;
9397 struct wcd_swr_ctrl_platform_data *platdata;
9398 char plat_dev_name[WCD934X_STRING_LEN];
9399
9400 tavil = container_of(work, struct tavil_priv,
9401 tavil_add_child_devices_work);
9402 if (!tavil) {
9403 pr_err("%s: Memory for WCD934X does not exist\n",
9404 __func__);
9405 return;
9406 }
9407 wcd9xxx = tavil->wcd9xxx;
9408 if (!wcd9xxx) {
9409 pr_err("%s: Memory for WCD9XXX does not exist\n",
9410 __func__);
9411 return;
9412 }
9413 if (!wcd9xxx->dev->of_node) {
9414 dev_err(wcd9xxx->dev, "%s: DT node for wcd9xxx does not exist\n",
9415 __func__);
9416 return;
9417 }
9418
9419 platdata = &tavil->swr.plat_data;
9420
9421 for_each_child_of_node(wcd9xxx->dev->of_node, node) {
9422
9423 /* Parse and add the SPI device node */
9424 if (!strcmp(node->name, "wcd_spi")) {
9425 tavil_codec_add_spi_device(tavil, node);
9426 continue;
9427 }
9428
9429 /* Parse other child device nodes and add platform device */
9430 if (!strcmp(node->name, "swr_master"))
9431 strlcpy(plat_dev_name, "tavil_swr_ctrl",
9432 (WCD934X_STRING_LEN - 1));
9433 else if (strnstr(node->name, "msm_cdc_pinctrl",
9434 strlen("msm_cdc_pinctrl")) != NULL)
9435 strlcpy(plat_dev_name, node->name,
9436 (WCD934X_STRING_LEN - 1));
9437 else
9438 continue;
9439
9440 pdev = platform_device_alloc(plat_dev_name, -1);
9441 if (!pdev) {
9442 dev_err(wcd9xxx->dev, "%s: pdev memory alloc failed\n",
9443 __func__);
9444 ret = -ENOMEM;
9445 goto err_mem;
9446 }
9447 pdev->dev.parent = tavil->dev;
9448 pdev->dev.of_node = node;
9449
9450 if (strcmp(node->name, "swr_master") == 0) {
9451 ret = platform_device_add_data(pdev, platdata,
9452 sizeof(*platdata));
9453 if (ret) {
9454 dev_err(&pdev->dev,
9455 "%s: cannot add plat data ctrl:%d\n",
9456 __func__, ctrl_num);
9457 goto err_pdev_add;
9458 }
9459 }
9460
9461 ret = platform_device_add(pdev);
9462 if (ret) {
9463 dev_err(&pdev->dev,
9464 "%s: Cannot add platform device\n",
9465 __func__);
9466 goto err_pdev_add;
9467 }
9468
9469 if (strcmp(node->name, "swr_master") == 0) {
9470 temp = krealloc(swr_ctrl_data,
9471 (ctrl_num + 1) * sizeof(
9472 struct tavil_swr_ctrl_data),
9473 GFP_KERNEL);
9474 if (!temp) {
9475 dev_err(wcd9xxx->dev, "out of memory\n");
9476 ret = -ENOMEM;
9477 goto err_pdev_add;
9478 }
9479 swr_ctrl_data = temp;
9480 swr_ctrl_data[ctrl_num].swr_pdev = pdev;
9481 ctrl_num++;
9482 dev_dbg(&pdev->dev,
9483 "%s: Added soundwire ctrl device(s)\n",
9484 __func__);
9485 tavil->swr.ctrl_data = swr_ctrl_data;
9486 }
9487 }
9488
9489 return;
9490
9491err_pdev_add:
9492 platform_device_put(pdev);
9493err_mem:
9494 return;
9495}
9496
9497static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
9498{
9499 int val, rc;
9500
9501 __tavil_cdc_mclk_enable(tavil, true);
9502
9503 regmap_update_bits(tavil->wcd9xxx->regmap,
9504 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x1E, 0x10);
9505 regmap_update_bits(tavil->wcd9xxx->regmap,
9506 WCD934X_CHIP_TIER_CTRL_EFUSE_CTL, 0x01, 0x01);
9507
9508 /*
9509 * 5ms sleep required after enabling efuse control
9510 * before checking the status.
9511 */
9512 usleep_range(5000, 5500);
9513 rc = regmap_read(tavil->wcd9xxx->regmap,
9514 WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val);
9515 if (rc || (!(val & 0x01)))
9516 WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
9517 __func__, val, rc);
9518
9519 __tavil_cdc_mclk_enable(tavil, false);
9520
9521 return rc;
9522}
9523
9524static void ___tavil_get_codec_fine_version(struct tavil_priv *tavil)
9525{
9526 int val1, val2, version;
9527 struct regmap *regmap;
9528 u16 id_minor;
9529 u32 version_mask = 0;
9530
9531 regmap = tavil->wcd9xxx->regmap;
9532 version = tavil->wcd9xxx->version;
9533 id_minor = tavil->wcd9xxx->codec_type->id_minor;
9534
9535 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14, &val1);
9536 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15, &val2);
9537
9538 dev_dbg(tavil->dev, "%s: chip version :0x%x 0x:%x\n",
9539 __func__, val1, val2);
9540
9541 version_mask |= (!!((u8)val1 & 0x80)) << DSD_DISABLED_MASK;
9542 version_mask |= (!!((u8)val2 & 0x01)) << SLNQ_DISABLED_MASK;
9543
9544 switch (version_mask) {
9545 case DSD_DISABLED | SLNQ_DISABLED:
9546 if (id_minor == cpu_to_le16(0))
9547 version = TAVIL_VERSION_WCD9340_1_0;
9548 else if (id_minor == cpu_to_le16(0x01))
9549 version = TAVIL_VERSION_WCD9340_1_1;
9550 break;
9551 case SLNQ_DISABLED:
9552 if (id_minor == cpu_to_le16(0))
9553 version = TAVIL_VERSION_WCD9341_1_0;
9554 else if (id_minor == cpu_to_le16(0x01))
9555 version = TAVIL_VERSION_WCD9341_1_1;
9556 break;
9557 }
9558
9559 tavil->wcd9xxx->version = version;
9560 tavil->wcd9xxx->codec_type->version = version;
9561}
9562
9563/*
9564 * tavil_get_wcd_dsp_cntl: Get the reference to wcd_dsp_cntl
9565 * @dev: Device pointer for codec device
9566 *
9567 * This API gets the reference to codec's struct wcd_dsp_cntl
9568 */
9569struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev)
9570{
9571 struct platform_device *pdev;
9572 struct tavil_priv *tavil;
9573
9574 if (!dev) {
9575 pr_err("%s: Invalid device\n", __func__);
9576 return NULL;
9577 }
9578
9579 pdev = to_platform_device(dev);
9580 tavil = platform_get_drvdata(pdev);
9581
9582 return tavil->wdsp_cntl;
9583}
9584EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl);
9585
9586static int tavil_probe(struct platform_device *pdev)
9587{
9588 int ret = 0;
9589 struct tavil_priv *tavil;
9590 struct clk *wcd_ext_clk;
9591 struct wcd9xxx_resmgr_v2 *resmgr;
9592 struct wcd9xxx_power_region *cdc_pwr;
9593
9594 tavil = devm_kzalloc(&pdev->dev, sizeof(struct tavil_priv),
9595 GFP_KERNEL);
9596 if (!tavil)
9597 return -ENOMEM;
9598
9599 platform_set_drvdata(pdev, tavil);
9600
9601 tavil->wcd9xxx = dev_get_drvdata(pdev->dev.parent);
9602 tavil->dev = &pdev->dev;
9603 INIT_DELAYED_WORK(&tavil->power_gate_work, tavil_codec_power_gate_work);
9604 mutex_init(&tavil->power_lock);
9605 INIT_WORK(&tavil->tavil_add_child_devices_work,
9606 tavil_add_child_devices);
9607 mutex_init(&tavil->micb_lock);
9608 mutex_init(&tavil->swr.read_mutex);
9609 mutex_init(&tavil->swr.write_mutex);
9610 mutex_init(&tavil->swr.clk_mutex);
9611 mutex_init(&tavil->codec_mutex);
9612 mutex_init(&tavil->svs_mutex);
9613
9614 /*
9615 * Codec hardware by default comes up in SVS mode.
9616 * Initialize the svs_ref_cnt to 1 to reflect the hardware
9617 * state in the driver.
9618 */
9619 tavil->svs_ref_cnt = 1;
9620
9621 cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
9622 GFP_KERNEL);
9623 if (!cdc_pwr) {
9624 ret = -ENOMEM;
9625 goto err_resmgr;
9626 }
9627 tavil->wcd9xxx->wcd9xxx_pwr[WCD9XXX_DIG_CORE_REGION_1] = cdc_pwr;
9628 cdc_pwr->pwr_collapse_reg_min = WCD934X_DIG_CORE_REG_MIN;
9629 cdc_pwr->pwr_collapse_reg_max = WCD934X_DIG_CORE_REG_MAX;
9630 wcd9xxx_set_power_state(tavil->wcd9xxx,
9631 WCD_REGION_POWER_COLLAPSE_REMOVE,
9632 WCD9XXX_DIG_CORE_REGION_1);
9633 /*
9634 * Init resource manager so that if child nodes such as SoundWire
9635 * requests for clock, resource manager can honor the request
9636 */
9637 resmgr = wcd_resmgr_init(&tavil->wcd9xxx->core_res, NULL);
9638 if (IS_ERR(resmgr)) {
9639 ret = PTR_ERR(resmgr);
9640 dev_err(&pdev->dev, "%s: Failed to initialize wcd resmgr\n",
9641 __func__);
9642 goto err_resmgr;
9643 }
9644 tavil->resmgr = resmgr;
9645 tavil->swr.plat_data.handle = (void *) tavil;
9646 tavil->swr.plat_data.read = tavil_swrm_read;
9647 tavil->swr.plat_data.write = tavil_swrm_write;
9648 tavil->swr.plat_data.bulk_write = tavil_swrm_bulk_write;
9649 tavil->swr.plat_data.clk = tavil_swrm_clock;
9650 tavil->swr.plat_data.handle_irq = tavil_swrm_handle_irq;
9651 tavil->swr.spkr_gain_offset = WCD934X_RX_GAIN_OFFSET_0_DB;
9652
9653 /* Register for Clock */
9654 wcd_ext_clk = clk_get(tavil->wcd9xxx->dev, "wcd_clk");
9655 if (IS_ERR(wcd_ext_clk)) {
9656 dev_err(tavil->wcd9xxx->dev, "%s: clk get %s failed\n",
9657 __func__, "wcd_ext_clk");
9658 goto err_clk;
9659 }
9660 tavil->wcd_ext_clk = wcd_ext_clk;
9661 set_bit(AUDIO_NOMINAL, &tavil->status_mask);
9662 /* Update codec register default values */
9663 dev_dbg(&pdev->dev, "%s: MCLK Rate = %x\n", __func__,
9664 tavil->wcd9xxx->mclk_rate);
9665 if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_12P288MHZ)
9666 regmap_update_bits(tavil->wcd9xxx->regmap,
9667 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9668 0x03, 0x00);
9669 else if (tavil->wcd9xxx->mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
9670 regmap_update_bits(tavil->wcd9xxx->regmap,
9671 WCD934X_CODEC_RPM_CLK_MCLK_CFG,
9672 0x03, 0x01);
9673 tavil_update_reg_defaults(tavil);
9674 __tavil_enable_efuse_sensing(tavil);
9675 ___tavil_get_codec_fine_version(tavil);
9676 tavil_update_cpr_defaults(tavil);
9677
9678 /* Register with soc framework */
9679 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tavil,
9680 tavil_dai, ARRAY_SIZE(tavil_dai));
9681 if (ret) {
9682 dev_err(&pdev->dev, "%s: Codec registration failed\n",
9683 __func__);
9684 goto err_cdc_reg;
9685 }
9686 schedule_work(&tavil->tavil_add_child_devices_work);
9687
9688 return ret;
9689
9690err_cdc_reg:
9691 clk_put(tavil->wcd_ext_clk);
9692err_clk:
9693 wcd_resmgr_remove(tavil->resmgr);
9694err_resmgr:
9695 mutex_destroy(&tavil->micb_lock);
9696 mutex_destroy(&tavil->svs_mutex);
9697 mutex_destroy(&tavil->codec_mutex);
9698 mutex_destroy(&tavil->swr.read_mutex);
9699 mutex_destroy(&tavil->swr.write_mutex);
9700 mutex_destroy(&tavil->swr.clk_mutex);
9701 devm_kfree(&pdev->dev, tavil);
9702
9703 return ret;
9704}
9705
9706static int tavil_remove(struct platform_device *pdev)
9707{
9708 struct tavil_priv *tavil;
9709
9710 tavil = platform_get_drvdata(pdev);
9711 if (!tavil)
9712 return -EINVAL;
9713
9714 mutex_destroy(&tavil->micb_lock);
9715 mutex_destroy(&tavil->svs_mutex);
9716 mutex_destroy(&tavil->codec_mutex);
9717 mutex_destroy(&tavil->swr.read_mutex);
9718 mutex_destroy(&tavil->swr.write_mutex);
9719 mutex_destroy(&tavil->swr.clk_mutex);
9720
9721 snd_soc_unregister_codec(&pdev->dev);
9722 clk_put(tavil->wcd_ext_clk);
9723 wcd_resmgr_remove(tavil->resmgr);
9724 if (tavil->dsd_config) {
9725 tavil_dsd_deinit(tavil->dsd_config);
9726 tavil->dsd_config = NULL;
9727 }
9728 devm_kfree(&pdev->dev, tavil);
9729 return 0;
9730}
9731
9732static struct platform_driver tavil_codec_driver = {
9733 .probe = tavil_probe,
9734 .remove = tavil_remove,
9735 .driver = {
9736 .name = "tavil_codec",
9737 .owner = THIS_MODULE,
9738#ifdef CONFIG_PM
9739 .pm = &tavil_pm_ops,
9740#endif
9741 },
9742};
9743
9744module_platform_driver(tavil_codec_driver);
9745
9746MODULE_DESCRIPTION("Tavil Codec driver");
9747MODULE_LICENSE("GPL v2");