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