162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/module.h>
562306a36Sopenharmony_ci#include <linux/slab.h>
662306a36Sopenharmony_ci#include <linux/platform_device.h>
762306a36Sopenharmony_ci#include <linux/device.h>
862306a36Sopenharmony_ci#include <linux/delay.h>
962306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1262306a36Sopenharmony_ci#include <linux/component.h>
1362306a36Sopenharmony_ci#include <sound/tlv.h>
1462306a36Sopenharmony_ci#include <linux/of_gpio.h>
1562306a36Sopenharmony_ci#include <linux/of.h>
1662306a36Sopenharmony_ci#include <sound/jack.h>
1762306a36Sopenharmony_ci#include <sound/pcm.h>
1862306a36Sopenharmony_ci#include <sound/pcm_params.h>
1962306a36Sopenharmony_ci#include <linux/regmap.h>
2062306a36Sopenharmony_ci#include <sound/soc.h>
2162306a36Sopenharmony_ci#include <sound/soc-dapm.h>
2262306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "wcd-clsh-v2.h"
2562306a36Sopenharmony_ci#include "wcd-mbhc-v2.h"
2662306a36Sopenharmony_ci#include "wcd938x.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define WCD938X_MAX_MICBIAS		(4)
2962306a36Sopenharmony_ci#define WCD938X_MAX_SUPPLY		(4)
3062306a36Sopenharmony_ci#define WCD938X_MBHC_MAX_BUTTONS	(8)
3162306a36Sopenharmony_ci#define TX_ADC_MAX			(4)
3262306a36Sopenharmony_ci#define WCD938X_TX_MAX_SWR_PORTS	(5)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define WCD938X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
3562306a36Sopenharmony_ci			    SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
3662306a36Sopenharmony_ci			    SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
3762306a36Sopenharmony_ci/* Fractional Rates */
3862306a36Sopenharmony_ci#define WCD938X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
3962306a36Sopenharmony_ci				 SNDRV_PCM_RATE_176400)
4062306a36Sopenharmony_ci#define WCD938X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
4162306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S24_LE)
4262306a36Sopenharmony_ci/* Convert from vout ctl to micbias voltage in mV */
4362306a36Sopenharmony_ci#define  WCD_VOUT_CTL_TO_MICB(v)	(1000 + v * 50)
4462306a36Sopenharmony_ci#define SWR_CLK_RATE_0P6MHZ		(600000)
4562306a36Sopenharmony_ci#define SWR_CLK_RATE_1P2MHZ		(1200000)
4662306a36Sopenharmony_ci#define SWR_CLK_RATE_2P4MHZ		(2400000)
4762306a36Sopenharmony_ci#define SWR_CLK_RATE_4P8MHZ		(4800000)
4862306a36Sopenharmony_ci#define SWR_CLK_RATE_9P6MHZ		(9600000)
4962306a36Sopenharmony_ci#define SWR_CLK_RATE_11P2896MHZ		(1128960)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define WCD938X_DRV_NAME "wcd938x_codec"
5262306a36Sopenharmony_ci#define WCD938X_VERSION_1_0		(1)
5362306a36Sopenharmony_ci#define EAR_RX_PATH_AUX			(1)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define ADC_MODE_VAL_HIFI		0x01
5662306a36Sopenharmony_ci#define ADC_MODE_VAL_LO_HIF		0x02
5762306a36Sopenharmony_ci#define ADC_MODE_VAL_NORMAL		0x03
5862306a36Sopenharmony_ci#define ADC_MODE_VAL_LP			0x05
5962306a36Sopenharmony_ci#define ADC_MODE_VAL_ULP1		0x09
6062306a36Sopenharmony_ci#define ADC_MODE_VAL_ULP2		0x0B
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* Z value defined in milliohm */
6362306a36Sopenharmony_ci#define WCD938X_ZDET_VAL_32             (32000)
6462306a36Sopenharmony_ci#define WCD938X_ZDET_VAL_400            (400000)
6562306a36Sopenharmony_ci#define WCD938X_ZDET_VAL_1200           (1200000)
6662306a36Sopenharmony_ci#define WCD938X_ZDET_VAL_100K           (100000000)
6762306a36Sopenharmony_ci/* Z floating defined in ohms */
6862306a36Sopenharmony_ci#define WCD938X_ZDET_FLOATING_IMPEDANCE	(0x0FFFFFFE)
6962306a36Sopenharmony_ci#define WCD938X_ZDET_NUM_MEASUREMENTS   (900)
7062306a36Sopenharmony_ci#define WCD938X_MBHC_GET_C1(c)          ((c & 0xC000) >> 14)
7162306a36Sopenharmony_ci#define WCD938X_MBHC_GET_X1(x)          (x & 0x3FFF)
7262306a36Sopenharmony_ci/* Z value compared in milliOhm */
7362306a36Sopenharmony_ci#define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000))
7462306a36Sopenharmony_ci#define WCD938X_MBHC_ZDET_CONST         (86 * 16384)
7562306a36Sopenharmony_ci#define WCD938X_MBHC_MOISTURE_RREF      R_24_KOHM
7662306a36Sopenharmony_ci#define WCD_MBHC_HS_V_MAX           1600
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \
7962306a36Sopenharmony_ci{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
8062306a36Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
8162306a36Sopenharmony_ci		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
8262306a36Sopenharmony_ci	.tlv.p = (tlv_array), \
8362306a36Sopenharmony_ci	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
8462306a36Sopenharmony_ci	.put = wcd938x_ear_pa_put_gain, \
8562306a36Sopenharmony_ci	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cienum {
8862306a36Sopenharmony_ci	WCD9380 = 0,
8962306a36Sopenharmony_ci	WCD9385 = 5,
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cienum {
9362306a36Sopenharmony_ci	TX_HDR12 = 0,
9462306a36Sopenharmony_ci	TX_HDR34,
9562306a36Sopenharmony_ci	TX_HDR_MAX,
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cienum {
9962306a36Sopenharmony_ci	WCD_RX1,
10062306a36Sopenharmony_ci	WCD_RX2,
10162306a36Sopenharmony_ci	WCD_RX3
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cienum {
10562306a36Sopenharmony_ci	/* INTR_CTRL_INT_MASK_0 */
10662306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0,
10762306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET,
10862306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,
10962306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,
11062306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_SW_DET,
11162306a36Sopenharmony_ci	WCD938X_IRQ_HPHR_OCP_INT,
11262306a36Sopenharmony_ci	WCD938X_IRQ_HPHR_CNP_INT,
11362306a36Sopenharmony_ci	WCD938X_IRQ_HPHL_OCP_INT,
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/* INTR_CTRL_INT_MASK_1 */
11662306a36Sopenharmony_ci	WCD938X_IRQ_HPHL_CNP_INT,
11762306a36Sopenharmony_ci	WCD938X_IRQ_EAR_CNP_INT,
11862306a36Sopenharmony_ci	WCD938X_IRQ_EAR_SCD_INT,
11962306a36Sopenharmony_ci	WCD938X_IRQ_AUX_CNP_INT,
12062306a36Sopenharmony_ci	WCD938X_IRQ_AUX_SCD_INT,
12162306a36Sopenharmony_ci	WCD938X_IRQ_HPHL_PDM_WD_INT,
12262306a36Sopenharmony_ci	WCD938X_IRQ_HPHR_PDM_WD_INT,
12362306a36Sopenharmony_ci	WCD938X_IRQ_AUX_PDM_WD_INT,
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* INTR_CTRL_INT_MASK_2 */
12662306a36Sopenharmony_ci	WCD938X_IRQ_LDORT_SCD_INT,
12762306a36Sopenharmony_ci	WCD938X_IRQ_MBHC_MOISTURE_INT,
12862306a36Sopenharmony_ci	WCD938X_IRQ_HPHL_SURGE_DET_INT,
12962306a36Sopenharmony_ci	WCD938X_IRQ_HPHR_SURGE_DET_INT,
13062306a36Sopenharmony_ci	WCD938X_NUM_IRQS,
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cienum {
13462306a36Sopenharmony_ci	WCD_ADC1 = 0,
13562306a36Sopenharmony_ci	WCD_ADC2,
13662306a36Sopenharmony_ci	WCD_ADC3,
13762306a36Sopenharmony_ci	WCD_ADC4,
13862306a36Sopenharmony_ci	ALLOW_BUCK_DISABLE,
13962306a36Sopenharmony_ci	HPH_COMP_DELAY,
14062306a36Sopenharmony_ci	HPH_PA_DELAY,
14162306a36Sopenharmony_ci	AMIC2_BCS_ENABLE,
14262306a36Sopenharmony_ci	WCD_SUPPLIES_LPM_MODE,
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cienum {
14662306a36Sopenharmony_ci	ADC_MODE_INVALID = 0,
14762306a36Sopenharmony_ci	ADC_MODE_HIFI,
14862306a36Sopenharmony_ci	ADC_MODE_LO_HIF,
14962306a36Sopenharmony_ci	ADC_MODE_NORMAL,
15062306a36Sopenharmony_ci	ADC_MODE_LP,
15162306a36Sopenharmony_ci	ADC_MODE_ULP1,
15262306a36Sopenharmony_ci	ADC_MODE_ULP2,
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cienum {
15662306a36Sopenharmony_ci	AIF1_PB = 0,
15762306a36Sopenharmony_ci	AIF1_CAP,
15862306a36Sopenharmony_ci	NUM_CODEC_DAIS,
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic u8 tx_mode_bit[] = {
16262306a36Sopenharmony_ci	[ADC_MODE_INVALID] = 0x00,
16362306a36Sopenharmony_ci	[ADC_MODE_HIFI] = 0x01,
16462306a36Sopenharmony_ci	[ADC_MODE_LO_HIF] = 0x02,
16562306a36Sopenharmony_ci	[ADC_MODE_NORMAL] = 0x04,
16662306a36Sopenharmony_ci	[ADC_MODE_LP] = 0x08,
16762306a36Sopenharmony_ci	[ADC_MODE_ULP1] = 0x10,
16862306a36Sopenharmony_ci	[ADC_MODE_ULP2] = 0x20,
16962306a36Sopenharmony_ci};
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistruct wcd938x_priv {
17262306a36Sopenharmony_ci	struct sdw_slave *tx_sdw_dev;
17362306a36Sopenharmony_ci	struct wcd938x_sdw_priv *sdw_priv[NUM_CODEC_DAIS];
17462306a36Sopenharmony_ci	struct device *txdev;
17562306a36Sopenharmony_ci	struct device *rxdev;
17662306a36Sopenharmony_ci	struct device_node *rxnode, *txnode;
17762306a36Sopenharmony_ci	struct regmap *regmap;
17862306a36Sopenharmony_ci	struct mutex micb_lock;
17962306a36Sopenharmony_ci	/* mbhc module */
18062306a36Sopenharmony_ci	struct wcd_mbhc *wcd_mbhc;
18162306a36Sopenharmony_ci	struct wcd_mbhc_config mbhc_cfg;
18262306a36Sopenharmony_ci	struct wcd_mbhc_intr intr_ids;
18362306a36Sopenharmony_ci	struct wcd_clsh_ctrl *clsh_info;
18462306a36Sopenharmony_ci	struct irq_domain *virq;
18562306a36Sopenharmony_ci	struct regmap_irq_chip *wcd_regmap_irq_chip;
18662306a36Sopenharmony_ci	struct regmap_irq_chip_data *irq_chip;
18762306a36Sopenharmony_ci	struct regulator_bulk_data supplies[WCD938X_MAX_SUPPLY];
18862306a36Sopenharmony_ci	struct snd_soc_jack *jack;
18962306a36Sopenharmony_ci	unsigned long status_mask;
19062306a36Sopenharmony_ci	s32 micb_ref[WCD938X_MAX_MICBIAS];
19162306a36Sopenharmony_ci	s32 pullup_ref[WCD938X_MAX_MICBIAS];
19262306a36Sopenharmony_ci	u32 hph_mode;
19362306a36Sopenharmony_ci	u32 tx_mode[TX_ADC_MAX];
19462306a36Sopenharmony_ci	int flyback_cur_det_disable;
19562306a36Sopenharmony_ci	int ear_rx_path;
19662306a36Sopenharmony_ci	int variant;
19762306a36Sopenharmony_ci	int reset_gpio;
19862306a36Sopenharmony_ci	struct gpio_desc *us_euro_gpio;
19962306a36Sopenharmony_ci	u32 micb1_mv;
20062306a36Sopenharmony_ci	u32 micb2_mv;
20162306a36Sopenharmony_ci	u32 micb3_mv;
20262306a36Sopenharmony_ci	u32 micb4_mv;
20362306a36Sopenharmony_ci	int hphr_pdm_wd_int;
20462306a36Sopenharmony_ci	int hphl_pdm_wd_int;
20562306a36Sopenharmony_ci	int aux_pdm_wd_int;
20662306a36Sopenharmony_ci	bool comp1_enable;
20762306a36Sopenharmony_ci	bool comp2_enable;
20862306a36Sopenharmony_ci	bool ldoh;
20962306a36Sopenharmony_ci	bool bcs_dis;
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
21362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, 0);
21462306a36Sopenharmony_cistatic const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistruct wcd938x_mbhc_zdet_param {
21762306a36Sopenharmony_ci	u16 ldo_ctl;
21862306a36Sopenharmony_ci	u16 noff;
21962306a36Sopenharmony_ci	u16 nshift;
22062306a36Sopenharmony_ci	u16 btn5;
22162306a36Sopenharmony_ci	u16 btn6;
22262306a36Sopenharmony_ci	u16 btn7;
22362306a36Sopenharmony_ci};
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
22662306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80),
22762306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40),
22862306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20),
22962306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30),
23062306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08),
23162306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F),
23262306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04),
23362306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10),
23462306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08),
23562306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01),
23662306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06),
23762306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80),
23862306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F),
23962306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03),
24062306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03),
24162306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08),
24262306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
24362306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20),
24462306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80),
24562306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40),
24662306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10),
24762306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07),
24862306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70),
24962306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF),
25062306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0),
25162306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF),
25262306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40),
25362306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80),
25462306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0),
25562306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10),
25662306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02),
25762306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01),
25862306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70),
25962306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20),
26062306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40),
26162306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10),
26262306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01),
26362306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01),
26462306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80),
26562306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20),
26662306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08),
26762306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40),
26862306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80),
26962306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF),
27062306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F),
27162306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10),
27262306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04),
27362306a36Sopenharmony_ci	WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02),
27462306a36Sopenharmony_ci};
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_cistatic const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = {
27762306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
27862306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02),
27962306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04),
28062306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08),
28162306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_SW_DET, 0, 0x10),
28262306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_OCP_INT, 0, 0x20),
28362306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_CNP_INT, 0, 0x40),
28462306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_OCP_INT, 0, 0x80),
28562306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_CNP_INT, 1, 0x01),
28662306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_CNP_INT, 1, 0x02),
28762306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_SCD_INT, 1, 0x04),
28862306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_CNP_INT, 1, 0x08),
28962306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_SCD_INT, 1, 0x10),
29062306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_PDM_WD_INT, 1, 0x20),
29162306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_PDM_WD_INT, 1, 0x40),
29262306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_PDM_WD_INT, 1, 0x80),
29362306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_LDORT_SCD_INT, 2, 0x01),
29462306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_MOISTURE_INT, 2, 0x02),
29562306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_SURGE_DET_INT, 2, 0x04),
29662306a36Sopenharmony_ci	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08),
29762306a36Sopenharmony_ci};
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic struct regmap_irq_chip wcd938x_regmap_irq_chip = {
30062306a36Sopenharmony_ci	.name = "wcd938x",
30162306a36Sopenharmony_ci	.irqs = wcd938x_irqs,
30262306a36Sopenharmony_ci	.num_irqs = ARRAY_SIZE(wcd938x_irqs),
30362306a36Sopenharmony_ci	.num_regs = 3,
30462306a36Sopenharmony_ci	.status_base = WCD938X_DIGITAL_INTR_STATUS_0,
30562306a36Sopenharmony_ci	.mask_base = WCD938X_DIGITAL_INTR_MASK_0,
30662306a36Sopenharmony_ci	.ack_base = WCD938X_DIGITAL_INTR_CLEAR_0,
30762306a36Sopenharmony_ci	.use_ack = 1,
30862306a36Sopenharmony_ci	.runtime_pm = true,
30962306a36Sopenharmony_ci	.irq_drv_data = NULL,
31062306a36Sopenharmony_ci};
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic int wcd938x_get_clk_rate(int mode)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	int rate;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	switch (mode) {
31762306a36Sopenharmony_ci	case ADC_MODE_ULP2:
31862306a36Sopenharmony_ci		rate = SWR_CLK_RATE_0P6MHZ;
31962306a36Sopenharmony_ci		break;
32062306a36Sopenharmony_ci	case ADC_MODE_ULP1:
32162306a36Sopenharmony_ci		rate = SWR_CLK_RATE_1P2MHZ;
32262306a36Sopenharmony_ci		break;
32362306a36Sopenharmony_ci	case ADC_MODE_LP:
32462306a36Sopenharmony_ci		rate = SWR_CLK_RATE_4P8MHZ;
32562306a36Sopenharmony_ci		break;
32662306a36Sopenharmony_ci	case ADC_MODE_NORMAL:
32762306a36Sopenharmony_ci	case ADC_MODE_LO_HIF:
32862306a36Sopenharmony_ci	case ADC_MODE_HIFI:
32962306a36Sopenharmony_ci	case ADC_MODE_INVALID:
33062306a36Sopenharmony_ci	default:
33162306a36Sopenharmony_ci		rate = SWR_CLK_RATE_9P6MHZ;
33262306a36Sopenharmony_ci		break;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	return rate;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic int wcd938x_set_swr_clk_rate(struct snd_soc_component *component, int rate, int bank)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	u8 mask = (bank ? 0xF0 : 0x0F);
34162306a36Sopenharmony_ci	u8 val = 0;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	switch (rate) {
34462306a36Sopenharmony_ci	case SWR_CLK_RATE_0P6MHZ:
34562306a36Sopenharmony_ci		val = (bank ? 0x60 : 0x06);
34662306a36Sopenharmony_ci		break;
34762306a36Sopenharmony_ci	case SWR_CLK_RATE_1P2MHZ:
34862306a36Sopenharmony_ci		val = (bank ? 0x50 : 0x05);
34962306a36Sopenharmony_ci		break;
35062306a36Sopenharmony_ci	case SWR_CLK_RATE_2P4MHZ:
35162306a36Sopenharmony_ci		val = (bank ? 0x30 : 0x03);
35262306a36Sopenharmony_ci		break;
35362306a36Sopenharmony_ci	case SWR_CLK_RATE_4P8MHZ:
35462306a36Sopenharmony_ci		val = (bank ? 0x10 : 0x01);
35562306a36Sopenharmony_ci		break;
35662306a36Sopenharmony_ci	case SWR_CLK_RATE_9P6MHZ:
35762306a36Sopenharmony_ci	default:
35862306a36Sopenharmony_ci		val = 0x00;
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci	snd_soc_component_update_bits(component, WCD938X_DIGITAL_SWR_TX_CLK_RATE,
36262306a36Sopenharmony_ci				      mask, val);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return 0;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int wcd938x_io_init(struct wcd938x_priv *wcd938x)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct regmap *rm = wcd938x->regmap;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x0E, 0x0E);
37262306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x80, 0x80);
37362306a36Sopenharmony_ci	/* 1 msec delay as per HW requirement */
37462306a36Sopenharmony_ci	usleep_range(1000, 1010);
37562306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x40, 0x40);
37662306a36Sopenharmony_ci	/* 1 msec delay as per HW requirement */
37762306a36Sopenharmony_ci	usleep_range(1000, 1010);
37862306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_LDORXTX_CONFIG, 0x10, 0x00);
37962306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_BIAS_VBG_FINE_ADJ,
38062306a36Sopenharmony_ci								0xF0, 0x80);
38162306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x80, 0x80);
38262306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x40);
38362306a36Sopenharmony_ci	/* 10 msec delay as per HW requirement */
38462306a36Sopenharmony_ci	usleep_range(10000, 10010);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x00);
38762306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL,
38862306a36Sopenharmony_ci				      0xF0, 0x00);
38962306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW,
39062306a36Sopenharmony_ci				      0x1F, 0x15);
39162306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW,
39262306a36Sopenharmony_ci				      0x1F, 0x15);
39362306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_HPH_REFBUFF_UHQA_CTL,
39462306a36Sopenharmony_ci				      0xC0, 0x80);
39562306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_CDC_DMIC_CTL,
39662306a36Sopenharmony_ci				      0x02, 0x02);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP,
39962306a36Sopenharmony_ci			   0xFF, 0x14);
40062306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP,
40162306a36Sopenharmony_ci			   0x1F, 0x08);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0xFF, 0x55);
40462306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0xFF, 0x44);
40562306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0xFF, 0x11);
40662306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0xFF, 0x00);
40762306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0xFF, 0x00);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	/* Set Noise Filter Resistor value */
41062306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_MICB1_TEST_CTL_1, 0xE0, 0xE0);
41162306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_MICB2_TEST_CTL_1, 0xE0, 0xE0);
41262306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_MICB3_TEST_CTL_1, 0xE0, 0xE0);
41362306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_MICB4_TEST_CTL_1, 0xE0, 0xE0);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_TX_3_4_TEST_BLK_EN2, 0x01, 0x00);
41662306a36Sopenharmony_ci	regmap_update_bits(rm, WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	return 0;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info,
42362306a36Sopenharmony_ci				    struct sdw_port_config *port_config,
42462306a36Sopenharmony_ci				    u8 enable)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	u8 ch_mask, port_num;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	port_num = ch_info->port_num;
42962306a36Sopenharmony_ci	ch_mask = ch_info->ch_mask;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	port_config->num = port_num;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	if (enable)
43462306a36Sopenharmony_ci		port_config->ch_mask |= ch_mask;
43562306a36Sopenharmony_ci	else
43662306a36Sopenharmony_ci		port_config->ch_mask &= ~ch_mask;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	return 0;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 port_num, u8 ch_id, u8 enable)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id],
44462306a36Sopenharmony_ci					&wcd->port_config[port_num - 1],
44562306a36Sopenharmony_ci					enable);
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistatic int wcd938x_codec_enable_rxclk(struct snd_soc_dapm_widget *w,
44962306a36Sopenharmony_ci				      struct snd_kcontrol *kcontrol,
45062306a36Sopenharmony_ci				      int event)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	switch (event) {
45562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
45662306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
45762306a36Sopenharmony_ci				WCD938X_ANA_RX_CLK_EN_MASK, 1);
45862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
45962306a36Sopenharmony_ci				WCD938X_RX_BIAS_EN_MASK, 1);
46062306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX0_CTL,
46162306a36Sopenharmony_ci				WCD938X_DEM_DITHER_ENABLE_MASK, 0);
46262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX1_CTL,
46362306a36Sopenharmony_ci				WCD938X_DEM_DITHER_ENABLE_MASK, 0);
46462306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX2_CTL,
46562306a36Sopenharmony_ci				WCD938X_DEM_DITHER_ENABLE_MASK, 0);
46662306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
46762306a36Sopenharmony_ci				WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 1);
46862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_AUX_AUXPA,
46962306a36Sopenharmony_ci					      WCD938X_AUXPA_CLK_EN_MASK, 1);
47062306a36Sopenharmony_ci		break;
47162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
47262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
47362306a36Sopenharmony_ci				WCD938X_VNEG_EN_MASK, 0);
47462306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
47562306a36Sopenharmony_ci				WCD938X_VPOS_EN_MASK, 0);
47662306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
47762306a36Sopenharmony_ci				WCD938X_RX_BIAS_EN_MASK, 0);
47862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
47962306a36Sopenharmony_ci				WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 0);
48062306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
48162306a36Sopenharmony_ci				WCD938X_ANA_RX_CLK_EN_MASK, 0);
48262306a36Sopenharmony_ci		break;
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci	return 0;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic int wcd938x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
48862306a36Sopenharmony_ci					struct snd_kcontrol *kcontrol,
48962306a36Sopenharmony_ci					int event)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
49262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	switch (event) {
49562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
49662306a36Sopenharmony_ci		snd_soc_component_write_field(component,
49762306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
49862306a36Sopenharmony_ci				WCD938X_RXD0_CLK_EN_MASK, 0x01);
49962306a36Sopenharmony_ci		snd_soc_component_write_field(component,
50062306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,
50162306a36Sopenharmony_ci				WCD938X_HPHL_RX_EN_MASK, 1);
50262306a36Sopenharmony_ci		snd_soc_component_write_field(component,
50362306a36Sopenharmony_ci				WCD938X_HPH_RDAC_CLK_CTL1,
50462306a36Sopenharmony_ci				WCD938X_CHOP_CLK_EN_MASK, 0);
50562306a36Sopenharmony_ci		break;
50662306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
50762306a36Sopenharmony_ci		snd_soc_component_write_field(component,
50862306a36Sopenharmony_ci				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L,
50962306a36Sopenharmony_ci				WCD938X_HPH_RES_DIV_MASK, 0x02);
51062306a36Sopenharmony_ci		if (wcd938x->comp1_enable) {
51162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
51262306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_COMP_CTL_0,
51362306a36Sopenharmony_ci				WCD938X_HPHL_COMP_EN_MASK, 1);
51462306a36Sopenharmony_ci			/* 5msec compander delay as per HW requirement */
51562306a36Sopenharmony_ci			if (!wcd938x->comp2_enable || (snd_soc_component_read(component,
51662306a36Sopenharmony_ci							 WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x01))
51762306a36Sopenharmony_ci				usleep_range(5000, 5010);
51862306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,
51962306a36Sopenharmony_ci					      WCD938X_AUTOCHOP_TIMER_EN, 0);
52062306a36Sopenharmony_ci		} else {
52162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
52262306a36Sopenharmony_ci					WCD938X_DIGITAL_CDC_COMP_CTL_0,
52362306a36Sopenharmony_ci					WCD938X_HPHL_COMP_EN_MASK, 0);
52462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
52562306a36Sopenharmony_ci					WCD938X_HPH_L_EN,
52662306a36Sopenharmony_ci					WCD938X_GAIN_SRC_SEL_MASK,
52762306a36Sopenharmony_ci					WCD938X_GAIN_SRC_SEL_REGISTER);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci		}
53062306a36Sopenharmony_ci		break;
53162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
53262306a36Sopenharmony_ci		snd_soc_component_write_field(component,
53362306a36Sopenharmony_ci			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,
53462306a36Sopenharmony_ci			WCD938X_HPH_RES_DIV_MASK, 0x1);
53562306a36Sopenharmony_ci		break;
53662306a36Sopenharmony_ci	}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	return 0;
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cistatic int wcd938x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
54262306a36Sopenharmony_ci					struct snd_kcontrol *kcontrol,
54362306a36Sopenharmony_ci					int event)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
54662306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	switch (event) {
54962306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
55062306a36Sopenharmony_ci		snd_soc_component_write_field(component,
55162306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
55262306a36Sopenharmony_ci				WCD938X_RXD1_CLK_EN_MASK, 1);
55362306a36Sopenharmony_ci		snd_soc_component_write_field(component,
55462306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,
55562306a36Sopenharmony_ci				WCD938X_HPHR_RX_EN_MASK, 1);
55662306a36Sopenharmony_ci		snd_soc_component_write_field(component,
55762306a36Sopenharmony_ci				WCD938X_HPH_RDAC_CLK_CTL1,
55862306a36Sopenharmony_ci				WCD938X_CHOP_CLK_EN_MASK, 0);
55962306a36Sopenharmony_ci		break;
56062306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
56162306a36Sopenharmony_ci		snd_soc_component_write_field(component,
56262306a36Sopenharmony_ci				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,
56362306a36Sopenharmony_ci				WCD938X_HPH_RES_DIV_MASK, 0x02);
56462306a36Sopenharmony_ci		if (wcd938x->comp2_enable) {
56562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
56662306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_COMP_CTL_0,
56762306a36Sopenharmony_ci				WCD938X_HPHR_COMP_EN_MASK, 1);
56862306a36Sopenharmony_ci			/* 5msec compander delay as per HW requirement */
56962306a36Sopenharmony_ci			if (!wcd938x->comp1_enable ||
57062306a36Sopenharmony_ci				(snd_soc_component_read(component,
57162306a36Sopenharmony_ci					WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x02))
57262306a36Sopenharmony_ci				usleep_range(5000, 5010);
57362306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,
57462306a36Sopenharmony_ci					      WCD938X_AUTOCHOP_TIMER_EN, 0);
57562306a36Sopenharmony_ci		} else {
57662306a36Sopenharmony_ci			snd_soc_component_write_field(component,
57762306a36Sopenharmony_ci					WCD938X_DIGITAL_CDC_COMP_CTL_0,
57862306a36Sopenharmony_ci					WCD938X_HPHR_COMP_EN_MASK, 0);
57962306a36Sopenharmony_ci			snd_soc_component_write_field(component,
58062306a36Sopenharmony_ci					WCD938X_HPH_R_EN,
58162306a36Sopenharmony_ci					WCD938X_GAIN_SRC_SEL_MASK,
58262306a36Sopenharmony_ci					WCD938X_GAIN_SRC_SEL_REGISTER);
58362306a36Sopenharmony_ci		}
58462306a36Sopenharmony_ci		break;
58562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
58662306a36Sopenharmony_ci		snd_soc_component_write_field(component,
58762306a36Sopenharmony_ci			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,
58862306a36Sopenharmony_ci			WCD938X_HPH_RES_DIV_MASK, 0x01);
58962306a36Sopenharmony_ci		break;
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	return 0;
59362306a36Sopenharmony_ci}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic int wcd938x_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
59662306a36Sopenharmony_ci				       struct snd_kcontrol *kcontrol,
59762306a36Sopenharmony_ci				       int event)
59862306a36Sopenharmony_ci{
59962306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
60062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	switch (event) {
60362306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
60462306a36Sopenharmony_ci		wcd938x->ear_rx_path =
60562306a36Sopenharmony_ci			snd_soc_component_read(
60662306a36Sopenharmony_ci				component, WCD938X_DIGITAL_CDC_EAR_PATH_CTL);
60762306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) {
60862306a36Sopenharmony_ci			snd_soc_component_write_field(component,
60962306a36Sopenharmony_ci				WCD938X_EAR_EAR_DAC_CON,
61062306a36Sopenharmony_ci				WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 0);
61162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
61262306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,
61362306a36Sopenharmony_ci				WCD938X_AUX_EN_MASK, 1);
61462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
61562306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
61662306a36Sopenharmony_ci				WCD938X_RXD2_CLK_EN_MASK, 1);
61762306a36Sopenharmony_ci			snd_soc_component_write_field(component,
61862306a36Sopenharmony_ci				WCD938X_ANA_EAR_COMPANDER_CTL,
61962306a36Sopenharmony_ci				WCD938X_GAIN_OVRD_REG_MASK, 1);
62062306a36Sopenharmony_ci		} else {
62162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
62262306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,
62362306a36Sopenharmony_ci				WCD938X_HPHL_RX_EN_MASK, 1);
62462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
62562306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
62662306a36Sopenharmony_ci				WCD938X_RXD0_CLK_EN_MASK, 1);
62762306a36Sopenharmony_ci			if (wcd938x->comp1_enable)
62862306a36Sopenharmony_ci				snd_soc_component_write_field(component,
62962306a36Sopenharmony_ci					WCD938X_DIGITAL_CDC_COMP_CTL_0,
63062306a36Sopenharmony_ci					WCD938X_HPHL_COMP_EN_MASK, 1);
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci		/* 5 msec delay as per HW requirement */
63362306a36Sopenharmony_ci		usleep_range(5000, 5010);
63462306a36Sopenharmony_ci		if (wcd938x->flyback_cur_det_disable == 0)
63562306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,
63662306a36Sopenharmony_ci						      WCD938X_EN_CUR_DET_MASK, 0);
63762306a36Sopenharmony_ci		wcd938x->flyback_cur_det_disable++;
63862306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,
63962306a36Sopenharmony_ci			     WCD_CLSH_EVENT_PRE_DAC,
64062306a36Sopenharmony_ci			     WCD_CLSH_STATE_EAR,
64162306a36Sopenharmony_ci			     wcd938x->hph_mode);
64262306a36Sopenharmony_ci		break;
64362306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
64462306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) {
64562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
64662306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,
64762306a36Sopenharmony_ci				WCD938X_AUX_EN_MASK, 0);
64862306a36Sopenharmony_ci			snd_soc_component_write_field(component,
64962306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
65062306a36Sopenharmony_ci				WCD938X_RXD2_CLK_EN_MASK, 0);
65162306a36Sopenharmony_ci		} else {
65262306a36Sopenharmony_ci			snd_soc_component_write_field(component,
65362306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,
65462306a36Sopenharmony_ci				WCD938X_HPHL_RX_EN_MASK, 0);
65562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
65662306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
65762306a36Sopenharmony_ci				WCD938X_RXD0_CLK_EN_MASK, 0);
65862306a36Sopenharmony_ci			if (wcd938x->comp1_enable)
65962306a36Sopenharmony_ci				snd_soc_component_write_field(component,
66062306a36Sopenharmony_ci					WCD938X_DIGITAL_CDC_COMP_CTL_0,
66162306a36Sopenharmony_ci					WCD938X_HPHL_COMP_EN_MASK, 0);
66262306a36Sopenharmony_ci		}
66362306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,
66462306a36Sopenharmony_ci					      WCD938X_GAIN_OVRD_REG_MASK, 0);
66562306a36Sopenharmony_ci		snd_soc_component_write_field(component,
66662306a36Sopenharmony_ci				WCD938X_EAR_EAR_DAC_CON,
66762306a36Sopenharmony_ci				WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 1);
66862306a36Sopenharmony_ci		break;
66962306a36Sopenharmony_ci	}
67062306a36Sopenharmony_ci	return 0;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
67562306a36Sopenharmony_ci				       struct snd_kcontrol *kcontrol,
67662306a36Sopenharmony_ci				       int event)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
67962306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	switch (event) {
68262306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
68362306a36Sopenharmony_ci		snd_soc_component_write_field(component,
68462306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
68562306a36Sopenharmony_ci				WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 1);
68662306a36Sopenharmony_ci		snd_soc_component_write_field(component,
68762306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
68862306a36Sopenharmony_ci				WCD938X_RXD2_CLK_EN_MASK, 1);
68962306a36Sopenharmony_ci		snd_soc_component_write_field(component,
69062306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,
69162306a36Sopenharmony_ci				WCD938X_AUX_EN_MASK, 1);
69262306a36Sopenharmony_ci		if (wcd938x->flyback_cur_det_disable == 0)
69362306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,
69462306a36Sopenharmony_ci						      WCD938X_EN_CUR_DET_MASK, 0);
69562306a36Sopenharmony_ci		wcd938x->flyback_cur_det_disable++;
69662306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,
69762306a36Sopenharmony_ci			     WCD_CLSH_EVENT_PRE_DAC,
69862306a36Sopenharmony_ci			     WCD_CLSH_STATE_AUX,
69962306a36Sopenharmony_ci			     wcd938x->hph_mode);
70062306a36Sopenharmony_ci		break;
70162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
70262306a36Sopenharmony_ci		snd_soc_component_write_field(component,
70362306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
70462306a36Sopenharmony_ci				WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0);
70562306a36Sopenharmony_ci		break;
70662306a36Sopenharmony_ci	}
70762306a36Sopenharmony_ci	return 0;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_cistatic int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
71262306a36Sopenharmony_ci					struct snd_kcontrol *kcontrol, int event)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
71562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
71662306a36Sopenharmony_ci	int hph_mode = wcd938x->hph_mode;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	switch (event) {
71962306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
72062306a36Sopenharmony_ci		if (wcd938x->ldoh)
72162306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,
72262306a36Sopenharmony_ci						      WCD938X_LDOH_EN_MASK, 1);
72362306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC,
72462306a36Sopenharmony_ci					WCD_CLSH_STATE_HPHR, hph_mode);
72562306a36Sopenharmony_ci		wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
72862306a36Sopenharmony_ci		    hph_mode == CLS_H_ULP) {
72962306a36Sopenharmony_ci			snd_soc_component_write_field(component,
73062306a36Sopenharmony_ci				WCD938X_HPH_REFBUFF_LP_CTL,
73162306a36Sopenharmony_ci				WCD938X_PREREF_FLIT_BYPASS_MASK, 1);
73262306a36Sopenharmony_ci		}
73362306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
73462306a36Sopenharmony_ci					      WCD938X_HPHR_REF_EN_MASK, 1);
73562306a36Sopenharmony_ci		wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode);
73662306a36Sopenharmony_ci		/* 100 usec delay as per HW requirement */
73762306a36Sopenharmony_ci		usleep_range(100, 110);
73862306a36Sopenharmony_ci		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
73962306a36Sopenharmony_ci		snd_soc_component_write_field(component,
74062306a36Sopenharmony_ci					      WCD938X_DIGITAL_PDM_WD_CTL1,
74162306a36Sopenharmony_ci					      WCD938X_PDM_WD_EN_MASK, 0x3);
74262306a36Sopenharmony_ci		break;
74362306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
74462306a36Sopenharmony_ci		/*
74562306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
74662306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
74762306a36Sopenharmony_ci		 * 20ms delay is required.
74862306a36Sopenharmony_ci		 */
74962306a36Sopenharmony_ci		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
75062306a36Sopenharmony_ci			if (!wcd938x->comp2_enable)
75162306a36Sopenharmony_ci				usleep_range(20000, 20100);
75262306a36Sopenharmony_ci			else
75362306a36Sopenharmony_ci				usleep_range(7000, 7100);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci			if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
75662306a36Sopenharmony_ci			    hph_mode == CLS_H_ULP)
75762306a36Sopenharmony_ci				snd_soc_component_write_field(component,
75862306a36Sopenharmony_ci						WCD938X_HPH_REFBUFF_LP_CTL,
75962306a36Sopenharmony_ci						WCD938X_PREREF_FLIT_BYPASS_MASK, 0);
76062306a36Sopenharmony_ci			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
76162306a36Sopenharmony_ci		}
76262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,
76362306a36Sopenharmony_ci					      WCD938X_AUTOCHOP_TIMER_EN, 1);
76462306a36Sopenharmony_ci		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
76562306a36Sopenharmony_ci			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
76662306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
76762306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_MASK,
76862306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_CLASS_AB);
76962306a36Sopenharmony_ci		enable_irq(wcd938x->hphr_pdm_wd_int);
77062306a36Sopenharmony_ci		break;
77162306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
77262306a36Sopenharmony_ci		disable_irq_nosync(wcd938x->hphr_pdm_wd_int);
77362306a36Sopenharmony_ci		/*
77462306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
77562306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
77662306a36Sopenharmony_ci		 * 20ms delay is required.
77762306a36Sopenharmony_ci		 */
77862306a36Sopenharmony_ci		if (!wcd938x->comp2_enable)
77962306a36Sopenharmony_ci			usleep_range(20000, 20100);
78062306a36Sopenharmony_ci		else
78162306a36Sopenharmony_ci			usleep_range(7000, 7100);
78262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
78362306a36Sopenharmony_ci					      WCD938X_HPHR_EN_MASK, 0);
78462306a36Sopenharmony_ci		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
78562306a36Sopenharmony_ci					     WCD_EVENT_PRE_HPHR_PA_OFF);
78662306a36Sopenharmony_ci		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
78762306a36Sopenharmony_ci		break;
78862306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
78962306a36Sopenharmony_ci		/*
79062306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
79162306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
79262306a36Sopenharmony_ci		 * 20ms delay is required.
79362306a36Sopenharmony_ci		 */
79462306a36Sopenharmony_ci		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
79562306a36Sopenharmony_ci			if (!wcd938x->comp2_enable)
79662306a36Sopenharmony_ci				usleep_range(20000, 20100);
79762306a36Sopenharmony_ci			else
79862306a36Sopenharmony_ci				usleep_range(7000, 7100);
79962306a36Sopenharmony_ci			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
80062306a36Sopenharmony_ci		}
80162306a36Sopenharmony_ci		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
80262306a36Sopenharmony_ci					     WCD_EVENT_POST_HPHR_PA_OFF);
80362306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
80462306a36Sopenharmony_ci					      WCD938X_HPHR_REF_EN_MASK, 0);
80562306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1,
80662306a36Sopenharmony_ci					      WCD938X_PDM_WD_EN_MASK, 0);
80762306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,
80862306a36Sopenharmony_ci					WCD_CLSH_STATE_HPHR, hph_mode);
80962306a36Sopenharmony_ci		if (wcd938x->ldoh)
81062306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,
81162306a36Sopenharmony_ci						      WCD938X_LDOH_EN_MASK, 0);
81262306a36Sopenharmony_ci		break;
81362306a36Sopenharmony_ci	}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	return 0;
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_cistatic int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
81962306a36Sopenharmony_ci					struct snd_kcontrol *kcontrol, int event)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
82262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
82362306a36Sopenharmony_ci	int hph_mode = wcd938x->hph_mode;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	switch (event) {
82662306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
82762306a36Sopenharmony_ci		if (wcd938x->ldoh)
82862306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,
82962306a36Sopenharmony_ci						      WCD938X_LDOH_EN_MASK, 1);
83062306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC,
83162306a36Sopenharmony_ci					WCD_CLSH_STATE_HPHL, hph_mode);
83262306a36Sopenharmony_ci		wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI);
83362306a36Sopenharmony_ci		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
83462306a36Sopenharmony_ci		    hph_mode == CLS_H_ULP) {
83562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
83662306a36Sopenharmony_ci					WCD938X_HPH_REFBUFF_LP_CTL,
83762306a36Sopenharmony_ci					WCD938X_PREREF_FLIT_BYPASS_MASK, 1);
83862306a36Sopenharmony_ci		}
83962306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
84062306a36Sopenharmony_ci					      WCD938X_HPHL_REF_EN_MASK, 1);
84162306a36Sopenharmony_ci		wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode);
84262306a36Sopenharmony_ci		/* 100 usec delay as per HW requirement */
84362306a36Sopenharmony_ci		usleep_range(100, 110);
84462306a36Sopenharmony_ci		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
84562306a36Sopenharmony_ci		snd_soc_component_write_field(component,
84662306a36Sopenharmony_ci					WCD938X_DIGITAL_PDM_WD_CTL0,
84762306a36Sopenharmony_ci					WCD938X_PDM_WD_EN_MASK, 0x3);
84862306a36Sopenharmony_ci		break;
84962306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
85062306a36Sopenharmony_ci		/*
85162306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
85262306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
85362306a36Sopenharmony_ci		 * 20ms delay is required.
85462306a36Sopenharmony_ci		 */
85562306a36Sopenharmony_ci		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
85662306a36Sopenharmony_ci			if (!wcd938x->comp1_enable)
85762306a36Sopenharmony_ci				usleep_range(20000, 20100);
85862306a36Sopenharmony_ci			else
85962306a36Sopenharmony_ci				usleep_range(7000, 7100);
86062306a36Sopenharmony_ci			if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
86162306a36Sopenharmony_ci			    hph_mode == CLS_H_ULP)
86262306a36Sopenharmony_ci				snd_soc_component_write_field(component,
86362306a36Sopenharmony_ci					WCD938X_HPH_REFBUFF_LP_CTL,
86462306a36Sopenharmony_ci					WCD938X_PREREF_FLIT_BYPASS_MASK, 0);
86562306a36Sopenharmony_ci			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
86662306a36Sopenharmony_ci		}
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,
86962306a36Sopenharmony_ci					      WCD938X_AUTOCHOP_TIMER_EN, 1);
87062306a36Sopenharmony_ci		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
87162306a36Sopenharmony_ci			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
87262306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
87362306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_MASK,
87462306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_CLASS_AB);
87562306a36Sopenharmony_ci		enable_irq(wcd938x->hphl_pdm_wd_int);
87662306a36Sopenharmony_ci		break;
87762306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
87862306a36Sopenharmony_ci		disable_irq_nosync(wcd938x->hphl_pdm_wd_int);
87962306a36Sopenharmony_ci		/*
88062306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
88162306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
88262306a36Sopenharmony_ci		 * 20ms delay is required.
88362306a36Sopenharmony_ci		 */
88462306a36Sopenharmony_ci		if (!wcd938x->comp1_enable)
88562306a36Sopenharmony_ci			usleep_range(20000, 20100);
88662306a36Sopenharmony_ci		else
88762306a36Sopenharmony_ci			usleep_range(7000, 7100);
88862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
88962306a36Sopenharmony_ci					      WCD938X_HPHL_EN_MASK, 0);
89062306a36Sopenharmony_ci		wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF);
89162306a36Sopenharmony_ci		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
89262306a36Sopenharmony_ci		break;
89362306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
89462306a36Sopenharmony_ci		/*
89562306a36Sopenharmony_ci		 * 7ms sleep is required if compander is enabled as per
89662306a36Sopenharmony_ci		 * HW requirement. If compander is disabled, then
89762306a36Sopenharmony_ci		 * 20ms delay is required.
89862306a36Sopenharmony_ci		 */
89962306a36Sopenharmony_ci		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
90062306a36Sopenharmony_ci			if (!wcd938x->comp1_enable)
90162306a36Sopenharmony_ci				usleep_range(21000, 21100);
90262306a36Sopenharmony_ci			else
90362306a36Sopenharmony_ci				usleep_range(7000, 7100);
90462306a36Sopenharmony_ci			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
90562306a36Sopenharmony_ci		}
90662306a36Sopenharmony_ci		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
90762306a36Sopenharmony_ci					     WCD_EVENT_POST_HPHL_PA_OFF);
90862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_HPH,
90962306a36Sopenharmony_ci					      WCD938X_HPHL_REF_EN_MASK, 0);
91062306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,
91162306a36Sopenharmony_ci					      WCD938X_PDM_WD_EN_MASK, 0);
91262306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,
91362306a36Sopenharmony_ci					WCD_CLSH_STATE_HPHL, hph_mode);
91462306a36Sopenharmony_ci		if (wcd938x->ldoh)
91562306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,
91662306a36Sopenharmony_ci						      WCD938X_LDOH_EN_MASK, 0);
91762306a36Sopenharmony_ci		break;
91862306a36Sopenharmony_ci	}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	return 0;
92162306a36Sopenharmony_ci}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cistatic int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
92462306a36Sopenharmony_ci				       struct snd_kcontrol *kcontrol, int event)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
92762306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
92862306a36Sopenharmony_ci	int hph_mode = wcd938x->hph_mode;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	switch (event) {
93162306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
93262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,
93362306a36Sopenharmony_ci					      WCD938X_AUX_PDM_WD_EN_MASK, 1);
93462306a36Sopenharmony_ci		break;
93562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
93662306a36Sopenharmony_ci		/* 1 msec delay as per HW requirement */
93762306a36Sopenharmony_ci		usleep_range(1000, 1010);
93862306a36Sopenharmony_ci		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
93962306a36Sopenharmony_ci			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
94062306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
94162306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_MASK,
94262306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_CLASS_AB);
94362306a36Sopenharmony_ci		enable_irq(wcd938x->aux_pdm_wd_int);
94462306a36Sopenharmony_ci		break;
94562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
94662306a36Sopenharmony_ci		disable_irq_nosync(wcd938x->aux_pdm_wd_int);
94762306a36Sopenharmony_ci		break;
94862306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
94962306a36Sopenharmony_ci		/* 1 msec delay as per HW requirement */
95062306a36Sopenharmony_ci		usleep_range(1000, 1010);
95162306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,
95262306a36Sopenharmony_ci					      WCD938X_AUX_PDM_WD_EN_MASK, 0);
95362306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,
95462306a36Sopenharmony_ci			     WCD_CLSH_EVENT_POST_PA,
95562306a36Sopenharmony_ci			     WCD_CLSH_STATE_AUX,
95662306a36Sopenharmony_ci			     hph_mode);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci		wcd938x->flyback_cur_det_disable--;
95962306a36Sopenharmony_ci		if (wcd938x->flyback_cur_det_disable == 0)
96062306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,
96162306a36Sopenharmony_ci						      WCD938X_EN_CUR_DET_MASK, 1);
96262306a36Sopenharmony_ci		break;
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci	return 0;
96562306a36Sopenharmony_ci}
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_cistatic int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
96862306a36Sopenharmony_ci				       struct snd_kcontrol *kcontrol, int event)
96962306a36Sopenharmony_ci{
97062306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
97162306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
97262306a36Sopenharmony_ci	int hph_mode = wcd938x->hph_mode;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	switch (event) {
97562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
97662306a36Sopenharmony_ci		/*
97762306a36Sopenharmony_ci		 * Enable watchdog interrupt for HPHL or AUX
97862306a36Sopenharmony_ci		 * depending on mux value
97962306a36Sopenharmony_ci		 */
98062306a36Sopenharmony_ci		wcd938x->ear_rx_path = snd_soc_component_read(component,
98162306a36Sopenharmony_ci							      WCD938X_DIGITAL_CDC_EAR_PATH_CTL);
98262306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
98362306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,
98462306a36Sopenharmony_ci					      WCD938X_AUX_PDM_WD_EN_MASK, 1);
98562306a36Sopenharmony_ci		else
98662306a36Sopenharmony_ci			snd_soc_component_write_field(component,
98762306a36Sopenharmony_ci						      WCD938X_DIGITAL_PDM_WD_CTL0,
98862306a36Sopenharmony_ci						      WCD938X_PDM_WD_EN_MASK, 0x3);
98962306a36Sopenharmony_ci		if (!wcd938x->comp1_enable)
99062306a36Sopenharmony_ci			snd_soc_component_write_field(component,
99162306a36Sopenharmony_ci						      WCD938X_ANA_EAR_COMPANDER_CTL,
99262306a36Sopenharmony_ci						      WCD938X_GAIN_OVRD_REG_MASK, 1);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci		break;
99562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
99662306a36Sopenharmony_ci		/* 6 msec delay as per HW requirement */
99762306a36Sopenharmony_ci		usleep_range(6000, 6010);
99862306a36Sopenharmony_ci		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||
99962306a36Sopenharmony_ci			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)
100062306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,
100162306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_MASK,
100262306a36Sopenharmony_ci					WCD938X_REGULATOR_MODE_CLASS_AB);
100362306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
100462306a36Sopenharmony_ci			enable_irq(wcd938x->aux_pdm_wd_int);
100562306a36Sopenharmony_ci		else
100662306a36Sopenharmony_ci			enable_irq(wcd938x->hphl_pdm_wd_int);
100762306a36Sopenharmony_ci		break;
100862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
100962306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
101062306a36Sopenharmony_ci			disable_irq_nosync(wcd938x->aux_pdm_wd_int);
101162306a36Sopenharmony_ci		else
101262306a36Sopenharmony_ci			disable_irq_nosync(wcd938x->hphl_pdm_wd_int);
101362306a36Sopenharmony_ci		break;
101462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
101562306a36Sopenharmony_ci		if (!wcd938x->comp1_enable)
101662306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,
101762306a36Sopenharmony_ci						      WCD938X_GAIN_OVRD_REG_MASK, 0);
101862306a36Sopenharmony_ci		/* 7 msec delay as per HW requirement */
101962306a36Sopenharmony_ci		usleep_range(7000, 7010);
102062306a36Sopenharmony_ci		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)
102162306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,
102262306a36Sopenharmony_ci					      WCD938X_AUX_PDM_WD_EN_MASK, 0);
102362306a36Sopenharmony_ci		else
102462306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,
102562306a36Sopenharmony_ci					WCD938X_PDM_WD_EN_MASK, 0);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,
102862306a36Sopenharmony_ci					WCD_CLSH_STATE_EAR, hph_mode);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci		wcd938x->flyback_cur_det_disable--;
103162306a36Sopenharmony_ci		if (wcd938x->flyback_cur_det_disable == 0)
103262306a36Sopenharmony_ci			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,
103362306a36Sopenharmony_ci						      WCD938X_EN_CUR_DET_MASK, 1);
103462306a36Sopenharmony_ci		break;
103562306a36Sopenharmony_ci	}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	return 0;
103862306a36Sopenharmony_ci}
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_cistatic int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
104162306a36Sopenharmony_ci				     struct snd_kcontrol *kcontrol,
104262306a36Sopenharmony_ci				     int event)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
104562306a36Sopenharmony_ci	u16 dmic_clk_reg, dmic_clk_en_reg;
104662306a36Sopenharmony_ci	u8 dmic_sel_mask, dmic_clk_mask;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	switch (w->shift) {
104962306a36Sopenharmony_ci	case 0:
105062306a36Sopenharmony_ci	case 1:
105162306a36Sopenharmony_ci		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;
105262306a36Sopenharmony_ci		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;
105362306a36Sopenharmony_ci		dmic_clk_mask = WCD938X_DMIC1_RATE_MASK;
105462306a36Sopenharmony_ci		dmic_sel_mask = WCD938X_AMIC1_IN_SEL_MASK;
105562306a36Sopenharmony_ci		break;
105662306a36Sopenharmony_ci	case 2:
105762306a36Sopenharmony_ci	case 3:
105862306a36Sopenharmony_ci		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;
105962306a36Sopenharmony_ci		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL;
106062306a36Sopenharmony_ci		dmic_clk_mask = WCD938X_DMIC2_RATE_MASK;
106162306a36Sopenharmony_ci		dmic_sel_mask = WCD938X_AMIC3_IN_SEL_MASK;
106262306a36Sopenharmony_ci		break;
106362306a36Sopenharmony_ci	case 4:
106462306a36Sopenharmony_ci	case 5:
106562306a36Sopenharmony_ci		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;
106662306a36Sopenharmony_ci		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC3_CTL;
106762306a36Sopenharmony_ci		dmic_clk_mask = WCD938X_DMIC3_RATE_MASK;
106862306a36Sopenharmony_ci		dmic_sel_mask = WCD938X_AMIC4_IN_SEL_MASK;
106962306a36Sopenharmony_ci		break;
107062306a36Sopenharmony_ci	case 6:
107162306a36Sopenharmony_ci	case 7:
107262306a36Sopenharmony_ci		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;
107362306a36Sopenharmony_ci		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC4_CTL;
107462306a36Sopenharmony_ci		dmic_clk_mask = WCD938X_DMIC4_RATE_MASK;
107562306a36Sopenharmony_ci		dmic_sel_mask = WCD938X_AMIC5_IN_SEL_MASK;
107662306a36Sopenharmony_ci		break;
107762306a36Sopenharmony_ci	default:
107862306a36Sopenharmony_ci		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
107962306a36Sopenharmony_ci			__func__);
108062306a36Sopenharmony_ci		return -EINVAL;
108162306a36Sopenharmony_ci	}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	switch (event) {
108462306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
108562306a36Sopenharmony_ci		snd_soc_component_write_field(component,
108662306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_AMIC_CTL,
108762306a36Sopenharmony_ci				dmic_sel_mask,
108862306a36Sopenharmony_ci				WCD938X_AMIC1_IN_SEL_DMIC);
108962306a36Sopenharmony_ci		/* 250us sleep as per HW requirement */
109062306a36Sopenharmony_ci		usleep_range(250, 260);
109162306a36Sopenharmony_ci		/* Setting DMIC clock rate to 2.4MHz */
109262306a36Sopenharmony_ci		snd_soc_component_write_field(component, dmic_clk_reg,
109362306a36Sopenharmony_ci					      dmic_clk_mask,
109462306a36Sopenharmony_ci					      WCD938X_DMIC4_RATE_2P4MHZ);
109562306a36Sopenharmony_ci		snd_soc_component_write_field(component, dmic_clk_en_reg,
109662306a36Sopenharmony_ci					      WCD938X_DMIC_CLK_EN_MASK, 1);
109762306a36Sopenharmony_ci		/* enable clock scaling */
109862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_DMIC_CTL,
109962306a36Sopenharmony_ci					      WCD938X_DMIC_CLK_SCALING_EN_MASK, 0x3);
110062306a36Sopenharmony_ci		break;
110162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
110262306a36Sopenharmony_ci		snd_soc_component_write_field(component,
110362306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_AMIC_CTL,
110462306a36Sopenharmony_ci				dmic_sel_mask, WCD938X_AMIC1_IN_SEL_AMIC);
110562306a36Sopenharmony_ci		snd_soc_component_write_field(component, dmic_clk_en_reg,
110662306a36Sopenharmony_ci					      WCD938X_DMIC_CLK_EN_MASK, 0);
110762306a36Sopenharmony_ci		break;
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci	return 0;
111062306a36Sopenharmony_ci}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_cistatic int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
111362306a36Sopenharmony_ci			       struct snd_kcontrol *kcontrol, int event)
111462306a36Sopenharmony_ci{
111562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
111662306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
111762306a36Sopenharmony_ci	int bank;
111862306a36Sopenharmony_ci	int rate;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	bank = (wcd938x_swr_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev)) ? 0 : 1;
112162306a36Sopenharmony_ci	bank = bank ? 0 : 1;
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	switch (event) {
112462306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
112562306a36Sopenharmony_ci		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
112662306a36Sopenharmony_ci			int i = 0, mode = 0;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci			if (test_bit(WCD_ADC1, &wcd938x->status_mask))
112962306a36Sopenharmony_ci				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];
113062306a36Sopenharmony_ci			if (test_bit(WCD_ADC2, &wcd938x->status_mask))
113162306a36Sopenharmony_ci				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];
113262306a36Sopenharmony_ci			if (test_bit(WCD_ADC3, &wcd938x->status_mask))
113362306a36Sopenharmony_ci				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];
113462306a36Sopenharmony_ci			if (test_bit(WCD_ADC4, &wcd938x->status_mask))
113562306a36Sopenharmony_ci				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci			if (mode != 0) {
113862306a36Sopenharmony_ci				for (i = 0; i < ADC_MODE_ULP2; i++) {
113962306a36Sopenharmony_ci					if (mode & (1 << i)) {
114062306a36Sopenharmony_ci						i++;
114162306a36Sopenharmony_ci						break;
114262306a36Sopenharmony_ci					}
114362306a36Sopenharmony_ci				}
114462306a36Sopenharmony_ci			}
114562306a36Sopenharmony_ci			rate = wcd938x_get_clk_rate(i);
114662306a36Sopenharmony_ci			wcd938x_set_swr_clk_rate(component, rate, bank);
114762306a36Sopenharmony_ci			/* Copy clk settings to active bank */
114862306a36Sopenharmony_ci			wcd938x_set_swr_clk_rate(component, rate, !bank);
114962306a36Sopenharmony_ci		}
115062306a36Sopenharmony_ci		break;
115162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
115262306a36Sopenharmony_ci		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
115362306a36Sopenharmony_ci			rate = wcd938x_get_clk_rate(ADC_MODE_INVALID);
115462306a36Sopenharmony_ci			wcd938x_set_swr_clk_rate(component, rate, !bank);
115562306a36Sopenharmony_ci			wcd938x_set_swr_clk_rate(component, rate, bank);
115662306a36Sopenharmony_ci		}
115762306a36Sopenharmony_ci		break;
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	return 0;
116162306a36Sopenharmony_ci}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_cistatic int wcd938x_get_adc_mode(int val)
116462306a36Sopenharmony_ci{
116562306a36Sopenharmony_ci	int ret = 0;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	switch (val) {
116862306a36Sopenharmony_ci	case ADC_MODE_INVALID:
116962306a36Sopenharmony_ci		ret = ADC_MODE_VAL_NORMAL;
117062306a36Sopenharmony_ci		break;
117162306a36Sopenharmony_ci	case ADC_MODE_HIFI:
117262306a36Sopenharmony_ci		ret = ADC_MODE_VAL_HIFI;
117362306a36Sopenharmony_ci		break;
117462306a36Sopenharmony_ci	case ADC_MODE_LO_HIF:
117562306a36Sopenharmony_ci		ret = ADC_MODE_VAL_LO_HIF;
117662306a36Sopenharmony_ci		break;
117762306a36Sopenharmony_ci	case ADC_MODE_NORMAL:
117862306a36Sopenharmony_ci		ret = ADC_MODE_VAL_NORMAL;
117962306a36Sopenharmony_ci		break;
118062306a36Sopenharmony_ci	case ADC_MODE_LP:
118162306a36Sopenharmony_ci		ret = ADC_MODE_VAL_LP;
118262306a36Sopenharmony_ci		break;
118362306a36Sopenharmony_ci	case ADC_MODE_ULP1:
118462306a36Sopenharmony_ci		ret = ADC_MODE_VAL_ULP1;
118562306a36Sopenharmony_ci		break;
118662306a36Sopenharmony_ci	case ADC_MODE_ULP2:
118762306a36Sopenharmony_ci		ret = ADC_MODE_VAL_ULP2;
118862306a36Sopenharmony_ci		break;
118962306a36Sopenharmony_ci	default:
119062306a36Sopenharmony_ci		ret = -EINVAL;
119162306a36Sopenharmony_ci		break;
119262306a36Sopenharmony_ci	}
119362306a36Sopenharmony_ci	return ret;
119462306a36Sopenharmony_ci}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_cistatic int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
119762306a36Sopenharmony_ci				    struct snd_kcontrol *kcontrol, int event)
119862306a36Sopenharmony_ci{
119962306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
120062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	switch (event) {
120362306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
120462306a36Sopenharmony_ci		snd_soc_component_write_field(component,
120562306a36Sopenharmony_ci					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
120662306a36Sopenharmony_ci					      WCD938X_ANA_TX_CLK_EN_MASK, 1);
120762306a36Sopenharmony_ci		snd_soc_component_write_field(component,
120862306a36Sopenharmony_ci					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
120962306a36Sopenharmony_ci					      WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);
121062306a36Sopenharmony_ci		set_bit(w->shift, &wcd938x->status_mask);
121162306a36Sopenharmony_ci		break;
121262306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
121362306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
121462306a36Sopenharmony_ci					      WCD938X_ANA_TX_CLK_EN_MASK, 0);
121562306a36Sopenharmony_ci		clear_bit(w->shift, &wcd938x->status_mask);
121662306a36Sopenharmony_ci		break;
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	return 0;
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cistatic void wcd938x_tx_channel_config(struct snd_soc_component *component,
122362306a36Sopenharmony_ci				     int channel, int mode)
122462306a36Sopenharmony_ci{
122562306a36Sopenharmony_ci	int reg, mask;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	switch (channel) {
122862306a36Sopenharmony_ci	case 0:
122962306a36Sopenharmony_ci		reg = WCD938X_ANA_TX_CH2;
123062306a36Sopenharmony_ci		mask = WCD938X_HPF1_INIT_MASK;
123162306a36Sopenharmony_ci		break;
123262306a36Sopenharmony_ci	case 1:
123362306a36Sopenharmony_ci		reg = WCD938X_ANA_TX_CH2;
123462306a36Sopenharmony_ci		mask = WCD938X_HPF2_INIT_MASK;
123562306a36Sopenharmony_ci		break;
123662306a36Sopenharmony_ci	case 2:
123762306a36Sopenharmony_ci		reg = WCD938X_ANA_TX_CH4;
123862306a36Sopenharmony_ci		mask = WCD938X_HPF3_INIT_MASK;
123962306a36Sopenharmony_ci		break;
124062306a36Sopenharmony_ci	case 3:
124162306a36Sopenharmony_ci		reg = WCD938X_ANA_TX_CH4;
124262306a36Sopenharmony_ci		mask = WCD938X_HPF4_INIT_MASK;
124362306a36Sopenharmony_ci		break;
124462306a36Sopenharmony_ci	default:
124562306a36Sopenharmony_ci		return;
124662306a36Sopenharmony_ci	}
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	snd_soc_component_write_field(component, reg, mask, mode);
124962306a36Sopenharmony_ci}
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_cistatic int wcd938x_adc_enable_req(struct snd_soc_dapm_widget *w,
125262306a36Sopenharmony_ci				  struct snd_kcontrol *kcontrol, int event)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
125562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
125662306a36Sopenharmony_ci	int mode;
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	switch (event) {
125962306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
126062306a36Sopenharmony_ci		snd_soc_component_write_field(component,
126162306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_REQ_CTL,
126262306a36Sopenharmony_ci				WCD938X_FS_RATE_4P8_MASK, 1);
126362306a36Sopenharmony_ci		snd_soc_component_write_field(component,
126462306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_REQ_CTL,
126562306a36Sopenharmony_ci				WCD938X_NO_NOTCH_MASK, 0);
126662306a36Sopenharmony_ci		wcd938x_tx_channel_config(component, w->shift, 1);
126762306a36Sopenharmony_ci		mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
126862306a36Sopenharmony_ci		if (mode < 0) {
126962306a36Sopenharmony_ci			dev_info(component->dev, "Invalid ADC mode\n");
127062306a36Sopenharmony_ci			return -EINVAL;
127162306a36Sopenharmony_ci		}
127262306a36Sopenharmony_ci		switch (w->shift) {
127362306a36Sopenharmony_ci		case 0:
127462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
127562306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
127662306a36Sopenharmony_ci				WCD938X_TXD0_MODE_MASK, mode);
127762306a36Sopenharmony_ci			snd_soc_component_write_field(component,
127862306a36Sopenharmony_ci						WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
127962306a36Sopenharmony_ci						WCD938X_TXD0_CLK_EN_MASK, 1);
128062306a36Sopenharmony_ci			break;
128162306a36Sopenharmony_ci		case 1:
128262306a36Sopenharmony_ci			snd_soc_component_write_field(component,
128362306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
128462306a36Sopenharmony_ci				WCD938X_TXD1_MODE_MASK, mode);
128562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
128662306a36Sopenharmony_ci					      WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
128762306a36Sopenharmony_ci					      WCD938X_TXD1_CLK_EN_MASK, 1);
128862306a36Sopenharmony_ci			break;
128962306a36Sopenharmony_ci		case 2:
129062306a36Sopenharmony_ci			snd_soc_component_write_field(component,
129162306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
129262306a36Sopenharmony_ci				WCD938X_TXD2_MODE_MASK, mode);
129362306a36Sopenharmony_ci			snd_soc_component_write_field(component,
129462306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
129562306a36Sopenharmony_ci				WCD938X_TXD2_CLK_EN_MASK, 1);
129662306a36Sopenharmony_ci			break;
129762306a36Sopenharmony_ci		case 3:
129862306a36Sopenharmony_ci			snd_soc_component_write_field(component,
129962306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
130062306a36Sopenharmony_ci				WCD938X_TXD3_MODE_MASK, mode);
130162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
130262306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
130362306a36Sopenharmony_ci				WCD938X_TXD3_CLK_EN_MASK, 1);
130462306a36Sopenharmony_ci			break;
130562306a36Sopenharmony_ci		default:
130662306a36Sopenharmony_ci			break;
130762306a36Sopenharmony_ci		}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci		wcd938x_tx_channel_config(component, w->shift, 0);
131062306a36Sopenharmony_ci		break;
131162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
131262306a36Sopenharmony_ci		switch (w->shift) {
131362306a36Sopenharmony_ci		case 0:
131462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
131562306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
131662306a36Sopenharmony_ci				WCD938X_TXD0_MODE_MASK, 0);
131762306a36Sopenharmony_ci			snd_soc_component_write_field(component,
131862306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
131962306a36Sopenharmony_ci				WCD938X_TXD0_CLK_EN_MASK, 0);
132062306a36Sopenharmony_ci			break;
132162306a36Sopenharmony_ci		case 1:
132262306a36Sopenharmony_ci			snd_soc_component_write_field(component,
132362306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
132462306a36Sopenharmony_ci				WCD938X_TXD1_MODE_MASK, 0);
132562306a36Sopenharmony_ci			snd_soc_component_write_field(component,
132662306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
132762306a36Sopenharmony_ci				WCD938X_TXD1_CLK_EN_MASK, 0);
132862306a36Sopenharmony_ci			break;
132962306a36Sopenharmony_ci		case 2:
133062306a36Sopenharmony_ci			snd_soc_component_write_field(component,
133162306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
133262306a36Sopenharmony_ci				WCD938X_TXD2_MODE_MASK, 0);
133362306a36Sopenharmony_ci			snd_soc_component_write_field(component,
133462306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
133562306a36Sopenharmony_ci				WCD938X_TXD2_CLK_EN_MASK, 0);
133662306a36Sopenharmony_ci			break;
133762306a36Sopenharmony_ci		case 3:
133862306a36Sopenharmony_ci			snd_soc_component_write_field(component,
133962306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
134062306a36Sopenharmony_ci				WCD938X_TXD3_MODE_MASK, 0);
134162306a36Sopenharmony_ci			snd_soc_component_write_field(component,
134262306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
134362306a36Sopenharmony_ci				WCD938X_TXD3_CLK_EN_MASK, 0);
134462306a36Sopenharmony_ci			break;
134562306a36Sopenharmony_ci		default:
134662306a36Sopenharmony_ci			break;
134762306a36Sopenharmony_ci		}
134862306a36Sopenharmony_ci		snd_soc_component_write_field(component,
134962306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
135062306a36Sopenharmony_ci				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 0);
135162306a36Sopenharmony_ci		break;
135262306a36Sopenharmony_ci	}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	return 0;
135562306a36Sopenharmony_ci}
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_cistatic int wcd938x_micbias_control(struct snd_soc_component *component,
135862306a36Sopenharmony_ci				   int micb_num, int req, bool is_dapm)
135962306a36Sopenharmony_ci{
136062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
136162306a36Sopenharmony_ci	int micb_index = micb_num - 1;
136262306a36Sopenharmony_ci	u16 micb_reg;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	switch (micb_num) {
136562306a36Sopenharmony_ci	case MIC_BIAS_1:
136662306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB1;
136762306a36Sopenharmony_ci		break;
136862306a36Sopenharmony_ci	case MIC_BIAS_2:
136962306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB2;
137062306a36Sopenharmony_ci		break;
137162306a36Sopenharmony_ci	case MIC_BIAS_3:
137262306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB3;
137362306a36Sopenharmony_ci		break;
137462306a36Sopenharmony_ci	case MIC_BIAS_4:
137562306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB4;
137662306a36Sopenharmony_ci		break;
137762306a36Sopenharmony_ci	default:
137862306a36Sopenharmony_ci		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
137962306a36Sopenharmony_ci			__func__, micb_num);
138062306a36Sopenharmony_ci		return -EINVAL;
138162306a36Sopenharmony_ci	}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	switch (req) {
138462306a36Sopenharmony_ci	case MICB_PULLUP_ENABLE:
138562306a36Sopenharmony_ci		wcd938x->pullup_ref[micb_index]++;
138662306a36Sopenharmony_ci		if ((wcd938x->pullup_ref[micb_index] == 1) &&
138762306a36Sopenharmony_ci		    (wcd938x->micb_ref[micb_index] == 0))
138862306a36Sopenharmony_ci			snd_soc_component_write_field(component, micb_reg,
138962306a36Sopenharmony_ci						      WCD938X_MICB_EN_MASK,
139062306a36Sopenharmony_ci						      WCD938X_MICB_PULL_UP);
139162306a36Sopenharmony_ci		break;
139262306a36Sopenharmony_ci	case MICB_PULLUP_DISABLE:
139362306a36Sopenharmony_ci		if (wcd938x->pullup_ref[micb_index] > 0)
139462306a36Sopenharmony_ci			wcd938x->pullup_ref[micb_index]--;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci		if ((wcd938x->pullup_ref[micb_index] == 0) &&
139762306a36Sopenharmony_ci		    (wcd938x->micb_ref[micb_index] == 0))
139862306a36Sopenharmony_ci			snd_soc_component_write_field(component, micb_reg,
139962306a36Sopenharmony_ci						      WCD938X_MICB_EN_MASK, 0);
140062306a36Sopenharmony_ci		break;
140162306a36Sopenharmony_ci	case MICB_ENABLE:
140262306a36Sopenharmony_ci		wcd938x->micb_ref[micb_index]++;
140362306a36Sopenharmony_ci		if (wcd938x->micb_ref[micb_index] == 1) {
140462306a36Sopenharmony_ci			snd_soc_component_write_field(component,
140562306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
140662306a36Sopenharmony_ci				WCD938X_TX_CLK_EN_MASK, 0xF);
140762306a36Sopenharmony_ci			snd_soc_component_write_field(component,
140862306a36Sopenharmony_ci				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
140962306a36Sopenharmony_ci				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);
141062306a36Sopenharmony_ci			snd_soc_component_write_field(component,
141162306a36Sopenharmony_ci			       WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL,
141262306a36Sopenharmony_ci			       WCD938X_TX_SC_CLK_EN_MASK, 1);
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci			snd_soc_component_write_field(component, micb_reg,
141562306a36Sopenharmony_ci						      WCD938X_MICB_EN_MASK,
141662306a36Sopenharmony_ci						      WCD938X_MICB_ENABLE);
141762306a36Sopenharmony_ci			if (micb_num  == MIC_BIAS_2)
141862306a36Sopenharmony_ci				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
141962306a36Sopenharmony_ci						      WCD_EVENT_POST_MICBIAS_2_ON);
142062306a36Sopenharmony_ci		}
142162306a36Sopenharmony_ci		if (micb_num  == MIC_BIAS_2 && is_dapm)
142262306a36Sopenharmony_ci			wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
142362306a36Sopenharmony_ci					      WCD_EVENT_POST_DAPM_MICBIAS_2_ON);
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci		break;
142762306a36Sopenharmony_ci	case MICB_DISABLE:
142862306a36Sopenharmony_ci		if (wcd938x->micb_ref[micb_index] > 0)
142962306a36Sopenharmony_ci			wcd938x->micb_ref[micb_index]--;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci		if ((wcd938x->micb_ref[micb_index] == 0) &&
143262306a36Sopenharmony_ci		    (wcd938x->pullup_ref[micb_index] > 0))
143362306a36Sopenharmony_ci			snd_soc_component_write_field(component, micb_reg,
143462306a36Sopenharmony_ci						      WCD938X_MICB_EN_MASK,
143562306a36Sopenharmony_ci						      WCD938X_MICB_PULL_UP);
143662306a36Sopenharmony_ci		else if ((wcd938x->micb_ref[micb_index] == 0) &&
143762306a36Sopenharmony_ci			 (wcd938x->pullup_ref[micb_index] == 0)) {
143862306a36Sopenharmony_ci			if (micb_num  == MIC_BIAS_2)
143962306a36Sopenharmony_ci				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
144062306a36Sopenharmony_ci						      WCD_EVENT_PRE_MICBIAS_2_OFF);
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci			snd_soc_component_write_field(component, micb_reg,
144362306a36Sopenharmony_ci						      WCD938X_MICB_EN_MASK, 0);
144462306a36Sopenharmony_ci			if (micb_num  == MIC_BIAS_2)
144562306a36Sopenharmony_ci				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
144662306a36Sopenharmony_ci						      WCD_EVENT_POST_MICBIAS_2_OFF);
144762306a36Sopenharmony_ci		}
144862306a36Sopenharmony_ci		if (is_dapm && micb_num  == MIC_BIAS_2)
144962306a36Sopenharmony_ci			wcd_mbhc_event_notify(wcd938x->wcd_mbhc,
145062306a36Sopenharmony_ci					      WCD_EVENT_POST_DAPM_MICBIAS_2_OFF);
145162306a36Sopenharmony_ci		break;
145262306a36Sopenharmony_ci	}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	return 0;
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistatic int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
145862306a36Sopenharmony_ci					struct snd_kcontrol *kcontrol,
145962306a36Sopenharmony_ci					int event)
146062306a36Sopenharmony_ci{
146162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
146262306a36Sopenharmony_ci	int micb_num = w->shift;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	switch (event) {
146562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
146662306a36Sopenharmony_ci		wcd938x_micbias_control(component, micb_num, MICB_ENABLE, true);
146762306a36Sopenharmony_ci		break;
146862306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
146962306a36Sopenharmony_ci		/* 1 msec delay as per HW requirement */
147062306a36Sopenharmony_ci		usleep_range(1000, 1100);
147162306a36Sopenharmony_ci		break;
147262306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
147362306a36Sopenharmony_ci		wcd938x_micbias_control(component, micb_num, MICB_DISABLE, true);
147462306a36Sopenharmony_ci		break;
147562306a36Sopenharmony_ci	}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	return 0;
147862306a36Sopenharmony_ci}
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_cistatic int wcd938x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
148162306a36Sopenharmony_ci					       struct snd_kcontrol *kcontrol,
148262306a36Sopenharmony_ci					       int event)
148362306a36Sopenharmony_ci{
148462306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
148562306a36Sopenharmony_ci	int micb_num = w->shift;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	switch (event) {
148862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
148962306a36Sopenharmony_ci		wcd938x_micbias_control(component, micb_num,
149062306a36Sopenharmony_ci					MICB_PULLUP_ENABLE, true);
149162306a36Sopenharmony_ci		break;
149262306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
149362306a36Sopenharmony_ci		/* 1 msec delay as per HW requirement */
149462306a36Sopenharmony_ci		usleep_range(1000, 1100);
149562306a36Sopenharmony_ci		break;
149662306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
149762306a36Sopenharmony_ci		wcd938x_micbias_control(component, micb_num,
149862306a36Sopenharmony_ci					MICB_PULLUP_DISABLE, true);
149962306a36Sopenharmony_ci		break;
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	return 0;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_cistatic int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
150662306a36Sopenharmony_ci			       struct snd_ctl_elem_value *ucontrol)
150762306a36Sopenharmony_ci{
150862306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
150962306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
151062306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
151162306a36Sopenharmony_ci	int path = e->shift_l;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	ucontrol->value.enumerated.item[0] = wcd938x->tx_mode[path];
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	return 0;
151662306a36Sopenharmony_ci}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_cistatic int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
151962306a36Sopenharmony_ci			       struct snd_ctl_elem_value *ucontrol)
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
152262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
152362306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
152462306a36Sopenharmony_ci	int path = e->shift_l;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0])
152762306a36Sopenharmony_ci		return 0;
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci	wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0];
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	return 1;
153262306a36Sopenharmony_ci}
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_cistatic int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
153562306a36Sopenharmony_ci				 struct snd_ctl_elem_value *ucontrol)
153662306a36Sopenharmony_ci{
153762306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
153862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	ucontrol->value.enumerated.item[0] = wcd938x->hph_mode;
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	return 0;
154362306a36Sopenharmony_ci}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_cistatic int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
154662306a36Sopenharmony_ci				   struct snd_ctl_elem_value *ucontrol)
154762306a36Sopenharmony_ci{
154862306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
154962306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0])
155262306a36Sopenharmony_ci		return 0;
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	wcd938x->hph_mode = ucontrol->value.enumerated.item[0];
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	return 1;
155762306a36Sopenharmony_ci}
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_cistatic int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol,
156062306a36Sopenharmony_ci				   struct snd_ctl_elem_value *ucontrol)
156162306a36Sopenharmony_ci{
156262306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
156362306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	if (wcd938x->comp1_enable) {
156662306a36Sopenharmony_ci		dev_err(component->dev, "Can not set EAR PA Gain, compander1 is enabled\n");
156762306a36Sopenharmony_ci		return -EINVAL;
156862306a36Sopenharmony_ci	}
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,
157162306a36Sopenharmony_ci				      WCD938X_EAR_GAIN_MASK,
157262306a36Sopenharmony_ci				      ucontrol->value.integer.value[0]);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	return 1;
157562306a36Sopenharmony_ci}
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_cistatic int wcd938x_get_compander(struct snd_kcontrol *kcontrol,
157862306a36Sopenharmony_ci				 struct snd_ctl_elem_value *ucontrol)
157962306a36Sopenharmony_ci{
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
158262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
158362306a36Sopenharmony_ci	struct soc_mixer_control *mc;
158462306a36Sopenharmony_ci	bool hphr;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	mc = (struct soc_mixer_control *)(kcontrol->private_value);
158762306a36Sopenharmony_ci	hphr = mc->shift;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	if (hphr)
159062306a36Sopenharmony_ci		ucontrol->value.integer.value[0] = wcd938x->comp2_enable;
159162306a36Sopenharmony_ci	else
159262306a36Sopenharmony_ci		ucontrol->value.integer.value[0] = wcd938x->comp1_enable;
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	return 0;
159562306a36Sopenharmony_ci}
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_cistatic int wcd938x_set_compander(struct snd_kcontrol *kcontrol,
159862306a36Sopenharmony_ci				 struct snd_ctl_elem_value *ucontrol)
159962306a36Sopenharmony_ci{
160062306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
160162306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
160262306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd;
160362306a36Sopenharmony_ci	int value = ucontrol->value.integer.value[0];
160462306a36Sopenharmony_ci	int portidx;
160562306a36Sopenharmony_ci	struct soc_mixer_control *mc;
160662306a36Sopenharmony_ci	bool hphr;
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	mc = (struct soc_mixer_control *)(kcontrol->private_value);
160962306a36Sopenharmony_ci	hphr = mc->shift;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	wcd = wcd938x->sdw_priv[AIF1_PB];
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	if (hphr)
161462306a36Sopenharmony_ci		wcd938x->comp2_enable = value;
161562306a36Sopenharmony_ci	else
161662306a36Sopenharmony_ci		wcd938x->comp1_enable = value;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	portidx = wcd->ch_info[mc->reg].port_num;
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	if (value)
162162306a36Sopenharmony_ci		wcd938x_connect_port(wcd, portidx, mc->reg, true);
162262306a36Sopenharmony_ci	else
162362306a36Sopenharmony_ci		wcd938x_connect_port(wcd, portidx, mc->reg, false);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	return 1;
162662306a36Sopenharmony_ci}
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_cistatic int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol,
162962306a36Sopenharmony_ci			    struct snd_ctl_elem_value *ucontrol)
163062306a36Sopenharmony_ci{
163162306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
163262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = wcd938x->ldoh;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	return 0;
163762306a36Sopenharmony_ci}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_cistatic int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,
164062306a36Sopenharmony_ci			    struct snd_ctl_elem_value *ucontrol)
164162306a36Sopenharmony_ci{
164262306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
164362306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	if (wcd938x->ldoh == ucontrol->value.integer.value[0])
164662306a36Sopenharmony_ci		return 0;
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	wcd938x->ldoh = ucontrol->value.integer.value[0];
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	return 1;
165162306a36Sopenharmony_ci}
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_cistatic int wcd938x_bcs_get(struct snd_kcontrol *kcontrol,
165462306a36Sopenharmony_ci			   struct snd_ctl_elem_value *ucontrol)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
165762306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = wcd938x->bcs_dis;
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	return 0;
166262306a36Sopenharmony_ci}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_cistatic int wcd938x_bcs_put(struct snd_kcontrol *kcontrol,
166562306a36Sopenharmony_ci			   struct snd_ctl_elem_value *ucontrol)
166662306a36Sopenharmony_ci{
166762306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
166862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	if (wcd938x->bcs_dis == ucontrol->value.integer.value[0])
167162306a36Sopenharmony_ci		return 0;
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	wcd938x->bcs_dis = ucontrol->value.integer.value[0];
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	return 1;
167662306a36Sopenharmony_ci}
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_cistatic const char * const tx_mode_mux_text_wcd9380[] = {
167962306a36Sopenharmony_ci	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
168062306a36Sopenharmony_ci};
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_cistatic const char * const tx_mode_mux_text[] = {
168362306a36Sopenharmony_ci	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
168462306a36Sopenharmony_ci	"ADC_ULP1", "ADC_ULP2",
168562306a36Sopenharmony_ci};
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_cistatic const char * const rx_hph_mode_mux_text_wcd9380[] = {
168862306a36Sopenharmony_ci	"CLS_H_INVALID", "CLS_H_INVALID_1", "CLS_H_LP", "CLS_AB",
168962306a36Sopenharmony_ci	"CLS_H_LOHIFI", "CLS_H_ULP", "CLS_H_INVALID_2", "CLS_AB_LP",
169062306a36Sopenharmony_ci	"CLS_AB_LOHIFI",
169162306a36Sopenharmony_ci};
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_cistatic const char * const rx_hph_mode_mux_text[] = {
169462306a36Sopenharmony_ci	"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
169562306a36Sopenharmony_ci	"CLS_H_ULP", "CLS_AB_HIFI", "CLS_AB_LP", "CLS_AB_LOHIFI",
169662306a36Sopenharmony_ci};
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_cistatic const char * const adc2_mux_text[] = {
169962306a36Sopenharmony_ci	"INP2", "INP3"
170062306a36Sopenharmony_ci};
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_cistatic const char * const adc3_mux_text[] = {
170362306a36Sopenharmony_ci	"INP4", "INP6"
170462306a36Sopenharmony_ci};
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_cistatic const char * const adc4_mux_text[] = {
170762306a36Sopenharmony_ci	"INP5", "INP7"
170862306a36Sopenharmony_ci};
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_cistatic const char * const rdac3_mux_text[] = {
171162306a36Sopenharmony_ci	"RX1", "RX3"
171262306a36Sopenharmony_ci};
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_cistatic const char * const hdr12_mux_text[] = {
171562306a36Sopenharmony_ci	"NO_HDR12", "HDR12"
171662306a36Sopenharmony_ci};
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_cistatic const char * const hdr34_mux_text[] = {
171962306a36Sopenharmony_ci	"NO_HDR34", "HDR34"
172062306a36Sopenharmony_ci};
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_cistatic const struct soc_enum tx0_mode_enum_wcd9380 =
172362306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text_wcd9380),
172462306a36Sopenharmony_ci			tx_mode_mux_text_wcd9380);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_cistatic const struct soc_enum tx1_mode_enum_wcd9380 =
172762306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text_wcd9380),
172862306a36Sopenharmony_ci			tx_mode_mux_text_wcd9380);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_cistatic const struct soc_enum tx2_mode_enum_wcd9380 =
173162306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text_wcd9380),
173262306a36Sopenharmony_ci			tx_mode_mux_text_wcd9380);
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_cistatic const struct soc_enum tx3_mode_enum_wcd9380 =
173562306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text_wcd9380),
173662306a36Sopenharmony_ci			tx_mode_mux_text_wcd9380);
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cistatic const struct soc_enum tx0_mode_enum_wcd9385 =
173962306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text),
174062306a36Sopenharmony_ci			tx_mode_mux_text);
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_cistatic const struct soc_enum tx1_mode_enum_wcd9385 =
174362306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text),
174462306a36Sopenharmony_ci			tx_mode_mux_text);
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_cistatic const struct soc_enum tx2_mode_enum_wcd9385 =
174762306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text),
174862306a36Sopenharmony_ci			tx_mode_mux_text);
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_cistatic const struct soc_enum tx3_mode_enum_wcd9385 =
175162306a36Sopenharmony_ci	SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text),
175262306a36Sopenharmony_ci			tx_mode_mux_text);
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_cistatic const struct soc_enum rx_hph_mode_mux_enum_wcd9380 =
175562306a36Sopenharmony_ci		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text_wcd9380),
175662306a36Sopenharmony_ci				    rx_hph_mode_mux_text_wcd9380);
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_cistatic const struct soc_enum rx_hph_mode_mux_enum =
175962306a36Sopenharmony_ci		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
176062306a36Sopenharmony_ci				    rx_hph_mode_mux_text);
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_cistatic const struct soc_enum adc2_enum =
176362306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 7,
176462306a36Sopenharmony_ci				ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_cistatic const struct soc_enum adc3_enum =
176762306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 6,
176862306a36Sopenharmony_ci				ARRAY_SIZE(adc3_mux_text), adc3_mux_text);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_cistatic const struct soc_enum adc4_enum =
177162306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 5,
177262306a36Sopenharmony_ci				ARRAY_SIZE(adc4_mux_text), adc4_mux_text);
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_cistatic const struct soc_enum hdr12_enum =
177562306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 4,
177662306a36Sopenharmony_ci				ARRAY_SIZE(hdr12_mux_text), hdr12_mux_text);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_cistatic const struct soc_enum hdr34_enum =
177962306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 3,
178062306a36Sopenharmony_ci				ARRAY_SIZE(hdr34_mux_text), hdr34_mux_text);
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_cistatic const struct soc_enum rdac3_enum =
178362306a36Sopenharmony_ci		SOC_ENUM_SINGLE(WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0,
178462306a36Sopenharmony_ci				ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text);
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_cistatic const struct snd_kcontrol_new adc1_switch[] = {
178762306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
178862306a36Sopenharmony_ci};
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_cistatic const struct snd_kcontrol_new adc2_switch[] = {
179162306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
179262306a36Sopenharmony_ci};
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_cistatic const struct snd_kcontrol_new adc3_switch[] = {
179562306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
179662306a36Sopenharmony_ci};
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_cistatic const struct snd_kcontrol_new adc4_switch[] = {
179962306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
180062306a36Sopenharmony_ci};
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic1_switch[] = {
180362306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
180462306a36Sopenharmony_ci};
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic2_switch[] = {
180762306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
180862306a36Sopenharmony_ci};
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic3_switch[] = {
181162306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
181262306a36Sopenharmony_ci};
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic4_switch[] = {
181562306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
181662306a36Sopenharmony_ci};
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic5_switch[] = {
181962306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
182062306a36Sopenharmony_ci};
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic6_switch[] = {
182362306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
182462306a36Sopenharmony_ci};
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic7_switch[] = {
182762306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
182862306a36Sopenharmony_ci};
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_cistatic const struct snd_kcontrol_new dmic8_switch[] = {
183162306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
183262306a36Sopenharmony_ci};
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_cistatic const struct snd_kcontrol_new ear_rdac_switch[] = {
183562306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
183662306a36Sopenharmony_ci};
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_cistatic const struct snd_kcontrol_new aux_rdac_switch[] = {
183962306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
184062306a36Sopenharmony_ci};
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_cistatic const struct snd_kcontrol_new hphl_rdac_switch[] = {
184362306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
184462306a36Sopenharmony_ci};
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_cistatic const struct snd_kcontrol_new hphr_rdac_switch[] = {
184762306a36Sopenharmony_ci	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
184862306a36Sopenharmony_ci};
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_cistatic const struct snd_kcontrol_new tx_adc2_mux =
185162306a36Sopenharmony_ci	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_cistatic const struct snd_kcontrol_new tx_adc3_mux =
185462306a36Sopenharmony_ci	SOC_DAPM_ENUM("ADC3 MUX Mux", adc3_enum);
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_cistatic const struct snd_kcontrol_new tx_adc4_mux =
185762306a36Sopenharmony_ci	SOC_DAPM_ENUM("ADC4 MUX Mux", adc4_enum);
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_cistatic const struct snd_kcontrol_new tx_hdr12_mux =
186062306a36Sopenharmony_ci	SOC_DAPM_ENUM("HDR12 MUX Mux", hdr12_enum);
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_cistatic const struct snd_kcontrol_new tx_hdr34_mux =
186362306a36Sopenharmony_ci	SOC_DAPM_ENUM("HDR34 MUX Mux", hdr34_enum);
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_cistatic const struct snd_kcontrol_new rx_rdac3_mux =
186662306a36Sopenharmony_ci	SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum);
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_cistatic const struct snd_kcontrol_new wcd9380_snd_controls[] = {
186962306a36Sopenharmony_ci	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum_wcd9380,
187062306a36Sopenharmony_ci		     wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
187162306a36Sopenharmony_ci	SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9380,
187262306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
187362306a36Sopenharmony_ci	SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9380,
187462306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
187562306a36Sopenharmony_ci	SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9380,
187662306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
187762306a36Sopenharmony_ci	SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9380,
187862306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
187962306a36Sopenharmony_ci};
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_cistatic const struct snd_kcontrol_new wcd9385_snd_controls[] = {
188262306a36Sopenharmony_ci	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
188362306a36Sopenharmony_ci		     wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
188462306a36Sopenharmony_ci	SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9385,
188562306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
188662306a36Sopenharmony_ci	SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9385,
188762306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
188862306a36Sopenharmony_ci	SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9385,
188962306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
189062306a36Sopenharmony_ci	SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9385,
189162306a36Sopenharmony_ci		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),
189262306a36Sopenharmony_ci};
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_cistatic int wcd938x_get_swr_port(struct snd_kcontrol *kcontrol,
189562306a36Sopenharmony_ci			    struct snd_ctl_elem_value *ucontrol)
189662306a36Sopenharmony_ci{
189762306a36Sopenharmony_ci	struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
189862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp);
189962306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd;
190062306a36Sopenharmony_ci	struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;
190162306a36Sopenharmony_ci	int dai_id = mixer->shift;
190262306a36Sopenharmony_ci	int portidx, ch_idx = mixer->reg;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	wcd = wcd938x->sdw_priv[dai_id];
190662306a36Sopenharmony_ci	portidx = wcd->ch_info[ch_idx].port_num;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = wcd->port_enable[portidx];
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	return 0;
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol,
191462306a36Sopenharmony_ci			    struct snd_ctl_elem_value *ucontrol)
191562306a36Sopenharmony_ci{
191662306a36Sopenharmony_ci	struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
191762306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp);
191862306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd;
191962306a36Sopenharmony_ci	struct soc_mixer_control *mixer =
192062306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
192162306a36Sopenharmony_ci	int ch_idx = mixer->reg;
192262306a36Sopenharmony_ci	int portidx;
192362306a36Sopenharmony_ci	int dai_id = mixer->shift;
192462306a36Sopenharmony_ci	bool enable;
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	wcd = wcd938x->sdw_priv[dai_id];
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	portidx = wcd->ch_info[ch_idx].port_num;
192962306a36Sopenharmony_ci	if (ucontrol->value.integer.value[0])
193062306a36Sopenharmony_ci		enable = true;
193162306a36Sopenharmony_ci	else
193262306a36Sopenharmony_ci		enable = false;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	wcd->port_enable[portidx] = enable;
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	wcd938x_connect_port(wcd, portidx, ch_idx, enable);
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	return 1;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci}
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci/* MBHC related */
194362306a36Sopenharmony_cistatic void wcd938x_mbhc_clk_setup(struct snd_soc_component *component,
194462306a36Sopenharmony_ci				   bool enable)
194562306a36Sopenharmony_ci{
194662306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1,
194762306a36Sopenharmony_ci				      WCD938X_MBHC_CTL_RCO_EN_MASK, enable);
194862306a36Sopenharmony_ci}
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_cistatic void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component,
195162306a36Sopenharmony_ci					   bool enable)
195262306a36Sopenharmony_ci{
195362306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT,
195462306a36Sopenharmony_ci				      WCD938X_ANA_MBHC_BIAS_EN, enable);
195562306a36Sopenharmony_ci}
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_cistatic void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component,
195862306a36Sopenharmony_ci					 int *btn_low, int *btn_high,
195962306a36Sopenharmony_ci					 int num_btn, bool is_micbias)
196062306a36Sopenharmony_ci{
196162306a36Sopenharmony_ci	int i, vth;
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	if (num_btn > WCD_MBHC_DEF_BUTTONS) {
196462306a36Sopenharmony_ci		dev_err(component->dev, "%s: invalid number of buttons: %d\n",
196562306a36Sopenharmony_ci			__func__, num_btn);
196662306a36Sopenharmony_ci		return;
196762306a36Sopenharmony_ci	}
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci	for (i = 0; i < num_btn; i++) {
197062306a36Sopenharmony_ci		vth = ((btn_high[i] * 2) / 25) & 0x3F;
197162306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i,
197262306a36Sopenharmony_ci					   WCD938X_MBHC_BTN_VTH_MASK, vth);
197362306a36Sopenharmony_ci		dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",
197462306a36Sopenharmony_ci			__func__, i, btn_high[i], vth);
197562306a36Sopenharmony_ci	}
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_cistatic bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num)
197962306a36Sopenharmony_ci{
198062306a36Sopenharmony_ci	u8 val;
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	if (micb_num == MIC_BIAS_2) {
198362306a36Sopenharmony_ci		val = snd_soc_component_read_field(component,
198462306a36Sopenharmony_ci						   WCD938X_ANA_MICB2,
198562306a36Sopenharmony_ci						   WCD938X_ANA_MICB2_ENABLE_MASK);
198662306a36Sopenharmony_ci		if (val == WCD938X_MICB_ENABLE)
198762306a36Sopenharmony_ci			return true;
198862306a36Sopenharmony_ci	}
198962306a36Sopenharmony_ci	return false;
199062306a36Sopenharmony_ci}
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_cistatic void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component,
199362306a36Sopenharmony_ci							int pull_up_cur)
199462306a36Sopenharmony_ci{
199562306a36Sopenharmony_ci	/* Default pull up current to 2uA */
199662306a36Sopenharmony_ci	if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA)
199762306a36Sopenharmony_ci		pull_up_cur = HS_PULLUP_I_2P0_UA;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	snd_soc_component_write_field(component,
200062306a36Sopenharmony_ci				      WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,
200162306a36Sopenharmony_ci				      WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur);
200262306a36Sopenharmony_ci}
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_cistatic int wcd938x_mbhc_request_micbias(struct snd_soc_component *component,
200562306a36Sopenharmony_ci					int micb_num, int req)
200662306a36Sopenharmony_ci{
200762306a36Sopenharmony_ci	return wcd938x_micbias_control(component, micb_num, req, false);
200862306a36Sopenharmony_ci}
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_cistatic void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component,
201162306a36Sopenharmony_ci					   bool enable)
201262306a36Sopenharmony_ci{
201362306a36Sopenharmony_ci	if (enable) {
201462306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
201562306a36Sopenharmony_ci				    WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C);
201662306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
201762306a36Sopenharmony_ci				    WCD938X_RAMP_EN_MASK, 1);
201862306a36Sopenharmony_ci	} else {
201962306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
202062306a36Sopenharmony_ci				    WCD938X_RAMP_EN_MASK, 0);
202162306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,
202262306a36Sopenharmony_ci				    WCD938X_RAMP_SHIFT_CTRL_MASK, 0);
202362306a36Sopenharmony_ci	}
202462306a36Sopenharmony_ci}
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_cistatic int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)
202762306a36Sopenharmony_ci{
202862306a36Sopenharmony_ci	/* min micbias voltage is 1V and maximum is 2.85V */
202962306a36Sopenharmony_ci	if (micb_mv < 1000 || micb_mv > 2850)
203062306a36Sopenharmony_ci		return -EINVAL;
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	return (micb_mv - 1000) / 50;
203362306a36Sopenharmony_ci}
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_cistatic int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
203662306a36Sopenharmony_ci					    int req_volt, int micb_num)
203762306a36Sopenharmony_ci{
203862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x =  snd_soc_component_get_drvdata(component);
203962306a36Sopenharmony_ci	int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0;
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_ci	switch (micb_num) {
204262306a36Sopenharmony_ci	case MIC_BIAS_1:
204362306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB1;
204462306a36Sopenharmony_ci		break;
204562306a36Sopenharmony_ci	case MIC_BIAS_2:
204662306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB2;
204762306a36Sopenharmony_ci		break;
204862306a36Sopenharmony_ci	case MIC_BIAS_3:
204962306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB3;
205062306a36Sopenharmony_ci		break;
205162306a36Sopenharmony_ci	case MIC_BIAS_4:
205262306a36Sopenharmony_ci		micb_reg = WCD938X_ANA_MICB4;
205362306a36Sopenharmony_ci		break;
205462306a36Sopenharmony_ci	default:
205562306a36Sopenharmony_ci		return -EINVAL;
205662306a36Sopenharmony_ci	}
205762306a36Sopenharmony_ci	mutex_lock(&wcd938x->micb_lock);
205862306a36Sopenharmony_ci	/*
205962306a36Sopenharmony_ci	 * If requested micbias voltage is same as current micbias
206062306a36Sopenharmony_ci	 * voltage, then just return. Otherwise, adjust voltage as
206162306a36Sopenharmony_ci	 * per requested value. If micbias is already enabled, then
206262306a36Sopenharmony_ci	 * to avoid slow micbias ramp-up or down enable pull-up
206362306a36Sopenharmony_ci	 * momentarily, change the micbias value and then re-enable
206462306a36Sopenharmony_ci	 * micbias.
206562306a36Sopenharmony_ci	 */
206662306a36Sopenharmony_ci	micb_en = snd_soc_component_read_field(component, micb_reg,
206762306a36Sopenharmony_ci						WCD938X_MICB_EN_MASK);
206862306a36Sopenharmony_ci	cur_vout_ctl = snd_soc_component_read_field(component, micb_reg,
206962306a36Sopenharmony_ci						    WCD938X_MICB_VOUT_MASK);
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt);
207262306a36Sopenharmony_ci	if (req_vout_ctl < 0) {
207362306a36Sopenharmony_ci		ret = -EINVAL;
207462306a36Sopenharmony_ci		goto exit;
207562306a36Sopenharmony_ci	}
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	if (cur_vout_ctl == req_vout_ctl) {
207862306a36Sopenharmony_ci		ret = 0;
207962306a36Sopenharmony_ci		goto exit;
208062306a36Sopenharmony_ci	}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_ci	if (micb_en == WCD938X_MICB_ENABLE)
208362306a36Sopenharmony_ci		snd_soc_component_write_field(component, micb_reg,
208462306a36Sopenharmony_ci					      WCD938X_MICB_EN_MASK,
208562306a36Sopenharmony_ci					      WCD938X_MICB_PULL_UP);
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	snd_soc_component_write_field(component, micb_reg,
208862306a36Sopenharmony_ci				      WCD938X_MICB_VOUT_MASK,
208962306a36Sopenharmony_ci				      req_vout_ctl);
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	if (micb_en == WCD938X_MICB_ENABLE) {
209262306a36Sopenharmony_ci		snd_soc_component_write_field(component, micb_reg,
209362306a36Sopenharmony_ci					      WCD938X_MICB_EN_MASK,
209462306a36Sopenharmony_ci					      WCD938X_MICB_ENABLE);
209562306a36Sopenharmony_ci		/*
209662306a36Sopenharmony_ci		 * Add 2ms delay as per HW requirement after enabling
209762306a36Sopenharmony_ci		 * micbias
209862306a36Sopenharmony_ci		 */
209962306a36Sopenharmony_ci		usleep_range(2000, 2100);
210062306a36Sopenharmony_ci	}
210162306a36Sopenharmony_ciexit:
210262306a36Sopenharmony_ci	mutex_unlock(&wcd938x->micb_lock);
210362306a36Sopenharmony_ci	return ret;
210462306a36Sopenharmony_ci}
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_cistatic int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component,
210762306a36Sopenharmony_ci						int micb_num, bool req_en)
210862306a36Sopenharmony_ci{
210962306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
211062306a36Sopenharmony_ci	int micb_mv;
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	if (micb_num != MIC_BIAS_2)
211362306a36Sopenharmony_ci		return -EINVAL;
211462306a36Sopenharmony_ci	/*
211562306a36Sopenharmony_ci	 * If device tree micbias level is already above the minimum
211662306a36Sopenharmony_ci	 * voltage needed to detect threshold microphone, then do
211762306a36Sopenharmony_ci	 * not change the micbias, just return.
211862306a36Sopenharmony_ci	 */
211962306a36Sopenharmony_ci	if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)
212062306a36Sopenharmony_ci		return 0;
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv;
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
212562306a36Sopenharmony_ci}
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_cistatic void wcd938x_mbhc_get_result_params(struct snd_soc_component *component,
212862306a36Sopenharmony_ci						s16 *d1_a, u16 noff,
212962306a36Sopenharmony_ci						int32_t *zdet)
213062306a36Sopenharmony_ci{
213162306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
213262306a36Sopenharmony_ci	int i;
213362306a36Sopenharmony_ci	int val, val1;
213462306a36Sopenharmony_ci	s16 c1;
213562306a36Sopenharmony_ci	s32 x1, d1;
213662306a36Sopenharmony_ci	int32_t denom;
213762306a36Sopenharmony_ci	static const int minCode_param[] = {
213862306a36Sopenharmony_ci		3277, 1639, 820, 410, 205, 103, 52, 26
213962306a36Sopenharmony_ci	};
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20);
214262306a36Sopenharmony_ci	for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) {
214362306a36Sopenharmony_ci		regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val);
214462306a36Sopenharmony_ci		if (val & 0x80)
214562306a36Sopenharmony_ci			break;
214662306a36Sopenharmony_ci	}
214762306a36Sopenharmony_ci	val = val << 0x8;
214862306a36Sopenharmony_ci	regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1);
214962306a36Sopenharmony_ci	val |= val1;
215062306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00);
215162306a36Sopenharmony_ci	x1 = WCD938X_MBHC_GET_X1(val);
215262306a36Sopenharmony_ci	c1 = WCD938X_MBHC_GET_C1(val);
215362306a36Sopenharmony_ci	/* If ramp is not complete, give additional 5ms */
215462306a36Sopenharmony_ci	if ((c1 < 2) && x1)
215562306a36Sopenharmony_ci		usleep_range(5000, 5050);
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	if (!c1 || !x1) {
215862306a36Sopenharmony_ci		dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n",
215962306a36Sopenharmony_ci			c1, x1);
216062306a36Sopenharmony_ci		goto ramp_down;
216162306a36Sopenharmony_ci	}
216262306a36Sopenharmony_ci	d1 = d1_a[c1];
216362306a36Sopenharmony_ci	denom = (x1 * d1) - (1 << (14 - noff));
216462306a36Sopenharmony_ci	if (denom > 0)
216562306a36Sopenharmony_ci		*zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom;
216662306a36Sopenharmony_ci	else if (x1 < minCode_param[noff])
216762306a36Sopenharmony_ci		*zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n",
217062306a36Sopenharmony_ci		__func__, d1, c1, x1, *zdet);
217162306a36Sopenharmony_ciramp_down:
217262306a36Sopenharmony_ci	i = 0;
217362306a36Sopenharmony_ci	while (x1) {
217462306a36Sopenharmony_ci		regmap_read(wcd938x->regmap,
217562306a36Sopenharmony_ci				 WCD938X_ANA_MBHC_RESULT_1, &val);
217662306a36Sopenharmony_ci		regmap_read(wcd938x->regmap,
217762306a36Sopenharmony_ci				 WCD938X_ANA_MBHC_RESULT_2, &val1);
217862306a36Sopenharmony_ci		val = val << 0x08;
217962306a36Sopenharmony_ci		val |= val1;
218062306a36Sopenharmony_ci		x1 = WCD938X_MBHC_GET_X1(val);
218162306a36Sopenharmony_ci		i++;
218262306a36Sopenharmony_ci		if (i == WCD938X_ZDET_NUM_MEASUREMENTS)
218362306a36Sopenharmony_ci			break;
218462306a36Sopenharmony_ci	}
218562306a36Sopenharmony_ci}
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_cistatic void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
218862306a36Sopenharmony_ci				 struct wcd938x_mbhc_zdet_param *zdet_param,
218962306a36Sopenharmony_ci				 int32_t *zl, int32_t *zr, s16 *d1_a)
219062306a36Sopenharmony_ci{
219162306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
219262306a36Sopenharmony_ci	int32_t zdet = 0;
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
219562306a36Sopenharmony_ci				WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl);
219662306a36Sopenharmony_ci	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5,
219762306a36Sopenharmony_ci				    WCD938X_VTH_MASK, zdet_param->btn5);
219862306a36Sopenharmony_ci	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6,
219962306a36Sopenharmony_ci				      WCD938X_VTH_MASK, zdet_param->btn6);
220062306a36Sopenharmony_ci	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7,
220162306a36Sopenharmony_ci				     WCD938X_VTH_MASK, zdet_param->btn7);
220262306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,
220362306a36Sopenharmony_ci				WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff);
220462306a36Sopenharmony_ci	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL,
220562306a36Sopenharmony_ci				0x0F, zdet_param->nshift);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	if (!zl)
220862306a36Sopenharmony_ci		goto z_right;
220962306a36Sopenharmony_ci	/* Start impedance measurement for HPH_L */
221062306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
221162306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
221262306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",
221362306a36Sopenharmony_ci		__func__, zdet_param->noff);
221462306a36Sopenharmony_ci	wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
221562306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
221662306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_ci	*zl = zdet;
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ciz_right:
222162306a36Sopenharmony_ci	if (!zr)
222262306a36Sopenharmony_ci		return;
222362306a36Sopenharmony_ci	/* Start impedance measurement for HPH_R */
222462306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
222562306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
222662306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",
222762306a36Sopenharmony_ci		__func__, zdet_param->noff);
222862306a36Sopenharmony_ci	wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
222962306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
223062306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_ci	*zr = zdet;
223362306a36Sopenharmony_ci}
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_cistatic void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
223662306a36Sopenharmony_ci					int32_t *z_val, int flag_l_r)
223762306a36Sopenharmony_ci{
223862306a36Sopenharmony_ci	s16 q1;
223962306a36Sopenharmony_ci	int q1_cal;
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	if (*z_val < (WCD938X_ZDET_VAL_400/1000))
224262306a36Sopenharmony_ci		q1 = snd_soc_component_read(component,
224362306a36Sopenharmony_ci			WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));
224462306a36Sopenharmony_ci	else
224562306a36Sopenharmony_ci		q1 = snd_soc_component_read(component,
224662306a36Sopenharmony_ci			WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r));
224762306a36Sopenharmony_ci	if (q1 & 0x80)
224862306a36Sopenharmony_ci		q1_cal = (10000 - ((q1 & 0x7F) * 25));
224962306a36Sopenharmony_ci	else
225062306a36Sopenharmony_ci		q1_cal = (10000 + (q1 * 25));
225162306a36Sopenharmony_ci	if (q1_cal > 0)
225262306a36Sopenharmony_ci		*z_val = ((*z_val) * 10000) / q1_cal;
225362306a36Sopenharmony_ci}
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_cistatic void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component,
225662306a36Sopenharmony_ci					    uint32_t *zl, uint32_t *zr)
225762306a36Sopenharmony_ci{
225862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
225962306a36Sopenharmony_ci	s16 reg0, reg1, reg2, reg3, reg4;
226062306a36Sopenharmony_ci	int32_t z1L, z1R, z1Ls;
226162306a36Sopenharmony_ci	int zMono, z_diff1, z_diff2;
226262306a36Sopenharmony_ci	bool is_fsm_disable = false;
226362306a36Sopenharmony_ci	struct wcd938x_mbhc_zdet_param zdet_param[] = {
226462306a36Sopenharmony_ci		{4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */
226562306a36Sopenharmony_ci		{2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */
226662306a36Sopenharmony_ci		{1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */
226762306a36Sopenharmony_ci		{1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */
226862306a36Sopenharmony_ci	};
226962306a36Sopenharmony_ci	struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL;
227062306a36Sopenharmony_ci	s16 d1_a[][4] = {
227162306a36Sopenharmony_ci		{0, 30, 90, 30},
227262306a36Sopenharmony_ci		{0, 30, 30, 5},
227362306a36Sopenharmony_ci		{0, 30, 30, 5},
227462306a36Sopenharmony_ci		{0, 30, 30, 5},
227562306a36Sopenharmony_ci	};
227662306a36Sopenharmony_ci	s16 *d1 = NULL;
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5);
227962306a36Sopenharmony_ci	reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6);
228062306a36Sopenharmony_ci	reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7);
228162306a36Sopenharmony_ci	reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK);
228262306a36Sopenharmony_ci	reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL);
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci	if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) {
228562306a36Sopenharmony_ci		is_fsm_disable = true;
228662306a36Sopenharmony_ci		regmap_update_bits(wcd938x->regmap,
228762306a36Sopenharmony_ci				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x00);
228862306a36Sopenharmony_ci	}
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci	/* For NO-jack, disable L_DET_EN before Z-det measurements */
229162306a36Sopenharmony_ci	if (wcd938x->mbhc_cfg.hphl_swh)
229262306a36Sopenharmony_ci		regmap_update_bits(wcd938x->regmap,
229362306a36Sopenharmony_ci				   WCD938X_ANA_MBHC_MECH, 0x80, 0x00);
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	/* Turn off 100k pull down on HPHL */
229662306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
229762306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_MECH, 0x01, 0x00);
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci	/* Disable surge protection before impedance detection.
230062306a36Sopenharmony_ci	 * This is done to give correct value for high impedance.
230162306a36Sopenharmony_ci	 */
230262306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
230362306a36Sopenharmony_ci			   WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00);
230462306a36Sopenharmony_ci	/* 1ms delay needed after disable surge protection */
230562306a36Sopenharmony_ci	usleep_range(1000, 1010);
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	/* First get impedance on Left */
230862306a36Sopenharmony_ci	d1 = d1_a[1];
230962306a36Sopenharmony_ci	zdet_param_ptr = &zdet_param[1];
231062306a36Sopenharmony_ci	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci	if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))
231362306a36Sopenharmony_ci		goto left_ch_impedance;
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci	/* Second ramp for left ch */
231662306a36Sopenharmony_ci	if (z1L < WCD938X_ZDET_VAL_32) {
231762306a36Sopenharmony_ci		zdet_param_ptr = &zdet_param[0];
231862306a36Sopenharmony_ci		d1 = d1_a[0];
231962306a36Sopenharmony_ci	} else if ((z1L > WCD938X_ZDET_VAL_400) &&
232062306a36Sopenharmony_ci		  (z1L <= WCD938X_ZDET_VAL_1200)) {
232162306a36Sopenharmony_ci		zdet_param_ptr = &zdet_param[2];
232262306a36Sopenharmony_ci		d1 = d1_a[2];
232362306a36Sopenharmony_ci	} else if (z1L > WCD938X_ZDET_VAL_1200) {
232462306a36Sopenharmony_ci		zdet_param_ptr = &zdet_param[3];
232562306a36Sopenharmony_ci		d1 = d1_a[3];
232662306a36Sopenharmony_ci	}
232762306a36Sopenharmony_ci	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_cileft_ch_impedance:
233062306a36Sopenharmony_ci	if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
233162306a36Sopenharmony_ci		(z1L > WCD938X_ZDET_VAL_100K)) {
233262306a36Sopenharmony_ci		*zl = WCD938X_ZDET_FLOATING_IMPEDANCE;
233362306a36Sopenharmony_ci		zdet_param_ptr = &zdet_param[1];
233462306a36Sopenharmony_ci		d1 = d1_a[1];
233562306a36Sopenharmony_ci	} else {
233662306a36Sopenharmony_ci		*zl = z1L/1000;
233762306a36Sopenharmony_ci		wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0);
233862306a36Sopenharmony_ci	}
233962306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
234062306a36Sopenharmony_ci		__func__, *zl);
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_ci	/* Start of right impedance ramp and calculation */
234362306a36Sopenharmony_ci	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
234462306a36Sopenharmony_ci	if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {
234562306a36Sopenharmony_ci		if (((z1R > WCD938X_ZDET_VAL_1200) &&
234662306a36Sopenharmony_ci			(zdet_param_ptr->noff == 0x6)) ||
234762306a36Sopenharmony_ci			((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE))
234862306a36Sopenharmony_ci			goto right_ch_impedance;
234962306a36Sopenharmony_ci		/* Second ramp for right ch */
235062306a36Sopenharmony_ci		if (z1R < WCD938X_ZDET_VAL_32) {
235162306a36Sopenharmony_ci			zdet_param_ptr = &zdet_param[0];
235262306a36Sopenharmony_ci			d1 = d1_a[0];
235362306a36Sopenharmony_ci		} else if ((z1R > WCD938X_ZDET_VAL_400) &&
235462306a36Sopenharmony_ci			(z1R <= WCD938X_ZDET_VAL_1200)) {
235562306a36Sopenharmony_ci			zdet_param_ptr = &zdet_param[2];
235662306a36Sopenharmony_ci			d1 = d1_a[2];
235762306a36Sopenharmony_ci		} else if (z1R > WCD938X_ZDET_VAL_1200) {
235862306a36Sopenharmony_ci			zdet_param_ptr = &zdet_param[3];
235962306a36Sopenharmony_ci			d1 = d1_a[3];
236062306a36Sopenharmony_ci		}
236162306a36Sopenharmony_ci		wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);
236262306a36Sopenharmony_ci	}
236362306a36Sopenharmony_ciright_ch_impedance:
236462306a36Sopenharmony_ci	if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
236562306a36Sopenharmony_ci		(z1R > WCD938X_ZDET_VAL_100K)) {
236662306a36Sopenharmony_ci		*zr = WCD938X_ZDET_FLOATING_IMPEDANCE;
236762306a36Sopenharmony_ci	} else {
236862306a36Sopenharmony_ci		*zr = z1R/1000;
236962306a36Sopenharmony_ci		wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1);
237062306a36Sopenharmony_ci	}
237162306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
237262306a36Sopenharmony_ci		__func__, *zr);
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	/* Mono/stereo detection */
237562306a36Sopenharmony_ci	if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) &&
237662306a36Sopenharmony_ci		(*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) {
237762306a36Sopenharmony_ci		dev_dbg(component->dev,
237862306a36Sopenharmony_ci			"%s: plug type is invalid or extension cable\n",
237962306a36Sopenharmony_ci			__func__);
238062306a36Sopenharmony_ci		goto zdet_complete;
238162306a36Sopenharmony_ci	}
238262306a36Sopenharmony_ci	if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
238362306a36Sopenharmony_ci	    (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) ||
238462306a36Sopenharmony_ci	    ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||
238562306a36Sopenharmony_ci	    ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {
238662306a36Sopenharmony_ci		dev_dbg(component->dev,
238762306a36Sopenharmony_ci			"%s: Mono plug type with one ch floating or shorted to GND\n",
238862306a36Sopenharmony_ci			__func__);
238962306a36Sopenharmony_ci		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
239062306a36Sopenharmony_ci		goto zdet_complete;
239162306a36Sopenharmony_ci	}
239262306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
239362306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_OVR_MASK, 1);
239462306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
239562306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_R_MASK, 1);
239662306a36Sopenharmony_ci	if (*zl < (WCD938X_ZDET_VAL_32/1000))
239762306a36Sopenharmony_ci		wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);
239862306a36Sopenharmony_ci	else
239962306a36Sopenharmony_ci		wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);
240062306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
240162306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_R_MASK, 0);
240262306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,
240362306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_OVR_MASK, 0);
240462306a36Sopenharmony_ci	z1Ls /= 1000;
240562306a36Sopenharmony_ci	wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);
240662306a36Sopenharmony_ci	/* Parallel of left Z and 9 ohm pull down resistor */
240762306a36Sopenharmony_ci	zMono = ((*zl) * 9) / ((*zl) + 9);
240862306a36Sopenharmony_ci	z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);
240962306a36Sopenharmony_ci	z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));
241062306a36Sopenharmony_ci	if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {
241162306a36Sopenharmony_ci		dev_dbg(component->dev, "%s: stereo plug type detected\n",
241262306a36Sopenharmony_ci			__func__);
241362306a36Sopenharmony_ci		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO);
241462306a36Sopenharmony_ci	} else {
241562306a36Sopenharmony_ci		dev_dbg(component->dev, "%s: MONO plug type detected\n",
241662306a36Sopenharmony_ci			__func__);
241762306a36Sopenharmony_ci		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);
241862306a36Sopenharmony_ci	}
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	/* Enable surge protection again after impedance detection */
242162306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
242262306a36Sopenharmony_ci			   WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);
242362306a36Sopenharmony_cizdet_complete:
242462306a36Sopenharmony_ci	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0);
242562306a36Sopenharmony_ci	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1);
242662306a36Sopenharmony_ci	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2);
242762306a36Sopenharmony_ci	/* Turn on 100k pull down on HPHL */
242862306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap,
242962306a36Sopenharmony_ci			   WCD938X_ANA_MBHC_MECH, 0x01, 0x01);
243062306a36Sopenharmony_ci
243162306a36Sopenharmony_ci	/* For NO-jack, re-enable L_DET_EN after Z-det measurements */
243262306a36Sopenharmony_ci	if (wcd938x->mbhc_cfg.hphl_swh)
243362306a36Sopenharmony_ci		regmap_update_bits(wcd938x->regmap,
243462306a36Sopenharmony_ci				   WCD938X_ANA_MBHC_MECH, 0x80, 0x80);
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4);
243762306a36Sopenharmony_ci	snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3);
243862306a36Sopenharmony_ci	if (is_fsm_disable)
243962306a36Sopenharmony_ci		regmap_update_bits(wcd938x->regmap,
244062306a36Sopenharmony_ci				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x80);
244162306a36Sopenharmony_ci}
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_cistatic void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component,
244462306a36Sopenharmony_ci			bool enable)
244562306a36Sopenharmony_ci{
244662306a36Sopenharmony_ci	if (enable) {
244762306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
244862306a36Sopenharmony_ci					      WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1);
244962306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
245062306a36Sopenharmony_ci					      WCD938X_MBHC_GND_DET_EN_MASK, 1);
245162306a36Sopenharmony_ci	} else {
245262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
245362306a36Sopenharmony_ci					      WCD938X_MBHC_GND_DET_EN_MASK, 0);
245462306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,
245562306a36Sopenharmony_ci					      WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0);
245662306a36Sopenharmony_ci	}
245762306a36Sopenharmony_ci}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_cistatic void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,
246062306a36Sopenharmony_ci					  bool enable)
246162306a36Sopenharmony_ci{
246262306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
246362306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_R_MASK, enable);
246462306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,
246562306a36Sopenharmony_ci				      WCD938X_HPHPA_GND_L_MASK, enable);
246662306a36Sopenharmony_ci}
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_cistatic void wcd938x_mbhc_moisture_config(struct snd_soc_component *component)
246962306a36Sopenharmony_ci{
247062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci	if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
247362306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
247462306a36Sopenharmony_ci				    WCD938X_M_RTH_CTL_MASK, R_OFF);
247562306a36Sopenharmony_ci		return;
247662306a36Sopenharmony_ci	}
247762306a36Sopenharmony_ci
247862306a36Sopenharmony_ci	/* Do not enable moisture detection if jack type is NC */
247962306a36Sopenharmony_ci	if (!wcd938x->mbhc_cfg.hphl_swh) {
248062306a36Sopenharmony_ci		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
248162306a36Sopenharmony_ci			__func__);
248262306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
248362306a36Sopenharmony_ci				    WCD938X_M_RTH_CTL_MASK, R_OFF);
248462306a36Sopenharmony_ci		return;
248562306a36Sopenharmony_ci	}
248662306a36Sopenharmony_ci
248762306a36Sopenharmony_ci	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
248862306a36Sopenharmony_ci			    WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
248962306a36Sopenharmony_ci}
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_cistatic void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable)
249262306a36Sopenharmony_ci{
249362306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci	if (enable)
249662306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
249762306a36Sopenharmony_ci					WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);
249862306a36Sopenharmony_ci	else
249962306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
250062306a36Sopenharmony_ci				    WCD938X_M_RTH_CTL_MASK, R_OFF);
250162306a36Sopenharmony_ci}
250262306a36Sopenharmony_ci
250362306a36Sopenharmony_cistatic bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component)
250462306a36Sopenharmony_ci{
250562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
250662306a36Sopenharmony_ci	bool ret = false;
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci	if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {
250962306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
251062306a36Sopenharmony_ci				    WCD938X_M_RTH_CTL_MASK, R_OFF);
251162306a36Sopenharmony_ci		goto done;
251262306a36Sopenharmony_ci	}
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci	/* Do not enable moisture detection if jack type is NC */
251562306a36Sopenharmony_ci	if (!wcd938x->mbhc_cfg.hphl_swh) {
251662306a36Sopenharmony_ci		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",
251762306a36Sopenharmony_ci			__func__);
251862306a36Sopenharmony_ci		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,
251962306a36Sopenharmony_ci				    WCD938X_M_RTH_CTL_MASK, R_OFF);
252062306a36Sopenharmony_ci		goto done;
252162306a36Sopenharmony_ci	}
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci	/*
252462306a36Sopenharmony_ci	 * If moisture_en is already enabled, then skip to plug type
252562306a36Sopenharmony_ci	 * detection.
252662306a36Sopenharmony_ci	 */
252762306a36Sopenharmony_ci	if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK))
252862306a36Sopenharmony_ci		goto done;
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci	wcd938x_mbhc_moisture_detect_en(component, true);
253162306a36Sopenharmony_ci	/* Read moisture comparator status */
253262306a36Sopenharmony_ci	ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS)
253362306a36Sopenharmony_ci				& 0x20) ? 0 : 1);
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_cidone:
253662306a36Sopenharmony_ci	return ret;
253762306a36Sopenharmony_ci
253862306a36Sopenharmony_ci}
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_cistatic void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component,
254162306a36Sopenharmony_ci						bool enable)
254262306a36Sopenharmony_ci{
254362306a36Sopenharmony_ci	snd_soc_component_write_field(component,
254462306a36Sopenharmony_ci			      WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
254562306a36Sopenharmony_ci			      WCD938X_MOISTURE_EN_POLLING_MASK, enable);
254662306a36Sopenharmony_ci}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_cistatic const struct wcd_mbhc_cb mbhc_cb = {
254962306a36Sopenharmony_ci	.clk_setup = wcd938x_mbhc_clk_setup,
255062306a36Sopenharmony_ci	.mbhc_bias = wcd938x_mbhc_mbhc_bias_control,
255162306a36Sopenharmony_ci	.set_btn_thr = wcd938x_mbhc_program_btn_thr,
255262306a36Sopenharmony_ci	.micbias_enable_status = wcd938x_mbhc_micb_en_status,
255362306a36Sopenharmony_ci	.hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control,
255462306a36Sopenharmony_ci	.mbhc_micbias_control = wcd938x_mbhc_request_micbias,
255562306a36Sopenharmony_ci	.mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control,
255662306a36Sopenharmony_ci	.mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic,
255762306a36Sopenharmony_ci	.compute_impedance = wcd938x_wcd_mbhc_calc_impedance,
255862306a36Sopenharmony_ci	.mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl,
255962306a36Sopenharmony_ci	.hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl,
256062306a36Sopenharmony_ci	.mbhc_moisture_config = wcd938x_mbhc_moisture_config,
256162306a36Sopenharmony_ci	.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,
256262306a36Sopenharmony_ci	.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,
256362306a36Sopenharmony_ci	.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,
256462306a36Sopenharmony_ci};
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_cistatic int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,
256762306a36Sopenharmony_ci			      struct snd_ctl_elem_value *ucontrol)
256862306a36Sopenharmony_ci{
256962306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
257062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc);
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	return 0;
257562306a36Sopenharmony_ci}
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_cistatic int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol,
257862306a36Sopenharmony_ci				   struct snd_ctl_elem_value *ucontrol)
257962306a36Sopenharmony_ci{
258062306a36Sopenharmony_ci	uint32_t zl, zr;
258162306a36Sopenharmony_ci	bool hphr;
258262306a36Sopenharmony_ci	struct soc_mixer_control *mc;
258362306a36Sopenharmony_ci	struct snd_soc_component *component =
258462306a36Sopenharmony_ci					snd_soc_kcontrol_component(kcontrol);
258562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci	mc = (struct soc_mixer_control *)(kcontrol->private_value);
258862306a36Sopenharmony_ci	hphr = mc->shift;
258962306a36Sopenharmony_ci	wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr);
259062306a36Sopenharmony_ci	dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr);
259162306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = hphr ? zr : zl;
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	return 0;
259462306a36Sopenharmony_ci}
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_cistatic const struct snd_kcontrol_new hph_type_detect_controls[] = {
259762306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0,
259862306a36Sopenharmony_ci		       wcd938x_get_hph_type, NULL),
259962306a36Sopenharmony_ci};
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_cistatic const struct snd_kcontrol_new impedance_detect_controls[] = {
260262306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0,
260362306a36Sopenharmony_ci		       wcd938x_hph_impedance_get, NULL),
260462306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0,
260562306a36Sopenharmony_ci		       wcd938x_hph_impedance_get, NULL),
260662306a36Sopenharmony_ci};
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_cistatic int wcd938x_mbhc_init(struct snd_soc_component *component)
260962306a36Sopenharmony_ci{
261062306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
261162306a36Sopenharmony_ci	struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids;
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci	intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip,
261462306a36Sopenharmony_ci						    WCD938X_IRQ_MBHC_SW_DET);
261562306a36Sopenharmony_ci	intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip,
261662306a36Sopenharmony_ci							   WCD938X_IRQ_MBHC_BUTTON_PRESS_DET);
261762306a36Sopenharmony_ci	intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip,
261862306a36Sopenharmony_ci							     WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET);
261962306a36Sopenharmony_ci	intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip,
262062306a36Sopenharmony_ci							WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET);
262162306a36Sopenharmony_ci	intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip,
262262306a36Sopenharmony_ci							WCD938X_IRQ_MBHC_ELECT_INS_REM_DET);
262362306a36Sopenharmony_ci	intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
262462306a36Sopenharmony_ci						    WCD938X_IRQ_HPHL_OCP_INT);
262562306a36Sopenharmony_ci	intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip,
262662306a36Sopenharmony_ci						     WCD938X_IRQ_HPHR_OCP_INT);
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);
262962306a36Sopenharmony_ci	if (IS_ERR(wcd938x->wcd_mbhc))
263062306a36Sopenharmony_ci		return PTR_ERR(wcd938x->wcd_mbhc);
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	snd_soc_add_component_controls(component, impedance_detect_controls,
263362306a36Sopenharmony_ci				       ARRAY_SIZE(impedance_detect_controls));
263462306a36Sopenharmony_ci	snd_soc_add_component_controls(component, hph_type_detect_controls,
263562306a36Sopenharmony_ci				       ARRAY_SIZE(hph_type_detect_controls));
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_ci	return 0;
263862306a36Sopenharmony_ci}
263962306a36Sopenharmony_ci
264062306a36Sopenharmony_cistatic void wcd938x_mbhc_deinit(struct snd_soc_component *component)
264162306a36Sopenharmony_ci{
264262306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci	wcd_mbhc_deinit(wcd938x->wcd_mbhc);
264562306a36Sopenharmony_ci}
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_ci/* END MBHC */
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_cistatic const struct snd_kcontrol_new wcd938x_snd_controls[] = {
265062306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0,
265162306a36Sopenharmony_ci		       wcd938x_get_compander, wcd938x_set_compander),
265262306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHR_COMP Switch", WCD938X_COMP_R, 1, 1, 0,
265362306a36Sopenharmony_ci		       wcd938x_get_compander, wcd938x_set_compander),
265462306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHL Switch", WCD938X_HPH_L, 0, 1, 0,
265562306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
265662306a36Sopenharmony_ci	SOC_SINGLE_EXT("HPHR Switch", WCD938X_HPH_R, 0, 1, 0,
265762306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
265862306a36Sopenharmony_ci	SOC_SINGLE_EXT("CLSH Switch", WCD938X_CLSH, 0, 1, 0,
265962306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
266062306a36Sopenharmony_ci	SOC_SINGLE_EXT("LO Switch", WCD938X_LO, 0, 1, 0,
266162306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
266262306a36Sopenharmony_ci	SOC_SINGLE_EXT("DSD_L Switch", WCD938X_DSD_L, 0, 1, 0,
266362306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
266462306a36Sopenharmony_ci	SOC_SINGLE_EXT("DSD_R Switch", WCD938X_DSD_R, 0, 1, 0,
266562306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
266662306a36Sopenharmony_ci	SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 1, line_gain),
266762306a36Sopenharmony_ci	SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 1, line_gain),
266862306a36Sopenharmony_ci	WCD938X_EAR_PA_GAIN_TLV("EAR_PA Volume", WCD938X_ANA_EAR_COMPANDER_CTL,
266962306a36Sopenharmony_ci				2, 0x10, 0, ear_pa_gain),
267062306a36Sopenharmony_ci	SOC_SINGLE_EXT("ADC1 Switch", WCD938X_ADC1, 1, 1, 0,
267162306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
267262306a36Sopenharmony_ci	SOC_SINGLE_EXT("ADC2 Switch", WCD938X_ADC2, 1, 1, 0,
267362306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
267462306a36Sopenharmony_ci	SOC_SINGLE_EXT("ADC3 Switch", WCD938X_ADC3, 1, 1, 0,
267562306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
267662306a36Sopenharmony_ci	SOC_SINGLE_EXT("ADC4 Switch", WCD938X_ADC4, 1, 1, 0,
267762306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
267862306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC0 Switch", WCD938X_DMIC0, 1, 1, 0,
267962306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
268062306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC1 Switch", WCD938X_DMIC1, 1, 1, 0,
268162306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
268262306a36Sopenharmony_ci	SOC_SINGLE_EXT("MBHC Switch", WCD938X_MBHC, 1, 1, 0,
268362306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
268462306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC2 Switch", WCD938X_DMIC2, 1, 1, 0,
268562306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
268662306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC3 Switch", WCD938X_DMIC3, 1, 1, 0,
268762306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
268862306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC4 Switch", WCD938X_DMIC4, 1, 1, 0,
268962306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
269062306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC5 Switch", WCD938X_DMIC5, 1, 1, 0,
269162306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
269262306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC6 Switch", WCD938X_DMIC6, 1, 1, 0,
269362306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
269462306a36Sopenharmony_ci	SOC_SINGLE_EXT("DMIC7 Switch", WCD938X_DMIC7, 1, 1, 0,
269562306a36Sopenharmony_ci		       wcd938x_get_swr_port, wcd938x_set_swr_port),
269662306a36Sopenharmony_ci	SOC_SINGLE_EXT("LDOH Enable Switch", SND_SOC_NOPM, 0, 1, 0,
269762306a36Sopenharmony_ci		       wcd938x_ldoh_get, wcd938x_ldoh_put),
269862306a36Sopenharmony_ci	SOC_SINGLE_EXT("ADC2_BCS Disable Switch", SND_SOC_NOPM, 0, 1, 0,
269962306a36Sopenharmony_ci		       wcd938x_bcs_get, wcd938x_bcs_put),
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0, analog_gain),
270262306a36Sopenharmony_ci	SOC_SINGLE_TLV("ADC2 Volume", WCD938X_ANA_TX_CH2, 0, 20, 0, analog_gain),
270362306a36Sopenharmony_ci	SOC_SINGLE_TLV("ADC3 Volume", WCD938X_ANA_TX_CH3, 0, 20, 0, analog_gain),
270462306a36Sopenharmony_ci	SOC_SINGLE_TLV("ADC4 Volume", WCD938X_ANA_TX_CH4, 0, 20, 0, analog_gain),
270562306a36Sopenharmony_ci};
270662306a36Sopenharmony_ci
270762306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	/*input widgets*/
271062306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC1"),
271162306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC2"),
271262306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC3"),
271362306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC4"),
271462306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC5"),
271562306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC6"),
271662306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("AMIC7"),
271762306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("Analog Mic1", NULL),
271862306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("Analog Mic2", NULL),
271962306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("Analog Mic3", NULL),
272062306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
272162306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("Analog Mic5", NULL),
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci	/*tx widgets*/
272462306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
272562306a36Sopenharmony_ci			   wcd938x_codec_enable_adc,
272662306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
272762306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0,
272862306a36Sopenharmony_ci			   wcd938x_codec_enable_adc,
272962306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
273062306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 2, 0,
273162306a36Sopenharmony_ci			   wcd938x_codec_enable_adc,
273262306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
273362306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC4", NULL, SND_SOC_NOPM, 3, 0,
273462306a36Sopenharmony_ci			   wcd938x_codec_enable_adc,
273562306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
273662306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
273762306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
273862306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
273962306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0,
274062306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
274162306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
274262306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 2, 0,
274362306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
274462306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
274562306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 3, 0,
274662306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
274762306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
274862306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 4, 0,
274962306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
275062306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
275162306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 5, 0,
275262306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
275362306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
275462306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC7", NULL, SND_SOC_NOPM, 6, 0,
275562306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
275662306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
275762306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("DMIC8", NULL, SND_SOC_NOPM, 7, 0,
275862306a36Sopenharmony_ci			   wcd938x_codec_enable_dmic,
275962306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0,
276262306a36Sopenharmony_ci			     NULL, 0, wcd938x_adc_enable_req,
276362306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
276462306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 1, 0,
276562306a36Sopenharmony_ci			     NULL, 0, wcd938x_adc_enable_req,
276662306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
276762306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 2, 0,
276862306a36Sopenharmony_ci			     NULL, 0, wcd938x_adc_enable_req,
276962306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
277062306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC4 REQ", SND_SOC_NOPM, 3, 0, NULL, 0,
277162306a36Sopenharmony_ci			     wcd938x_adc_enable_req,
277262306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),
277562306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC3 MUX", SND_SOC_NOPM, 0, 0, &tx_adc3_mux),
277662306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0, &tx_adc4_mux),
277762306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("HDR12 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr12_mux),
277862306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("HDR34 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr34_mux),
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	/*tx mixers*/
278162306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch,
278262306a36Sopenharmony_ci			     ARRAY_SIZE(adc1_switch), wcd938x_tx_swr_ctrl,
278362306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
278462306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0, adc2_switch,
278562306a36Sopenharmony_ci			     ARRAY_SIZE(adc2_switch), wcd938x_tx_swr_ctrl,
278662306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
278762306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch,
278862306a36Sopenharmony_ci			     ARRAY_SIZE(adc3_switch), wcd938x_tx_swr_ctrl,
278962306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
279062306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("ADC4_MIXER", SND_SOC_NOPM, 0, 0, adc4_switch,
279162306a36Sopenharmony_ci			     ARRAY_SIZE(adc4_switch), wcd938x_tx_swr_ctrl,
279262306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
279362306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch,
279462306a36Sopenharmony_ci			     ARRAY_SIZE(dmic1_switch), wcd938x_tx_swr_ctrl,
279562306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
279662306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0, 0, dmic2_switch,
279762306a36Sopenharmony_ci			     ARRAY_SIZE(dmic2_switch), wcd938x_tx_swr_ctrl,
279862306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
279962306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0, 0, dmic3_switch,
280062306a36Sopenharmony_ci			     ARRAY_SIZE(dmic3_switch), wcd938x_tx_swr_ctrl,
280162306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
280262306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0, 0, dmic4_switch,
280362306a36Sopenharmony_ci			     ARRAY_SIZE(dmic4_switch), wcd938x_tx_swr_ctrl,
280462306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
280562306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0, 0, dmic5_switch,
280662306a36Sopenharmony_ci			     ARRAY_SIZE(dmic5_switch), wcd938x_tx_swr_ctrl,
280762306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
280862306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0, 0, dmic6_switch,
280962306a36Sopenharmony_ci			     ARRAY_SIZE(dmic6_switch), wcd938x_tx_swr_ctrl,
281062306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
281162306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC7_MIXER", SND_SOC_NOPM, 0, 0, dmic7_switch,
281262306a36Sopenharmony_ci			     ARRAY_SIZE(dmic7_switch), wcd938x_tx_swr_ctrl,
281362306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
281462306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("DMIC8_MIXER", SND_SOC_NOPM, 0, 0, dmic8_switch,
281562306a36Sopenharmony_ci			     ARRAY_SIZE(dmic8_switch), wcd938x_tx_swr_ctrl,
281662306a36Sopenharmony_ci			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
281762306a36Sopenharmony_ci	/* micbias widgets*/
281862306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,
281962306a36Sopenharmony_ci			    wcd938x_codec_enable_micbias,
282062306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
282162306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMD),
282262306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,
282362306a36Sopenharmony_ci			    wcd938x_codec_enable_micbias,
282462306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
282562306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMD),
282662306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,
282762306a36Sopenharmony_ci			    wcd938x_codec_enable_micbias,
282862306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
282962306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMD),
283062306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,
283162306a36Sopenharmony_ci			    wcd938x_codec_enable_micbias,
283262306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
283362306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMD),
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	/* micbias pull up widgets*/
283662306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,
283762306a36Sopenharmony_ci				wcd938x_codec_enable_micbias_pullup,
283862306a36Sopenharmony_ci				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
283962306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
284062306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,
284162306a36Sopenharmony_ci				wcd938x_codec_enable_micbias_pullup,
284262306a36Sopenharmony_ci				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
284362306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
284462306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,
284562306a36Sopenharmony_ci				wcd938x_codec_enable_micbias_pullup,
284662306a36Sopenharmony_ci				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
284762306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
284862306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("VA MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,
284962306a36Sopenharmony_ci				wcd938x_codec_enable_micbias_pullup,
285062306a36Sopenharmony_ci				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
285162306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	/*output widgets tx*/
285462306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),
285562306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),
285662306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"),
285762306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("ADC4_OUTPUT"),
285862306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
285962306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
286062306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"),
286162306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"),
286262306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"),
286362306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"),
286462306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC7_OUTPUT"),
286562306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("DMIC8_OUTPUT"),
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("IN1_HPHL"),
286862306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("IN2_HPHR"),
286962306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("IN3_AUX"),
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	/*rx widgets*/
287262306a36Sopenharmony_ci	SND_SOC_DAPM_PGA_E("EAR PGA", WCD938X_ANA_EAR, 7, 0, NULL, 0,
287362306a36Sopenharmony_ci			   wcd938x_codec_enable_ear_pa,
287462306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
287562306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
287662306a36Sopenharmony_ci	SND_SOC_DAPM_PGA_E("AUX PGA", WCD938X_AUX_AUXPA, 7, 0, NULL, 0,
287762306a36Sopenharmony_ci			   wcd938x_codec_enable_aux_pa,
287862306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
287962306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
288062306a36Sopenharmony_ci	SND_SOC_DAPM_PGA_E("HPHL PGA", WCD938X_ANA_HPH, 7, 0, NULL, 0,
288162306a36Sopenharmony_ci			   wcd938x_codec_enable_hphl_pa,
288262306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
288362306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
288462306a36Sopenharmony_ci	SND_SOC_DAPM_PGA_E("HPHR PGA", WCD938X_ANA_HPH, 6, 0, NULL, 0,
288562306a36Sopenharmony_ci			   wcd938x_codec_enable_hphr_pa,
288662306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
288762306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,
289062306a36Sopenharmony_ci			   wcd938x_codec_hphl_dac_event,
289162306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
289262306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
289362306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0,
289462306a36Sopenharmony_ci			   wcd938x_codec_hphr_dac_event,
289562306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
289662306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
289762306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0,
289862306a36Sopenharmony_ci			   wcd938x_codec_ear_dac_event,
289962306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
290062306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
290162306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("RDAC4", NULL, SND_SOC_NOPM, 0, 0,
290262306a36Sopenharmony_ci			   wcd938x_codec_aux_dac_event,
290362306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
290462306a36Sopenharmony_ci			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0, NULL, 0),
290962306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("RXCLK", SND_SOC_NOPM, 0, 0,
291062306a36Sopenharmony_ci			    wcd938x_codec_enable_rxclk,
291162306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
291262306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMD),
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0, NULL, 0),
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
291762306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
291862306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_ci	/* rx mixer widgets*/
292162306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0,
292262306a36Sopenharmony_ci			   ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)),
292362306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("AUX_RDAC", SND_SOC_NOPM, 0, 0,
292462306a36Sopenharmony_ci			   aux_rdac_switch, ARRAY_SIZE(aux_rdac_switch)),
292562306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0,
292662306a36Sopenharmony_ci			   hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)),
292762306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0,
292862306a36Sopenharmony_ci			   hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)),
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	/*output widgets rx*/
293162306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("EAR"),
293262306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("AUX"),
293362306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HPHL"),
293462306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HPHR"),
293562306a36Sopenharmony_ci
293662306a36Sopenharmony_ci};
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_cistatic const struct snd_soc_dapm_route wcd938x_audio_map[] = {
293962306a36Sopenharmony_ci	{"ADC1_OUTPUT", NULL, "ADC1_MIXER"},
294062306a36Sopenharmony_ci	{"ADC1_MIXER", "Switch", "ADC1 REQ"},
294162306a36Sopenharmony_ci	{"ADC1 REQ", NULL, "ADC1"},
294262306a36Sopenharmony_ci	{"ADC1", NULL, "AMIC1"},
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_ci	{"ADC2_OUTPUT", NULL, "ADC2_MIXER"},
294562306a36Sopenharmony_ci	{"ADC2_MIXER", "Switch", "ADC2 REQ"},
294662306a36Sopenharmony_ci	{"ADC2 REQ", NULL, "ADC2"},
294762306a36Sopenharmony_ci	{"ADC2", NULL, "HDR12 MUX"},
294862306a36Sopenharmony_ci	{"HDR12 MUX", "NO_HDR12", "ADC2 MUX"},
294962306a36Sopenharmony_ci	{"HDR12 MUX", "HDR12", "AMIC1"},
295062306a36Sopenharmony_ci	{"ADC2 MUX", "INP3", "AMIC3"},
295162306a36Sopenharmony_ci	{"ADC2 MUX", "INP2", "AMIC2"},
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci	{"ADC3_OUTPUT", NULL, "ADC3_MIXER"},
295462306a36Sopenharmony_ci	{"ADC3_MIXER", "Switch", "ADC3 REQ"},
295562306a36Sopenharmony_ci	{"ADC3 REQ", NULL, "ADC3"},
295662306a36Sopenharmony_ci	{"ADC3", NULL, "HDR34 MUX"},
295762306a36Sopenharmony_ci	{"HDR34 MUX", "NO_HDR34", "ADC3 MUX"},
295862306a36Sopenharmony_ci	{"HDR34 MUX", "HDR34", "AMIC5"},
295962306a36Sopenharmony_ci	{"ADC3 MUX", "INP4", "AMIC4"},
296062306a36Sopenharmony_ci	{"ADC3 MUX", "INP6", "AMIC6"},
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	{"ADC4_OUTPUT", NULL, "ADC4_MIXER"},
296362306a36Sopenharmony_ci	{"ADC4_MIXER", "Switch", "ADC4 REQ"},
296462306a36Sopenharmony_ci	{"ADC4 REQ", NULL, "ADC4"},
296562306a36Sopenharmony_ci	{"ADC4", NULL, "ADC4 MUX"},
296662306a36Sopenharmony_ci	{"ADC4 MUX", "INP5", "AMIC5"},
296762306a36Sopenharmony_ci	{"ADC4 MUX", "INP7", "AMIC7"},
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_ci	{"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"},
297062306a36Sopenharmony_ci	{"DMIC1_MIXER", "Switch", "DMIC1"},
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	{"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"},
297362306a36Sopenharmony_ci	{"DMIC2_MIXER", "Switch", "DMIC2"},
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	{"DMIC3_OUTPUT", NULL, "DMIC3_MIXER"},
297662306a36Sopenharmony_ci	{"DMIC3_MIXER", "Switch", "DMIC3"},
297762306a36Sopenharmony_ci
297862306a36Sopenharmony_ci	{"DMIC4_OUTPUT", NULL, "DMIC4_MIXER"},
297962306a36Sopenharmony_ci	{"DMIC4_MIXER", "Switch", "DMIC4"},
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci	{"DMIC5_OUTPUT", NULL, "DMIC5_MIXER"},
298262306a36Sopenharmony_ci	{"DMIC5_MIXER", "Switch", "DMIC5"},
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	{"DMIC6_OUTPUT", NULL, "DMIC6_MIXER"},
298562306a36Sopenharmony_ci	{"DMIC6_MIXER", "Switch", "DMIC6"},
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	{"DMIC7_OUTPUT", NULL, "DMIC7_MIXER"},
298862306a36Sopenharmony_ci	{"DMIC7_MIXER", "Switch", "DMIC7"},
298962306a36Sopenharmony_ci
299062306a36Sopenharmony_ci	{"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"},
299162306a36Sopenharmony_ci	{"DMIC8_MIXER", "Switch", "DMIC8"},
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci	{"IN1_HPHL", NULL, "VDD_BUCK"},
299462306a36Sopenharmony_ci	{"IN1_HPHL", NULL, "CLS_H_PORT"},
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci	{"RX1", NULL, "IN1_HPHL"},
299762306a36Sopenharmony_ci	{"RX1", NULL, "RXCLK"},
299862306a36Sopenharmony_ci	{"RDAC1", NULL, "RX1"},
299962306a36Sopenharmony_ci	{"HPHL_RDAC", "Switch", "RDAC1"},
300062306a36Sopenharmony_ci	{"HPHL PGA", NULL, "HPHL_RDAC"},
300162306a36Sopenharmony_ci	{"HPHL", NULL, "HPHL PGA"},
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	{"IN2_HPHR", NULL, "VDD_BUCK"},
300462306a36Sopenharmony_ci	{"IN2_HPHR", NULL, "CLS_H_PORT"},
300562306a36Sopenharmony_ci	{"RX2", NULL, "IN2_HPHR"},
300662306a36Sopenharmony_ci	{"RDAC2", NULL, "RX2"},
300762306a36Sopenharmony_ci	{"RX2", NULL, "RXCLK"},
300862306a36Sopenharmony_ci	{"HPHR_RDAC", "Switch", "RDAC2"},
300962306a36Sopenharmony_ci	{"HPHR PGA", NULL, "HPHR_RDAC"},
301062306a36Sopenharmony_ci	{"HPHR", NULL, "HPHR PGA"},
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci	{"IN3_AUX", NULL, "VDD_BUCK"},
301362306a36Sopenharmony_ci	{"IN3_AUX", NULL, "CLS_H_PORT"},
301462306a36Sopenharmony_ci	{"RX3", NULL, "IN3_AUX"},
301562306a36Sopenharmony_ci	{"RDAC4", NULL, "RX3"},
301662306a36Sopenharmony_ci	{"RX3", NULL, "RXCLK"},
301762306a36Sopenharmony_ci	{"AUX_RDAC", "Switch", "RDAC4"},
301862306a36Sopenharmony_ci	{"AUX PGA", NULL, "AUX_RDAC"},
301962306a36Sopenharmony_ci	{"AUX", NULL, "AUX PGA"},
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_ci	{"RDAC3_MUX", "RX3", "RX3"},
302262306a36Sopenharmony_ci	{"RDAC3_MUX", "RX1", "RX1"},
302362306a36Sopenharmony_ci	{"RDAC3", NULL, "RDAC3_MUX"},
302462306a36Sopenharmony_ci	{"EAR_RDAC", "Switch", "RDAC3"},
302562306a36Sopenharmony_ci	{"EAR PGA", NULL, "EAR_RDAC"},
302662306a36Sopenharmony_ci	{"EAR", NULL, "EAR PGA"},
302762306a36Sopenharmony_ci};
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_cistatic int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x)
303062306a36Sopenharmony_ci{
303162306a36Sopenharmony_ci	int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	/* set micbias voltage */
303462306a36Sopenharmony_ci	vout_ctl_1 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb1_mv);
303562306a36Sopenharmony_ci	vout_ctl_2 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb2_mv);
303662306a36Sopenharmony_ci	vout_ctl_3 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb3_mv);
303762306a36Sopenharmony_ci	vout_ctl_4 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb4_mv);
303862306a36Sopenharmony_ci	if (vout_ctl_1 < 0 || vout_ctl_2 < 0 || vout_ctl_3 < 0 || vout_ctl_4 < 0)
303962306a36Sopenharmony_ci		return -EINVAL;
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB1,
304262306a36Sopenharmony_ci			   WCD938X_MICB_VOUT_MASK, vout_ctl_1);
304362306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB2,
304462306a36Sopenharmony_ci			   WCD938X_MICB_VOUT_MASK, vout_ctl_2);
304562306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB3,
304662306a36Sopenharmony_ci			   WCD938X_MICB_VOUT_MASK, vout_ctl_3);
304762306a36Sopenharmony_ci	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB4,
304862306a36Sopenharmony_ci			   WCD938X_MICB_VOUT_MASK, vout_ctl_4);
304962306a36Sopenharmony_ci
305062306a36Sopenharmony_ci	return 0;
305162306a36Sopenharmony_ci}
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_cistatic irqreturn_t wcd938x_wd_handle_irq(int irq, void *data)
305462306a36Sopenharmony_ci{
305562306a36Sopenharmony_ci	return IRQ_HANDLED;
305662306a36Sopenharmony_ci}
305762306a36Sopenharmony_ci
305862306a36Sopenharmony_cistatic struct irq_chip wcd_irq_chip = {
305962306a36Sopenharmony_ci	.name = "WCD938x",
306062306a36Sopenharmony_ci};
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_cistatic int wcd_irq_chip_map(struct irq_domain *irqd, unsigned int virq,
306362306a36Sopenharmony_ci			irq_hw_number_t hw)
306462306a36Sopenharmony_ci{
306562306a36Sopenharmony_ci	irq_set_chip_and_handler(virq, &wcd_irq_chip, handle_simple_irq);
306662306a36Sopenharmony_ci	irq_set_nested_thread(virq, 1);
306762306a36Sopenharmony_ci	irq_set_noprobe(virq);
306862306a36Sopenharmony_ci
306962306a36Sopenharmony_ci	return 0;
307062306a36Sopenharmony_ci}
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_cistatic const struct irq_domain_ops wcd_domain_ops = {
307362306a36Sopenharmony_ci	.map = wcd_irq_chip_map,
307462306a36Sopenharmony_ci};
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_cistatic int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev)
307762306a36Sopenharmony_ci{
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci	wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL);
308062306a36Sopenharmony_ci	if (!(wcd->virq)) {
308162306a36Sopenharmony_ci		dev_err(dev, "%s: Failed to add IRQ domain\n", __func__);
308262306a36Sopenharmony_ci		return -EINVAL;
308362306a36Sopenharmony_ci	}
308462306a36Sopenharmony_ci
308562306a36Sopenharmony_ci	return devm_regmap_add_irq_chip(dev, wcd->regmap,
308662306a36Sopenharmony_ci					irq_create_mapping(wcd->virq, 0),
308762306a36Sopenharmony_ci					IRQF_ONESHOT, 0, &wcd938x_regmap_irq_chip,
308862306a36Sopenharmony_ci					&wcd->irq_chip);
308962306a36Sopenharmony_ci}
309062306a36Sopenharmony_ci
309162306a36Sopenharmony_cistatic int wcd938x_soc_codec_probe(struct snd_soc_component *component)
309262306a36Sopenharmony_ci{
309362306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
309462306a36Sopenharmony_ci	struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev;
309562306a36Sopenharmony_ci	struct device *dev = component->dev;
309662306a36Sopenharmony_ci	unsigned long time_left;
309762306a36Sopenharmony_ci	int ret, i;
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
310062306a36Sopenharmony_ci						msecs_to_jiffies(2000));
310162306a36Sopenharmony_ci	if (!time_left) {
310262306a36Sopenharmony_ci		dev_err(dev, "soundwire device init timeout\n");
310362306a36Sopenharmony_ci		return -ETIMEDOUT;
310462306a36Sopenharmony_ci	}
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	snd_soc_component_init_regmap(component, wcd938x->regmap);
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
310962306a36Sopenharmony_ci	if (ret < 0)
311062306a36Sopenharmony_ci		return ret;
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	wcd938x->variant = snd_soc_component_read_field(component,
311362306a36Sopenharmony_ci						 WCD938X_DIGITAL_EFUSE_REG_0,
311462306a36Sopenharmony_ci						 WCD938X_ID_MASK);
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X);
311762306a36Sopenharmony_ci	if (IS_ERR(wcd938x->clsh_info)) {
311862306a36Sopenharmony_ci		pm_runtime_put(dev);
311962306a36Sopenharmony_ci		return PTR_ERR(wcd938x->clsh_info);
312062306a36Sopenharmony_ci	}
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci	wcd938x_io_init(wcd938x);
312362306a36Sopenharmony_ci	/* Set all interrupts as edge triggered */
312462306a36Sopenharmony_ci	for (i = 0; i < wcd938x_regmap_irq_chip.num_regs; i++) {
312562306a36Sopenharmony_ci		regmap_write(wcd938x->regmap,
312662306a36Sopenharmony_ci			     (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);
312762306a36Sopenharmony_ci	}
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	pm_runtime_put(dev);
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci	wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
313262306a36Sopenharmony_ci						       WCD938X_IRQ_HPHR_PDM_WD_INT);
313362306a36Sopenharmony_ci	wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
313462306a36Sopenharmony_ci						       WCD938X_IRQ_HPHL_PDM_WD_INT);
313562306a36Sopenharmony_ci	wcd938x->aux_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
313662306a36Sopenharmony_ci						       WCD938X_IRQ_AUX_PDM_WD_INT);
313762306a36Sopenharmony_ci
313862306a36Sopenharmony_ci	/* Request for watchdog interrupt */
313962306a36Sopenharmony_ci	ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
314062306a36Sopenharmony_ci				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
314162306a36Sopenharmony_ci				   "HPHR PDM WD INT", wcd938x);
314262306a36Sopenharmony_ci	if (ret) {
314362306a36Sopenharmony_ci		dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret);
314462306a36Sopenharmony_ci		goto err_free_clsh_ctrl;
314562306a36Sopenharmony_ci	}
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
314862306a36Sopenharmony_ci				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
314962306a36Sopenharmony_ci				   "HPHL PDM WD INT", wcd938x);
315062306a36Sopenharmony_ci	if (ret) {
315162306a36Sopenharmony_ci		dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret);
315262306a36Sopenharmony_ci		goto err_free_hphr_pdm_wd_int;
315362306a36Sopenharmony_ci	}
315462306a36Sopenharmony_ci
315562306a36Sopenharmony_ci	ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
315662306a36Sopenharmony_ci				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
315762306a36Sopenharmony_ci				   "AUX PDM WD INT", wcd938x);
315862306a36Sopenharmony_ci	if (ret) {
315962306a36Sopenharmony_ci		dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret);
316062306a36Sopenharmony_ci		goto err_free_hphl_pdm_wd_int;
316162306a36Sopenharmony_ci	}
316262306a36Sopenharmony_ci
316362306a36Sopenharmony_ci	/* Disable watchdog interrupt for HPH and AUX */
316462306a36Sopenharmony_ci	disable_irq_nosync(wcd938x->hphr_pdm_wd_int);
316562306a36Sopenharmony_ci	disable_irq_nosync(wcd938x->hphl_pdm_wd_int);
316662306a36Sopenharmony_ci	disable_irq_nosync(wcd938x->aux_pdm_wd_int);
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci	switch (wcd938x->variant) {
316962306a36Sopenharmony_ci	case WCD9380:
317062306a36Sopenharmony_ci		ret = snd_soc_add_component_controls(component, wcd9380_snd_controls,
317162306a36Sopenharmony_ci					ARRAY_SIZE(wcd9380_snd_controls));
317262306a36Sopenharmony_ci		if (ret < 0) {
317362306a36Sopenharmony_ci			dev_err(component->dev,
317462306a36Sopenharmony_ci				"%s: Failed to add snd ctrls for variant: %d\n",
317562306a36Sopenharmony_ci				__func__, wcd938x->variant);
317662306a36Sopenharmony_ci			goto err_free_aux_pdm_wd_int;
317762306a36Sopenharmony_ci		}
317862306a36Sopenharmony_ci		break;
317962306a36Sopenharmony_ci	case WCD9385:
318062306a36Sopenharmony_ci		ret = snd_soc_add_component_controls(component, wcd9385_snd_controls,
318162306a36Sopenharmony_ci					ARRAY_SIZE(wcd9385_snd_controls));
318262306a36Sopenharmony_ci		if (ret < 0) {
318362306a36Sopenharmony_ci			dev_err(component->dev,
318462306a36Sopenharmony_ci				"%s: Failed to add snd ctrls for variant: %d\n",
318562306a36Sopenharmony_ci				__func__, wcd938x->variant);
318662306a36Sopenharmony_ci			goto err_free_aux_pdm_wd_int;
318762306a36Sopenharmony_ci		}
318862306a36Sopenharmony_ci		break;
318962306a36Sopenharmony_ci	default:
319062306a36Sopenharmony_ci		break;
319162306a36Sopenharmony_ci	}
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_ci	ret = wcd938x_mbhc_init(component);
319462306a36Sopenharmony_ci	if (ret) {
319562306a36Sopenharmony_ci		dev_err(component->dev,  "mbhc initialization failed\n");
319662306a36Sopenharmony_ci		goto err_free_aux_pdm_wd_int;
319762306a36Sopenharmony_ci	}
319862306a36Sopenharmony_ci
319962306a36Sopenharmony_ci	return 0;
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_cierr_free_aux_pdm_wd_int:
320262306a36Sopenharmony_ci	free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
320362306a36Sopenharmony_cierr_free_hphl_pdm_wd_int:
320462306a36Sopenharmony_ci	free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
320562306a36Sopenharmony_cierr_free_hphr_pdm_wd_int:
320662306a36Sopenharmony_ci	free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
320762306a36Sopenharmony_cierr_free_clsh_ctrl:
320862306a36Sopenharmony_ci	wcd_clsh_ctrl_free(wcd938x->clsh_info);
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci	return ret;
321162306a36Sopenharmony_ci}
321262306a36Sopenharmony_ci
321362306a36Sopenharmony_cistatic void wcd938x_soc_codec_remove(struct snd_soc_component *component)
321462306a36Sopenharmony_ci{
321562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci	wcd938x_mbhc_deinit(component);
321862306a36Sopenharmony_ci
321962306a36Sopenharmony_ci	free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
322062306a36Sopenharmony_ci	free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
322162306a36Sopenharmony_ci	free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
322262306a36Sopenharmony_ci
322362306a36Sopenharmony_ci	wcd_clsh_ctrl_free(wcd938x->clsh_info);
322462306a36Sopenharmony_ci}
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_cistatic int wcd938x_codec_set_jack(struct snd_soc_component *comp,
322762306a36Sopenharmony_ci				  struct snd_soc_jack *jack, void *data)
322862306a36Sopenharmony_ci{
322962306a36Sopenharmony_ci	struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev);
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci	if (jack)
323262306a36Sopenharmony_ci		return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack);
323362306a36Sopenharmony_ci	else
323462306a36Sopenharmony_ci		wcd_mbhc_stop(wcd->wcd_mbhc);
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_ci	return 0;
323762306a36Sopenharmony_ci}
323862306a36Sopenharmony_ci
323962306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
324062306a36Sopenharmony_ci	.name = "wcd938x_codec",
324162306a36Sopenharmony_ci	.probe = wcd938x_soc_codec_probe,
324262306a36Sopenharmony_ci	.remove = wcd938x_soc_codec_remove,
324362306a36Sopenharmony_ci	.controls = wcd938x_snd_controls,
324462306a36Sopenharmony_ci	.num_controls = ARRAY_SIZE(wcd938x_snd_controls),
324562306a36Sopenharmony_ci	.dapm_widgets = wcd938x_dapm_widgets,
324662306a36Sopenharmony_ci	.num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),
324762306a36Sopenharmony_ci	.dapm_routes = wcd938x_audio_map,
324862306a36Sopenharmony_ci	.num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),
324962306a36Sopenharmony_ci	.set_jack = wcd938x_codec_set_jack,
325062306a36Sopenharmony_ci	.endianness = 1,
325162306a36Sopenharmony_ci};
325262306a36Sopenharmony_ci
325362306a36Sopenharmony_cistatic void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd)
325462306a36Sopenharmony_ci{
325562306a36Sopenharmony_ci	struct device_node *np = dev->of_node;
325662306a36Sopenharmony_ci	u32 prop_val = 0;
325762306a36Sopenharmony_ci	int rc = 0;
325862306a36Sopenharmony_ci
325962306a36Sopenharmony_ci	rc = of_property_read_u32(np, "qcom,micbias1-microvolt",  &prop_val);
326062306a36Sopenharmony_ci	if (!rc)
326162306a36Sopenharmony_ci		wcd->micb1_mv = prop_val/1000;
326262306a36Sopenharmony_ci	else
326362306a36Sopenharmony_ci		dev_info(dev, "%s: Micbias1 DT property not found\n", __func__);
326462306a36Sopenharmony_ci
326562306a36Sopenharmony_ci	rc = of_property_read_u32(np, "qcom,micbias2-microvolt",  &prop_val);
326662306a36Sopenharmony_ci	if (!rc)
326762306a36Sopenharmony_ci		wcd->micb2_mv = prop_val/1000;
326862306a36Sopenharmony_ci	else
326962306a36Sopenharmony_ci		dev_info(dev, "%s: Micbias2 DT property not found\n", __func__);
327062306a36Sopenharmony_ci
327162306a36Sopenharmony_ci	rc = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val);
327262306a36Sopenharmony_ci	if (!rc)
327362306a36Sopenharmony_ci		wcd->micb3_mv = prop_val/1000;
327462306a36Sopenharmony_ci	else
327562306a36Sopenharmony_ci		dev_info(dev, "%s: Micbias3 DT property not found\n", __func__);
327662306a36Sopenharmony_ci
327762306a36Sopenharmony_ci	rc = of_property_read_u32(np, "qcom,micbias4-microvolt",  &prop_val);
327862306a36Sopenharmony_ci	if (!rc)
327962306a36Sopenharmony_ci		wcd->micb4_mv = prop_val/1000;
328062306a36Sopenharmony_ci	else
328162306a36Sopenharmony_ci		dev_info(dev, "%s: Micbias4 DT property not found\n", __func__);
328262306a36Sopenharmony_ci}
328362306a36Sopenharmony_ci
328462306a36Sopenharmony_cistatic bool wcd938x_swap_gnd_mic(struct snd_soc_component *component, bool active)
328562306a36Sopenharmony_ci{
328662306a36Sopenharmony_ci	int value;
328762306a36Sopenharmony_ci
328862306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x;
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_ci	wcd938x = snd_soc_component_get_drvdata(component);
329162306a36Sopenharmony_ci
329262306a36Sopenharmony_ci	value = gpiod_get_value(wcd938x->us_euro_gpio);
329362306a36Sopenharmony_ci
329462306a36Sopenharmony_ci	gpiod_set_value(wcd938x->us_euro_gpio, !value);
329562306a36Sopenharmony_ci
329662306a36Sopenharmony_ci	return true;
329762306a36Sopenharmony_ci}
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_ci
330062306a36Sopenharmony_cistatic int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev)
330162306a36Sopenharmony_ci{
330262306a36Sopenharmony_ci	struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg;
330362306a36Sopenharmony_ci	int ret;
330462306a36Sopenharmony_ci
330562306a36Sopenharmony_ci	wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0);
330662306a36Sopenharmony_ci	if (wcd938x->reset_gpio < 0)
330762306a36Sopenharmony_ci		return dev_err_probe(dev, wcd938x->reset_gpio,
330862306a36Sopenharmony_ci				     "Failed to get reset gpio\n");
330962306a36Sopenharmony_ci
331062306a36Sopenharmony_ci	wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro",
331162306a36Sopenharmony_ci						GPIOD_OUT_LOW);
331262306a36Sopenharmony_ci	if (IS_ERR(wcd938x->us_euro_gpio))
331362306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio),
331462306a36Sopenharmony_ci				     "us-euro swap Control GPIO not found\n");
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci	cfg->swap_gnd_mic = wcd938x_swap_gnd_mic;
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	wcd938x->supplies[0].supply = "vdd-rxtx";
331962306a36Sopenharmony_ci	wcd938x->supplies[1].supply = "vdd-io";
332062306a36Sopenharmony_ci	wcd938x->supplies[2].supply = "vdd-buck";
332162306a36Sopenharmony_ci	wcd938x->supplies[3].supply = "vdd-mic-bias";
332262306a36Sopenharmony_ci
332362306a36Sopenharmony_ci	ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies);
332462306a36Sopenharmony_ci	if (ret)
332562306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to get supplies\n");
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci	ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies);
332862306a36Sopenharmony_ci	if (ret) {
332962306a36Sopenharmony_ci		regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);
333062306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to enable supplies\n");
333162306a36Sopenharmony_ci	}
333262306a36Sopenharmony_ci
333362306a36Sopenharmony_ci	wcd938x_dt_parse_micbias_info(dev, wcd938x);
333462306a36Sopenharmony_ci
333562306a36Sopenharmony_ci	cfg->mbhc_micbias = MIC_BIAS_2;
333662306a36Sopenharmony_ci	cfg->anc_micbias = MIC_BIAS_2;
333762306a36Sopenharmony_ci	cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
333862306a36Sopenharmony_ci	cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS;
333962306a36Sopenharmony_ci	cfg->micb_mv = wcd938x->micb2_mv;
334062306a36Sopenharmony_ci	cfg->linein_th = 5000;
334162306a36Sopenharmony_ci	cfg->hs_thr = 1700;
334262306a36Sopenharmony_ci	cfg->hph_thr = 50;
334362306a36Sopenharmony_ci
334462306a36Sopenharmony_ci	wcd_dt_parse_mbhc_data(dev, cfg);
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci	return 0;
334762306a36Sopenharmony_ci}
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_cistatic int wcd938x_reset(struct wcd938x_priv *wcd938x)
335062306a36Sopenharmony_ci{
335162306a36Sopenharmony_ci	gpio_direction_output(wcd938x->reset_gpio, 0);
335262306a36Sopenharmony_ci	/* 20us sleep required after pulling the reset gpio to LOW */
335362306a36Sopenharmony_ci	usleep_range(20, 30);
335462306a36Sopenharmony_ci	gpio_set_value(wcd938x->reset_gpio, 1);
335562306a36Sopenharmony_ci	/* 20us sleep required after pulling the reset gpio to HIGH */
335662306a36Sopenharmony_ci	usleep_range(20, 30);
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	return 0;
335962306a36Sopenharmony_ci}
336062306a36Sopenharmony_ci
336162306a36Sopenharmony_cistatic int wcd938x_codec_hw_params(struct snd_pcm_substream *substream,
336262306a36Sopenharmony_ci				struct snd_pcm_hw_params *params,
336362306a36Sopenharmony_ci				struct snd_soc_dai *dai)
336462306a36Sopenharmony_ci{
336562306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
336662306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
336762306a36Sopenharmony_ci
336862306a36Sopenharmony_ci	return wcd938x_sdw_hw_params(wcd, substream, params, dai);
336962306a36Sopenharmony_ci}
337062306a36Sopenharmony_ci
337162306a36Sopenharmony_cistatic int wcd938x_codec_free(struct snd_pcm_substream *substream,
337262306a36Sopenharmony_ci			      struct snd_soc_dai *dai)
337362306a36Sopenharmony_ci{
337462306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
337562306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci	return wcd938x_sdw_free(wcd, substream, dai);
337862306a36Sopenharmony_ci}
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_cistatic int wcd938x_codec_set_sdw_stream(struct snd_soc_dai *dai,
338162306a36Sopenharmony_ci				  void *stream, int direction)
338262306a36Sopenharmony_ci{
338362306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);
338462306a36Sopenharmony_ci	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci	return wcd938x_sdw_set_sdw_stream(wcd, dai, stream, direction);
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci}
338962306a36Sopenharmony_ci
339062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops wcd938x_sdw_dai_ops = {
339162306a36Sopenharmony_ci	.hw_params = wcd938x_codec_hw_params,
339262306a36Sopenharmony_ci	.hw_free = wcd938x_codec_free,
339362306a36Sopenharmony_ci	.set_stream = wcd938x_codec_set_sdw_stream,
339462306a36Sopenharmony_ci};
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_cistatic struct snd_soc_dai_driver wcd938x_dais[] = {
339762306a36Sopenharmony_ci	[0] = {
339862306a36Sopenharmony_ci		.name = "wcd938x-sdw-rx",
339962306a36Sopenharmony_ci		.playback = {
340062306a36Sopenharmony_ci			.stream_name = "WCD AIF1 Playback",
340162306a36Sopenharmony_ci			.rates = WCD938X_RATES_MASK | WCD938X_FRAC_RATES_MASK,
340262306a36Sopenharmony_ci			.formats = WCD938X_FORMATS_S16_S24_LE,
340362306a36Sopenharmony_ci			.rate_max = 192000,
340462306a36Sopenharmony_ci			.rate_min = 8000,
340562306a36Sopenharmony_ci			.channels_min = 1,
340662306a36Sopenharmony_ci			.channels_max = 2,
340762306a36Sopenharmony_ci		},
340862306a36Sopenharmony_ci		.ops = &wcd938x_sdw_dai_ops,
340962306a36Sopenharmony_ci	},
341062306a36Sopenharmony_ci	[1] = {
341162306a36Sopenharmony_ci		.name = "wcd938x-sdw-tx",
341262306a36Sopenharmony_ci		.capture = {
341362306a36Sopenharmony_ci			.stream_name = "WCD AIF1 Capture",
341462306a36Sopenharmony_ci			.rates = WCD938X_RATES_MASK,
341562306a36Sopenharmony_ci			.formats = SNDRV_PCM_FMTBIT_S16_LE,
341662306a36Sopenharmony_ci			.rate_min = 8000,
341762306a36Sopenharmony_ci			.rate_max = 192000,
341862306a36Sopenharmony_ci			.channels_min = 1,
341962306a36Sopenharmony_ci			.channels_max = 4,
342062306a36Sopenharmony_ci		},
342162306a36Sopenharmony_ci		.ops = &wcd938x_sdw_dai_ops,
342262306a36Sopenharmony_ci	},
342362306a36Sopenharmony_ci};
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_cistatic int wcd938x_bind(struct device *dev)
342662306a36Sopenharmony_ci{
342762306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
342862306a36Sopenharmony_ci	int ret;
342962306a36Sopenharmony_ci
343062306a36Sopenharmony_ci	ret = component_bind_all(dev, wcd938x);
343162306a36Sopenharmony_ci	if (ret) {
343262306a36Sopenharmony_ci		dev_err(dev, "%s: Slave bind failed, ret = %d\n",
343362306a36Sopenharmony_ci			__func__, ret);
343462306a36Sopenharmony_ci		return ret;
343562306a36Sopenharmony_ci	}
343662306a36Sopenharmony_ci
343762306a36Sopenharmony_ci	wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode);
343862306a36Sopenharmony_ci	if (!wcd938x->rxdev) {
343962306a36Sopenharmony_ci		dev_err(dev, "could not find slave with matching of node\n");
344062306a36Sopenharmony_ci		ret = -EINVAL;
344162306a36Sopenharmony_ci		goto err_unbind;
344262306a36Sopenharmony_ci	}
344362306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev);
344462306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x;
344562306a36Sopenharmony_ci
344662306a36Sopenharmony_ci	wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode);
344762306a36Sopenharmony_ci	if (!wcd938x->txdev) {
344862306a36Sopenharmony_ci		dev_err(dev, "could not find txslave with matching of node\n");
344962306a36Sopenharmony_ci		ret = -EINVAL;
345062306a36Sopenharmony_ci		goto err_put_rxdev;
345162306a36Sopenharmony_ci	}
345262306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev);
345362306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x;
345462306a36Sopenharmony_ci	wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev);
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci	/* As TX is main CSR reg interface, which should not be suspended first.
345762306a36Sopenharmony_ci	 * expicilty add the dependency link */
345862306a36Sopenharmony_ci	if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS |
345962306a36Sopenharmony_ci			    DL_FLAG_PM_RUNTIME)) {
346062306a36Sopenharmony_ci		dev_err(dev, "could not devlink tx and rx\n");
346162306a36Sopenharmony_ci		ret = -EINVAL;
346262306a36Sopenharmony_ci		goto err_put_txdev;
346362306a36Sopenharmony_ci	}
346462306a36Sopenharmony_ci
346562306a36Sopenharmony_ci	if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS |
346662306a36Sopenharmony_ci					DL_FLAG_PM_RUNTIME)) {
346762306a36Sopenharmony_ci		dev_err(dev, "could not devlink wcd and tx\n");
346862306a36Sopenharmony_ci		ret = -EINVAL;
346962306a36Sopenharmony_ci		goto err_remove_rxtx_link;
347062306a36Sopenharmony_ci	}
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci	if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS |
347362306a36Sopenharmony_ci					DL_FLAG_PM_RUNTIME)) {
347462306a36Sopenharmony_ci		dev_err(dev, "could not devlink wcd and rx\n");
347562306a36Sopenharmony_ci		ret = -EINVAL;
347662306a36Sopenharmony_ci		goto err_remove_tx_link;
347762306a36Sopenharmony_ci	}
347862306a36Sopenharmony_ci
347962306a36Sopenharmony_ci	wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL);
348062306a36Sopenharmony_ci	if (!wcd938x->regmap) {
348162306a36Sopenharmony_ci		dev_err(dev, "could not get TX device regmap\n");
348262306a36Sopenharmony_ci		ret = -EINVAL;
348362306a36Sopenharmony_ci		goto err_remove_rx_link;
348462306a36Sopenharmony_ci	}
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_ci	ret = wcd938x_irq_init(wcd938x, dev);
348762306a36Sopenharmony_ci	if (ret) {
348862306a36Sopenharmony_ci		dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret);
348962306a36Sopenharmony_ci		goto err_remove_rx_link;
349062306a36Sopenharmony_ci	}
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq;
349362306a36Sopenharmony_ci	wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq;
349462306a36Sopenharmony_ci
349562306a36Sopenharmony_ci	ret = wcd938x_set_micbias_data(wcd938x);
349662306a36Sopenharmony_ci	if (ret < 0) {
349762306a36Sopenharmony_ci		dev_err(dev, "%s: bad micbias pdata\n", __func__);
349862306a36Sopenharmony_ci		goto err_remove_rx_link;
349962306a36Sopenharmony_ci	}
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_ci	ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x,
350262306a36Sopenharmony_ci					 wcd938x_dais, ARRAY_SIZE(wcd938x_dais));
350362306a36Sopenharmony_ci	if (ret) {
350462306a36Sopenharmony_ci		dev_err(dev, "%s: Codec registration failed\n",
350562306a36Sopenharmony_ci				__func__);
350662306a36Sopenharmony_ci		goto err_remove_rx_link;
350762306a36Sopenharmony_ci	}
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci	return 0;
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_cierr_remove_rx_link:
351262306a36Sopenharmony_ci	device_link_remove(dev, wcd938x->rxdev);
351362306a36Sopenharmony_cierr_remove_tx_link:
351462306a36Sopenharmony_ci	device_link_remove(dev, wcd938x->txdev);
351562306a36Sopenharmony_cierr_remove_rxtx_link:
351662306a36Sopenharmony_ci	device_link_remove(wcd938x->rxdev, wcd938x->txdev);
351762306a36Sopenharmony_cierr_put_txdev:
351862306a36Sopenharmony_ci	put_device(wcd938x->txdev);
351962306a36Sopenharmony_cierr_put_rxdev:
352062306a36Sopenharmony_ci	put_device(wcd938x->rxdev);
352162306a36Sopenharmony_cierr_unbind:
352262306a36Sopenharmony_ci	component_unbind_all(dev, wcd938x);
352362306a36Sopenharmony_ci
352462306a36Sopenharmony_ci	return ret;
352562306a36Sopenharmony_ci}
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_cistatic void wcd938x_unbind(struct device *dev)
352862306a36Sopenharmony_ci{
352962306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci	snd_soc_unregister_component(dev);
353262306a36Sopenharmony_ci	device_link_remove(dev, wcd938x->txdev);
353362306a36Sopenharmony_ci	device_link_remove(dev, wcd938x->rxdev);
353462306a36Sopenharmony_ci	device_link_remove(wcd938x->rxdev, wcd938x->txdev);
353562306a36Sopenharmony_ci	put_device(wcd938x->txdev);
353662306a36Sopenharmony_ci	put_device(wcd938x->rxdev);
353762306a36Sopenharmony_ci	component_unbind_all(dev, wcd938x);
353862306a36Sopenharmony_ci}
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_cistatic const struct component_master_ops wcd938x_comp_ops = {
354162306a36Sopenharmony_ci	.bind   = wcd938x_bind,
354262306a36Sopenharmony_ci	.unbind = wcd938x_unbind,
354362306a36Sopenharmony_ci};
354462306a36Sopenharmony_ci
354562306a36Sopenharmony_cistatic int wcd938x_add_slave_components(struct wcd938x_priv *wcd938x,
354662306a36Sopenharmony_ci					struct device *dev,
354762306a36Sopenharmony_ci					struct component_match **matchptr)
354862306a36Sopenharmony_ci{
354962306a36Sopenharmony_ci	struct device_node *np;
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_ci	np = dev->of_node;
355262306a36Sopenharmony_ci
355362306a36Sopenharmony_ci	wcd938x->rxnode = of_parse_phandle(np, "qcom,rx-device", 0);
355462306a36Sopenharmony_ci	if (!wcd938x->rxnode) {
355562306a36Sopenharmony_ci		dev_err(dev, "%s: Rx-device node not defined\n", __func__);
355662306a36Sopenharmony_ci		return -ENODEV;
355762306a36Sopenharmony_ci	}
355862306a36Sopenharmony_ci
355962306a36Sopenharmony_ci	of_node_get(wcd938x->rxnode);
356062306a36Sopenharmony_ci	component_match_add_release(dev, matchptr, component_release_of,
356162306a36Sopenharmony_ci				    component_compare_of, wcd938x->rxnode);
356262306a36Sopenharmony_ci
356362306a36Sopenharmony_ci	wcd938x->txnode = of_parse_phandle(np, "qcom,tx-device", 0);
356462306a36Sopenharmony_ci	if (!wcd938x->txnode) {
356562306a36Sopenharmony_ci		dev_err(dev, "%s: Tx-device node not defined\n", __func__);
356662306a36Sopenharmony_ci		return -ENODEV;
356762306a36Sopenharmony_ci	}
356862306a36Sopenharmony_ci	of_node_get(wcd938x->txnode);
356962306a36Sopenharmony_ci	component_match_add_release(dev, matchptr, component_release_of,
357062306a36Sopenharmony_ci				    component_compare_of, wcd938x->txnode);
357162306a36Sopenharmony_ci	return 0;
357262306a36Sopenharmony_ci}
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_cistatic int wcd938x_probe(struct platform_device *pdev)
357562306a36Sopenharmony_ci{
357662306a36Sopenharmony_ci	struct component_match *match = NULL;
357762306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = NULL;
357862306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
357962306a36Sopenharmony_ci	int ret;
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci	wcd938x = devm_kzalloc(dev, sizeof(struct wcd938x_priv),
358262306a36Sopenharmony_ci				GFP_KERNEL);
358362306a36Sopenharmony_ci	if (!wcd938x)
358462306a36Sopenharmony_ci		return -ENOMEM;
358562306a36Sopenharmony_ci
358662306a36Sopenharmony_ci	dev_set_drvdata(dev, wcd938x);
358762306a36Sopenharmony_ci	mutex_init(&wcd938x->micb_lock);
358862306a36Sopenharmony_ci
358962306a36Sopenharmony_ci	ret = wcd938x_populate_dt_data(wcd938x, dev);
359062306a36Sopenharmony_ci	if (ret) {
359162306a36Sopenharmony_ci		dev_err(dev, "%s: Fail to obtain platform data\n", __func__);
359262306a36Sopenharmony_ci		return ret;
359362306a36Sopenharmony_ci	}
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci	ret = wcd938x_add_slave_components(wcd938x, dev, &match);
359662306a36Sopenharmony_ci	if (ret)
359762306a36Sopenharmony_ci		goto err_disable_regulators;
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci	wcd938x_reset(wcd938x);
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci	ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match);
360262306a36Sopenharmony_ci	if (ret)
360362306a36Sopenharmony_ci		goto err_disable_regulators;
360462306a36Sopenharmony_ci
360562306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, 1000);
360662306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
360762306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
360862306a36Sopenharmony_ci	pm_runtime_set_active(dev);
360962306a36Sopenharmony_ci	pm_runtime_enable(dev);
361062306a36Sopenharmony_ci	pm_runtime_idle(dev);
361162306a36Sopenharmony_ci
361262306a36Sopenharmony_ci	return 0;
361362306a36Sopenharmony_ci
361462306a36Sopenharmony_cierr_disable_regulators:
361562306a36Sopenharmony_ci	regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies);
361662306a36Sopenharmony_ci	regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci	return ret;
361962306a36Sopenharmony_ci}
362062306a36Sopenharmony_ci
362162306a36Sopenharmony_cistatic void wcd938x_remove(struct platform_device *pdev)
362262306a36Sopenharmony_ci{
362362306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
362462306a36Sopenharmony_ci	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	component_master_del(dev, &wcd938x_comp_ops);
362762306a36Sopenharmony_ci
362862306a36Sopenharmony_ci	pm_runtime_disable(dev);
362962306a36Sopenharmony_ci	pm_runtime_set_suspended(dev);
363062306a36Sopenharmony_ci	pm_runtime_dont_use_autosuspend(dev);
363162306a36Sopenharmony_ci
363262306a36Sopenharmony_ci	regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies);
363362306a36Sopenharmony_ci	regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);
363462306a36Sopenharmony_ci}
363562306a36Sopenharmony_ci
363662306a36Sopenharmony_ci#if defined(CONFIG_OF)
363762306a36Sopenharmony_cistatic const struct of_device_id wcd938x_dt_match[] = {
363862306a36Sopenharmony_ci	{ .compatible = "qcom,wcd9380-codec" },
363962306a36Sopenharmony_ci	{ .compatible = "qcom,wcd9385-codec" },
364062306a36Sopenharmony_ci	{}
364162306a36Sopenharmony_ci};
364262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, wcd938x_dt_match);
364362306a36Sopenharmony_ci#endif
364462306a36Sopenharmony_ci
364562306a36Sopenharmony_cistatic struct platform_driver wcd938x_codec_driver = {
364662306a36Sopenharmony_ci	.probe = wcd938x_probe,
364762306a36Sopenharmony_ci	.remove_new = wcd938x_remove,
364862306a36Sopenharmony_ci	.driver = {
364962306a36Sopenharmony_ci		.name = "wcd938x_codec",
365062306a36Sopenharmony_ci		.of_match_table = of_match_ptr(wcd938x_dt_match),
365162306a36Sopenharmony_ci		.suppress_bind_attrs = true,
365262306a36Sopenharmony_ci	},
365362306a36Sopenharmony_ci};
365462306a36Sopenharmony_ci
365562306a36Sopenharmony_cimodule_platform_driver(wcd938x_codec_driver);
365662306a36Sopenharmony_ciMODULE_DESCRIPTION("WCD938X Codec driver");
365762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
3658