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