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