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