brintos

brintos / linux-shallow public Read only

0
0
Text · 113.9 KiB · f2a4f32 Raw
3610 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.3 4#include <linux/module.h>5#include <linux/slab.h>6#include <linux/platform_device.h>7#include <linux/device.h>8#include <linux/delay.h>9#include <linux/gpio/consumer.h>10#include <linux/kernel.h>11#include <linux/pm_runtime.h>12#include <linux/component.h>13#include <sound/tlv.h>14#include <linux/of_gpio.h>15#include <linux/of.h>16#include <sound/jack.h>17#include <sound/pcm.h>18#include <sound/pcm_params.h>19#include <linux/regmap.h>20#include <sound/soc.h>21#include <sound/soc-dapm.h>22#include <linux/regulator/consumer.h>23 24#include "wcd-clsh-v2.h"25#include "wcd-mbhc-v2.h"26#include "wcd938x.h"27 28#define WCD938X_MAX_MICBIAS		(4)29#define WCD938X_MAX_SUPPLY		(4)30#define WCD938X_MBHC_MAX_BUTTONS	(8)31#define TX_ADC_MAX			(4)32 33#define WCD938X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\34			    SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\35			    SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)36/* Fractional Rates */37#define WCD938X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\38				 SNDRV_PCM_RATE_176400)39#define WCD938X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \40				    SNDRV_PCM_FMTBIT_S24_LE)41#define SWR_CLK_RATE_0P6MHZ		(600000)42#define SWR_CLK_RATE_1P2MHZ		(1200000)43#define SWR_CLK_RATE_2P4MHZ		(2400000)44#define SWR_CLK_RATE_4P8MHZ		(4800000)45#define SWR_CLK_RATE_9P6MHZ		(9600000)46#define SWR_CLK_RATE_11P2896MHZ		(1128960)47 48#define EAR_RX_PATH_AUX			(1)49 50#define ADC_MODE_VAL_HIFI		0x0151#define ADC_MODE_VAL_LO_HIF		0x0252#define ADC_MODE_VAL_NORMAL		0x0353#define ADC_MODE_VAL_LP			0x0554#define ADC_MODE_VAL_ULP1		0x0955#define ADC_MODE_VAL_ULP2		0x0B56 57/* Z value defined in milliohm */58#define WCD938X_ZDET_VAL_32             (32000)59#define WCD938X_ZDET_VAL_400            (400000)60#define WCD938X_ZDET_VAL_1200           (1200000)61#define WCD938X_ZDET_VAL_100K           (100000000)62/* Z floating defined in ohms */63#define WCD938X_ZDET_FLOATING_IMPEDANCE	(0x0FFFFFFE)64#define WCD938X_ZDET_NUM_MEASUREMENTS   (900)65#define WCD938X_MBHC_GET_C1(c)          ((c & 0xC000) >> 14)66#define WCD938X_MBHC_GET_X1(x)          (x & 0x3FFF)67/* Z value compared in milliOhm */68#define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000))69#define WCD938X_MBHC_ZDET_CONST         (86 * 16384)70#define WCD_MBHC_HS_V_MAX           160071 72#define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \73{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \74	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\75		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\76	.tlv.p = (tlv_array), \77	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\78	.put = wcd938x_ear_pa_put_gain, \79	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }80 81enum {82	WCD9380 = 0,83	WCD9385 = 5,84};85 86enum {87	/* INTR_CTRL_INT_MASK_0 */88	WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0,89	WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET,90	WCD938X_IRQ_MBHC_ELECT_INS_REM_DET,91	WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET,92	WCD938X_IRQ_MBHC_SW_DET,93	WCD938X_IRQ_HPHR_OCP_INT,94	WCD938X_IRQ_HPHR_CNP_INT,95	WCD938X_IRQ_HPHL_OCP_INT,96 97	/* INTR_CTRL_INT_MASK_1 */98	WCD938X_IRQ_HPHL_CNP_INT,99	WCD938X_IRQ_EAR_CNP_INT,100	WCD938X_IRQ_EAR_SCD_INT,101	WCD938X_IRQ_AUX_CNP_INT,102	WCD938X_IRQ_AUX_SCD_INT,103	WCD938X_IRQ_HPHL_PDM_WD_INT,104	WCD938X_IRQ_HPHR_PDM_WD_INT,105	WCD938X_IRQ_AUX_PDM_WD_INT,106 107	/* INTR_CTRL_INT_MASK_2 */108	WCD938X_IRQ_LDORT_SCD_INT,109	WCD938X_IRQ_MBHC_MOISTURE_INT,110	WCD938X_IRQ_HPHL_SURGE_DET_INT,111	WCD938X_IRQ_HPHR_SURGE_DET_INT,112	WCD938X_NUM_IRQS,113};114 115enum {116	WCD_ADC1 = 0,117	WCD_ADC2,118	WCD_ADC3,119	WCD_ADC4,120	ALLOW_BUCK_DISABLE,121	HPH_COMP_DELAY,122	HPH_PA_DELAY,123	AMIC2_BCS_ENABLE,124	WCD_SUPPLIES_LPM_MODE,125};126 127enum {128	ADC_MODE_INVALID = 0,129	ADC_MODE_HIFI,130	ADC_MODE_LO_HIF,131	ADC_MODE_NORMAL,132	ADC_MODE_LP,133	ADC_MODE_ULP1,134	ADC_MODE_ULP2,135};136 137enum {138	AIF1_PB = 0,139	AIF1_CAP,140	NUM_CODEC_DAIS,141};142 143static u8 tx_mode_bit[] = {144	[ADC_MODE_INVALID] = 0x00,145	[ADC_MODE_HIFI] = 0x01,146	[ADC_MODE_LO_HIF] = 0x02,147	[ADC_MODE_NORMAL] = 0x04,148	[ADC_MODE_LP] = 0x08,149	[ADC_MODE_ULP1] = 0x10,150	[ADC_MODE_ULP2] = 0x20,151};152 153struct wcd938x_priv {154	struct sdw_slave *tx_sdw_dev;155	struct wcd938x_sdw_priv *sdw_priv[NUM_CODEC_DAIS];156	struct device *txdev;157	struct device *rxdev;158	struct device_node *rxnode, *txnode;159	struct regmap *regmap;160	struct mutex micb_lock;161	/* mbhc module */162	struct wcd_mbhc *wcd_mbhc;163	struct wcd_mbhc_config mbhc_cfg;164	struct wcd_mbhc_intr intr_ids;165	struct wcd_clsh_ctrl *clsh_info;166	struct irq_domain *virq;167	struct regmap_irq_chip *wcd_regmap_irq_chip;168	struct regmap_irq_chip_data *irq_chip;169	struct regulator_bulk_data supplies[WCD938X_MAX_SUPPLY];170	struct snd_soc_jack *jack;171	unsigned long status_mask;172	s32 micb_ref[WCD938X_MAX_MICBIAS];173	s32 pullup_ref[WCD938X_MAX_MICBIAS];174	u32 hph_mode;175	u32 tx_mode[TX_ADC_MAX];176	int flyback_cur_det_disable;177	int ear_rx_path;178	int variant;179	int reset_gpio;180	struct gpio_desc *us_euro_gpio;181	u32 micb1_mv;182	u32 micb2_mv;183	u32 micb3_mv;184	u32 micb4_mv;185	int hphr_pdm_wd_int;186	int hphl_pdm_wd_int;187	int aux_pdm_wd_int;188	bool comp1_enable;189	bool comp2_enable;190	bool ldoh;191};192 193static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);194static const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, 0);195static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);196 197struct wcd938x_mbhc_zdet_param {198	u16 ldo_ctl;199	u16 noff;200	u16 nshift;201	u16 btn5;202	u16 btn6;203	u16 btn7;204};205 206static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {207	WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80),208	WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40),209	WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20),210	WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30),211	WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08),212	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F),213	WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04),214	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10),215	WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08),216	WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01),217	WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06),218	WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80),219	WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F),220	WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03),221	WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03),222	WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08),223	WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10),224	WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20),225	WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80),226	WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40),227	WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10),228	WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07),229	WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70),230	WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF),231	WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0),232	WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF),233	WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40),234	WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80),235	WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0),236	WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10),237	WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02),238	WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01),239	WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70),240	WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20),241	WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40),242	WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10),243	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01),244	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01),245	WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80),246	WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20),247	WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08),248	WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40),249	WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80),250	WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF),251	WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F),252	WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10),253	WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04),254	WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02),255};256 257static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = {258	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),259	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02),260	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04),261	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08),262	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_SW_DET, 0, 0x10),263	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_OCP_INT, 0, 0x20),264	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_CNP_INT, 0, 0x40),265	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_OCP_INT, 0, 0x80),266	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_CNP_INT, 1, 0x01),267	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_CNP_INT, 1, 0x02),268	REGMAP_IRQ_REG(WCD938X_IRQ_EAR_SCD_INT, 1, 0x04),269	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_CNP_INT, 1, 0x08),270	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_SCD_INT, 1, 0x10),271	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_PDM_WD_INT, 1, 0x20),272	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_PDM_WD_INT, 1, 0x40),273	REGMAP_IRQ_REG(WCD938X_IRQ_AUX_PDM_WD_INT, 1, 0x80),274	REGMAP_IRQ_REG(WCD938X_IRQ_LDORT_SCD_INT, 2, 0x01),275	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_MOISTURE_INT, 2, 0x02),276	REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_SURGE_DET_INT, 2, 0x04),277	REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08),278};279 280static struct regmap_irq_chip wcd938x_regmap_irq_chip = {281	.name = "wcd938x",282	.irqs = wcd938x_irqs,283	.num_irqs = ARRAY_SIZE(wcd938x_irqs),284	.num_regs = 3,285	.status_base = WCD938X_DIGITAL_INTR_STATUS_0,286	.mask_base = WCD938X_DIGITAL_INTR_MASK_0,287	.ack_base = WCD938X_DIGITAL_INTR_CLEAR_0,288	.use_ack = 1,289	.runtime_pm = true,290	.irq_drv_data = NULL,291};292 293static int wcd938x_get_clk_rate(int mode)294{295	int rate;296 297	switch (mode) {298	case ADC_MODE_ULP2:299		rate = SWR_CLK_RATE_0P6MHZ;300		break;301	case ADC_MODE_ULP1:302		rate = SWR_CLK_RATE_1P2MHZ;303		break;304	case ADC_MODE_LP:305		rate = SWR_CLK_RATE_4P8MHZ;306		break;307	case ADC_MODE_NORMAL:308	case ADC_MODE_LO_HIF:309	case ADC_MODE_HIFI:310	case ADC_MODE_INVALID:311	default:312		rate = SWR_CLK_RATE_9P6MHZ;313		break;314	}315 316	return rate;317}318 319static int wcd938x_set_swr_clk_rate(struct snd_soc_component *component, int rate, int bank)320{321	u8 mask = (bank ? 0xF0 : 0x0F);322	u8 val = 0;323 324	switch (rate) {325	case SWR_CLK_RATE_0P6MHZ:326		val = (bank ? 0x60 : 0x06);327		break;328	case SWR_CLK_RATE_1P2MHZ:329		val = (bank ? 0x50 : 0x05);330		break;331	case SWR_CLK_RATE_2P4MHZ:332		val = (bank ? 0x30 : 0x03);333		break;334	case SWR_CLK_RATE_4P8MHZ:335		val = (bank ? 0x10 : 0x01);336		break;337	case SWR_CLK_RATE_9P6MHZ:338	default:339		val = 0x00;340		break;341	}342	snd_soc_component_update_bits(component, WCD938X_DIGITAL_SWR_TX_CLK_RATE,343				      mask, val);344 345	return 0;346}347 348static int wcd938x_io_init(struct wcd938x_priv *wcd938x)349{350	struct regmap *rm = wcd938x->regmap;351 352	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x0E, 0x0E);353	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x80, 0x80);354	/* 1 msec delay as per HW requirement */355	usleep_range(1000, 1010);356	regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x40, 0x40);357	/* 1 msec delay as per HW requirement */358	usleep_range(1000, 1010);359	regmap_update_bits(rm, WCD938X_LDORXTX_CONFIG, 0x10, 0x00);360	regmap_update_bits(rm, WCD938X_BIAS_VBG_FINE_ADJ,361								0xF0, 0x80);362	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x80, 0x80);363	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x40);364	/* 10 msec delay as per HW requirement */365	usleep_range(10000, 10010);366 367	regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x00);368	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL,369				      0xF0, 0x00);370	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW,371				      0x1F, 0x15);372	regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW,373				      0x1F, 0x15);374	regmap_update_bits(rm, WCD938X_HPH_REFBUFF_UHQA_CTL,375				      0xC0, 0x80);376	regmap_update_bits(rm, WCD938X_DIGITAL_CDC_DMIC_CTL,377				      0x02, 0x02);378 379	regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP,380			   0xFF, 0x14);381	regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP,382			   0x1F, 0x08);383 384	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0xFF, 0x55);385	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0xFF, 0x44);386	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0xFF, 0x11);387	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0xFF, 0x00);388	regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0xFF, 0x00);389 390	/* Set Noise Filter Resistor value */391	regmap_update_bits(rm, WCD938X_MICB1_TEST_CTL_1, 0xE0, 0xE0);392	regmap_update_bits(rm, WCD938X_MICB2_TEST_CTL_1, 0xE0, 0xE0);393	regmap_update_bits(rm, WCD938X_MICB3_TEST_CTL_1, 0xE0, 0xE0);394	regmap_update_bits(rm, WCD938X_MICB4_TEST_CTL_1, 0xE0, 0xE0);395 396	regmap_update_bits(rm, WCD938X_TX_3_4_TEST_BLK_EN2, 0x01, 0x00);397	regmap_update_bits(rm, WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);398 399	return 0;400 401}402 403static int wcd938x_sdw_connect_port(const struct wcd938x_sdw_ch_info *ch_info,404				    struct sdw_port_config *port_config,405				    u8 enable)406{407	u8 ch_mask, port_num;408 409	port_num = ch_info->port_num;410	ch_mask = ch_info->ch_mask;411 412	port_config->num = port_num;413 414	if (enable)415		port_config->ch_mask |= ch_mask;416	else417		port_config->ch_mask &= ~ch_mask;418 419	return 0;420}421 422static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 port_num, u8 ch_id, u8 enable)423{424	return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id],425					&wcd->port_config[port_num - 1],426					enable);427}428 429static int wcd938x_codec_enable_rxclk(struct snd_soc_dapm_widget *w,430				      struct snd_kcontrol *kcontrol,431				      int event)432{433	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);434 435	switch (event) {436	case SND_SOC_DAPM_PRE_PMU:437		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,438				WCD938X_ANA_RX_CLK_EN_MASK, 1);439		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,440				WCD938X_RX_BIAS_EN_MASK, 1);441		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX0_CTL,442				WCD938X_DEM_DITHER_ENABLE_MASK, 0);443		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX1_CTL,444				WCD938X_DEM_DITHER_ENABLE_MASK, 0);445		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX2_CTL,446				WCD938X_DEM_DITHER_ENABLE_MASK, 0);447		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,448				WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 1);449		snd_soc_component_write_field(component, WCD938X_AUX_AUXPA,450					      WCD938X_AUXPA_CLK_EN_MASK, 1);451		break;452	case SND_SOC_DAPM_POST_PMD:453		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,454				WCD938X_VNEG_EN_MASK, 0);455		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,456				WCD938X_VPOS_EN_MASK, 0);457		snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,458				WCD938X_RX_BIAS_EN_MASK, 0);459		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,460				WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 0);461		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,462				WCD938X_ANA_RX_CLK_EN_MASK, 0);463		break;464	}465	return 0;466}467 468static int wcd938x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,469					struct snd_kcontrol *kcontrol,470					int event)471{472	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);473	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);474 475	switch (event) {476	case SND_SOC_DAPM_PRE_PMU:477		snd_soc_component_write_field(component,478				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,479				WCD938X_RXD0_CLK_EN_MASK, 0x01);480		snd_soc_component_write_field(component,481				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,482				WCD938X_HPHL_RX_EN_MASK, 1);483		snd_soc_component_write_field(component,484				WCD938X_HPH_RDAC_CLK_CTL1,485				WCD938X_CHOP_CLK_EN_MASK, 0);486		break;487	case SND_SOC_DAPM_POST_PMU:488		snd_soc_component_write_field(component,489				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L,490				WCD938X_HPH_RES_DIV_MASK, 0x02);491		if (wcd938x->comp1_enable) {492			snd_soc_component_write_field(component,493				WCD938X_DIGITAL_CDC_COMP_CTL_0,494				WCD938X_HPHL_COMP_EN_MASK, 1);495			/* 5msec compander delay as per HW requirement */496			if (!wcd938x->comp2_enable || (snd_soc_component_read(component,497							 WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x01))498				usleep_range(5000, 5010);499			snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,500					      WCD938X_AUTOCHOP_TIMER_EN, 0);501		} else {502			snd_soc_component_write_field(component,503					WCD938X_DIGITAL_CDC_COMP_CTL_0,504					WCD938X_HPHL_COMP_EN_MASK, 0);505			snd_soc_component_write_field(component,506					WCD938X_HPH_L_EN,507					WCD938X_GAIN_SRC_SEL_MASK,508					WCD938X_GAIN_SRC_SEL_REGISTER);509 510		}511		break;512	case SND_SOC_DAPM_POST_PMD:513		snd_soc_component_write_field(component,514			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,515			WCD938X_HPH_RES_DIV_MASK, 0x1);516		break;517	}518 519	return 0;520}521 522static int wcd938x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,523					struct snd_kcontrol *kcontrol,524					int event)525{526	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);527	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);528 529	switch (event) {530	case SND_SOC_DAPM_PRE_PMU:531		snd_soc_component_write_field(component,532				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,533				WCD938X_RXD1_CLK_EN_MASK, 1);534		snd_soc_component_write_field(component,535				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,536				WCD938X_HPHR_RX_EN_MASK, 1);537		snd_soc_component_write_field(component,538				WCD938X_HPH_RDAC_CLK_CTL1,539				WCD938X_CHOP_CLK_EN_MASK, 0);540		break;541	case SND_SOC_DAPM_POST_PMU:542		snd_soc_component_write_field(component,543				WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,544				WCD938X_HPH_RES_DIV_MASK, 0x02);545		if (wcd938x->comp2_enable) {546			snd_soc_component_write_field(component,547				WCD938X_DIGITAL_CDC_COMP_CTL_0,548				WCD938X_HPHR_COMP_EN_MASK, 1);549			/* 5msec compander delay as per HW requirement */550			if (!wcd938x->comp1_enable ||551				(snd_soc_component_read(component,552					WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x02))553				usleep_range(5000, 5010);554			snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,555					      WCD938X_AUTOCHOP_TIMER_EN, 0);556		} else {557			snd_soc_component_write_field(component,558					WCD938X_DIGITAL_CDC_COMP_CTL_0,559					WCD938X_HPHR_COMP_EN_MASK, 0);560			snd_soc_component_write_field(component,561					WCD938X_HPH_R_EN,562					WCD938X_GAIN_SRC_SEL_MASK,563					WCD938X_GAIN_SRC_SEL_REGISTER);564		}565		break;566	case SND_SOC_DAPM_POST_PMD:567		snd_soc_component_write_field(component,568			WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R,569			WCD938X_HPH_RES_DIV_MASK, 0x01);570		break;571	}572 573	return 0;574}575 576static int wcd938x_codec_ear_dac_event(struct snd_soc_dapm_widget *w,577				       struct snd_kcontrol *kcontrol,578				       int event)579{580	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);581	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);582 583	switch (event) {584	case SND_SOC_DAPM_PRE_PMU:585		wcd938x->ear_rx_path =586			snd_soc_component_read(587				component, WCD938X_DIGITAL_CDC_EAR_PATH_CTL);588		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) {589			snd_soc_component_write_field(component,590				WCD938X_EAR_EAR_DAC_CON,591				WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 0);592			snd_soc_component_write_field(component,593				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,594				WCD938X_AUX_EN_MASK, 1);595			snd_soc_component_write_field(component,596				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,597				WCD938X_RXD2_CLK_EN_MASK, 1);598			snd_soc_component_write_field(component,599				WCD938X_ANA_EAR_COMPANDER_CTL,600				WCD938X_GAIN_OVRD_REG_MASK, 1);601		} else {602			snd_soc_component_write_field(component,603				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,604				WCD938X_HPHL_RX_EN_MASK, 1);605			snd_soc_component_write_field(component,606				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,607				WCD938X_RXD0_CLK_EN_MASK, 1);608			if (wcd938x->comp1_enable)609				snd_soc_component_write_field(component,610					WCD938X_DIGITAL_CDC_COMP_CTL_0,611					WCD938X_HPHL_COMP_EN_MASK, 1);612		}613		/* 5 msec delay as per HW requirement */614		usleep_range(5000, 5010);615		if (wcd938x->flyback_cur_det_disable == 0)616			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,617						      WCD938X_EN_CUR_DET_MASK, 0);618		wcd938x->flyback_cur_det_disable++;619		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,620			     WCD_CLSH_EVENT_PRE_DAC,621			     WCD_CLSH_STATE_EAR,622			     wcd938x->hph_mode);623		break;624	case SND_SOC_DAPM_POST_PMD:625		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) {626			snd_soc_component_write_field(component,627				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,628				WCD938X_AUX_EN_MASK, 0);629			snd_soc_component_write_field(component,630				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,631				WCD938X_RXD2_CLK_EN_MASK, 0);632		} else {633			snd_soc_component_write_field(component,634				WCD938X_DIGITAL_CDC_HPH_GAIN_CTL,635				WCD938X_HPHL_RX_EN_MASK, 0);636			snd_soc_component_write_field(component,637				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,638				WCD938X_RXD0_CLK_EN_MASK, 0);639			if (wcd938x->comp1_enable)640				snd_soc_component_write_field(component,641					WCD938X_DIGITAL_CDC_COMP_CTL_0,642					WCD938X_HPHL_COMP_EN_MASK, 0);643		}644		snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,645					      WCD938X_GAIN_OVRD_REG_MASK, 0);646		snd_soc_component_write_field(component,647				WCD938X_EAR_EAR_DAC_CON,648				WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 1);649		break;650	}651	return 0;652 653}654 655static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w,656				       struct snd_kcontrol *kcontrol,657				       int event)658{659	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);660	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);661 662	switch (event) {663	case SND_SOC_DAPM_PRE_PMU:664		snd_soc_component_write_field(component,665				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,666				WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 1);667		snd_soc_component_write_field(component,668				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,669				WCD938X_RXD2_CLK_EN_MASK, 1);670		snd_soc_component_write_field(component,671				WCD938X_DIGITAL_CDC_AUX_GAIN_CTL,672				WCD938X_AUX_EN_MASK, 1);673		if (wcd938x->flyback_cur_det_disable == 0)674			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,675						      WCD938X_EN_CUR_DET_MASK, 0);676		wcd938x->flyback_cur_det_disable++;677		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,678			     WCD_CLSH_EVENT_PRE_DAC,679			     WCD_CLSH_STATE_AUX,680			     wcd938x->hph_mode);681		break;682	case SND_SOC_DAPM_POST_PMD:683		snd_soc_component_write_field(component,684				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,685				WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0);686		break;687	}688	return 0;689 690}691 692static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,693					struct snd_kcontrol *kcontrol, int event)694{695	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);696	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);697	int hph_mode = wcd938x->hph_mode;698 699	switch (event) {700	case SND_SOC_DAPM_PRE_PMU:701		if (wcd938x->ldoh)702			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,703						      WCD938X_LDOH_EN_MASK, 1);704		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC,705					WCD_CLSH_STATE_HPHR, hph_mode);706		wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI);707 708		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||709		    hph_mode == CLS_H_ULP) {710			snd_soc_component_write_field(component,711				WCD938X_HPH_REFBUFF_LP_CTL,712				WCD938X_PREREF_FLIT_BYPASS_MASK, 1);713		}714		snd_soc_component_write_field(component, WCD938X_ANA_HPH,715					      WCD938X_HPHR_REF_EN_MASK, 1);716		wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode);717		/* 100 usec delay as per HW requirement */718		usleep_range(100, 110);719		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);720		snd_soc_component_write_field(component,721					      WCD938X_DIGITAL_PDM_WD_CTL1,722					      WCD938X_PDM_WD_EN_MASK, 0x3);723		break;724	case SND_SOC_DAPM_POST_PMU:725		/*726		 * 7ms sleep is required if compander is enabled as per727		 * HW requirement. If compander is disabled, then728		 * 20ms delay is required.729		 */730		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {731			if (!wcd938x->comp2_enable)732				usleep_range(20000, 20100);733			else734				usleep_range(7000, 7100);735 736			if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||737			    hph_mode == CLS_H_ULP)738				snd_soc_component_write_field(component,739						WCD938X_HPH_REFBUFF_LP_CTL,740						WCD938X_PREREF_FLIT_BYPASS_MASK, 0);741			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);742		}743		snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,744					      WCD938X_AUTOCHOP_TIMER_EN, 1);745		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||746			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)747			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,748					WCD938X_REGULATOR_MODE_MASK,749					WCD938X_REGULATOR_MODE_CLASS_AB);750		enable_irq(wcd938x->hphr_pdm_wd_int);751		break;752	case SND_SOC_DAPM_PRE_PMD:753		disable_irq_nosync(wcd938x->hphr_pdm_wd_int);754		/*755		 * 7ms sleep is required if compander is enabled as per756		 * HW requirement. If compander is disabled, then757		 * 20ms delay is required.758		 */759		if (!wcd938x->comp2_enable)760			usleep_range(20000, 20100);761		else762			usleep_range(7000, 7100);763		snd_soc_component_write_field(component, WCD938X_ANA_HPH,764					      WCD938X_HPHR_EN_MASK, 0);765		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,766					     WCD_EVENT_PRE_HPHR_PA_OFF);767		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);768		break;769	case SND_SOC_DAPM_POST_PMD:770		/*771		 * 7ms sleep is required if compander is enabled as per772		 * HW requirement. If compander is disabled, then773		 * 20ms delay is required.774		 */775		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {776			if (!wcd938x->comp2_enable)777				usleep_range(20000, 20100);778			else779				usleep_range(7000, 7100);780			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);781		}782		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,783					     WCD_EVENT_POST_HPHR_PA_OFF);784		snd_soc_component_write_field(component, WCD938X_ANA_HPH,785					      WCD938X_HPHR_REF_EN_MASK, 0);786		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1,787					      WCD938X_PDM_WD_EN_MASK, 0);788		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,789					WCD_CLSH_STATE_HPHR, hph_mode);790		if (wcd938x->ldoh)791			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,792						      WCD938X_LDOH_EN_MASK, 0);793		break;794	}795 796	return 0;797}798 799static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,800					struct snd_kcontrol *kcontrol, int event)801{802	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);803	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);804	int hph_mode = wcd938x->hph_mode;805 806	switch (event) {807	case SND_SOC_DAPM_PRE_PMU:808		if (wcd938x->ldoh)809			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,810						      WCD938X_LDOH_EN_MASK, 1);811		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC,812					WCD_CLSH_STATE_HPHL, hph_mode);813		wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI);814		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||815		    hph_mode == CLS_H_ULP) {816			snd_soc_component_write_field(component,817					WCD938X_HPH_REFBUFF_LP_CTL,818					WCD938X_PREREF_FLIT_BYPASS_MASK, 1);819		}820		snd_soc_component_write_field(component, WCD938X_ANA_HPH,821					      WCD938X_HPHL_REF_EN_MASK, 1);822		wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode);823		/* 100 usec delay as per HW requirement */824		usleep_range(100, 110);825		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);826		snd_soc_component_write_field(component,827					WCD938X_DIGITAL_PDM_WD_CTL0,828					WCD938X_PDM_WD_EN_MASK, 0x3);829		break;830	case SND_SOC_DAPM_POST_PMU:831		/*832		 * 7ms sleep is required if compander is enabled as per833		 * HW requirement. If compander is disabled, then834		 * 20ms delay is required.835		 */836		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {837			if (!wcd938x->comp1_enable)838				usleep_range(20000, 20100);839			else840				usleep_range(7000, 7100);841			if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||842			    hph_mode == CLS_H_ULP)843				snd_soc_component_write_field(component,844					WCD938X_HPH_REFBUFF_LP_CTL,845					WCD938X_PREREF_FLIT_BYPASS_MASK, 0);846			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);847		}848 849		snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1,850					      WCD938X_AUTOCHOP_TIMER_EN, 1);851		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||852			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)853			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,854					WCD938X_REGULATOR_MODE_MASK,855					WCD938X_REGULATOR_MODE_CLASS_AB);856		enable_irq(wcd938x->hphl_pdm_wd_int);857		break;858	case SND_SOC_DAPM_PRE_PMD:859		disable_irq_nosync(wcd938x->hphl_pdm_wd_int);860		/*861		 * 7ms sleep is required if compander is enabled as per862		 * HW requirement. If compander is disabled, then863		 * 20ms delay is required.864		 */865		if (!wcd938x->comp1_enable)866			usleep_range(20000, 20100);867		else868			usleep_range(7000, 7100);869		snd_soc_component_write_field(component, WCD938X_ANA_HPH,870					      WCD938X_HPHL_EN_MASK, 0);871		wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF);872		set_bit(HPH_PA_DELAY, &wcd938x->status_mask);873		break;874	case SND_SOC_DAPM_POST_PMD:875		/*876		 * 7ms sleep is required if compander is enabled as per877		 * HW requirement. If compander is disabled, then878		 * 20ms delay is required.879		 */880		if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {881			if (!wcd938x->comp1_enable)882				usleep_range(21000, 21100);883			else884				usleep_range(7000, 7100);885			clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);886		}887		wcd_mbhc_event_notify(wcd938x->wcd_mbhc,888					     WCD_EVENT_POST_HPHL_PA_OFF);889		snd_soc_component_write_field(component, WCD938X_ANA_HPH,890					      WCD938X_HPHL_REF_EN_MASK, 0);891		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,892					      WCD938X_PDM_WD_EN_MASK, 0);893		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,894					WCD_CLSH_STATE_HPHL, hph_mode);895		if (wcd938x->ldoh)896			snd_soc_component_write_field(component, WCD938X_LDOH_MODE,897						      WCD938X_LDOH_EN_MASK, 0);898		break;899	}900 901	return 0;902}903 904static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,905				       struct snd_kcontrol *kcontrol, int event)906{907	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);908	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);909	int hph_mode = wcd938x->hph_mode;910 911	switch (event) {912	case SND_SOC_DAPM_PRE_PMU:913		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,914					      WCD938X_AUX_PDM_WD_EN_MASK, 1);915		break;916	case SND_SOC_DAPM_POST_PMU:917		/* 1 msec delay as per HW requirement */918		usleep_range(1000, 1010);919		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||920			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)921			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,922					WCD938X_REGULATOR_MODE_MASK,923					WCD938X_REGULATOR_MODE_CLASS_AB);924		enable_irq(wcd938x->aux_pdm_wd_int);925		break;926	case SND_SOC_DAPM_PRE_PMD:927		disable_irq_nosync(wcd938x->aux_pdm_wd_int);928		break;929	case SND_SOC_DAPM_POST_PMD:930		/* 1 msec delay as per HW requirement */931		usleep_range(1000, 1010);932		snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,933					      WCD938X_AUX_PDM_WD_EN_MASK, 0);934		wcd_clsh_ctrl_set_state(wcd938x->clsh_info,935			     WCD_CLSH_EVENT_POST_PA,936			     WCD_CLSH_STATE_AUX,937			     hph_mode);938 939		wcd938x->flyback_cur_det_disable--;940		if (wcd938x->flyback_cur_det_disable == 0)941			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,942						      WCD938X_EN_CUR_DET_MASK, 1);943		break;944	}945	return 0;946}947 948static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,949				       struct snd_kcontrol *kcontrol, int event)950{951	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);952	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);953	int hph_mode = wcd938x->hph_mode;954 955	switch (event) {956	case SND_SOC_DAPM_PRE_PMU:957		/*958		 * Enable watchdog interrupt for HPHL or AUX959		 * depending on mux value960		 */961		wcd938x->ear_rx_path = snd_soc_component_read(component,962							      WCD938X_DIGITAL_CDC_EAR_PATH_CTL);963		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)964			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,965					      WCD938X_AUX_PDM_WD_EN_MASK, 1);966		else967			snd_soc_component_write_field(component,968						      WCD938X_DIGITAL_PDM_WD_CTL0,969						      WCD938X_PDM_WD_EN_MASK, 0x3);970		if (!wcd938x->comp1_enable)971			snd_soc_component_write_field(component,972						      WCD938X_ANA_EAR_COMPANDER_CTL,973						      WCD938X_GAIN_OVRD_REG_MASK, 1);974 975		break;976	case SND_SOC_DAPM_POST_PMU:977		/* 6 msec delay as per HW requirement */978		usleep_range(6000, 6010);979		if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI ||980			hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI)981			snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES,982					WCD938X_REGULATOR_MODE_MASK,983					WCD938X_REGULATOR_MODE_CLASS_AB);984		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)985			enable_irq(wcd938x->aux_pdm_wd_int);986		else987			enable_irq(wcd938x->hphl_pdm_wd_int);988		break;989	case SND_SOC_DAPM_PRE_PMD:990		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)991			disable_irq_nosync(wcd938x->aux_pdm_wd_int);992		else993			disable_irq_nosync(wcd938x->hphl_pdm_wd_int);994		break;995	case SND_SOC_DAPM_POST_PMD:996		if (!wcd938x->comp1_enable)997			snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,998						      WCD938X_GAIN_OVRD_REG_MASK, 0);999		/* 7 msec delay as per HW requirement */1000		usleep_range(7000, 7010);1001		if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX)1002			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2,1003					      WCD938X_AUX_PDM_WD_EN_MASK, 0);1004		else1005			snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0,1006					WCD938X_PDM_WD_EN_MASK, 0);1007 1008		wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA,1009					WCD_CLSH_STATE_EAR, hph_mode);1010 1011		wcd938x->flyback_cur_det_disable--;1012		if (wcd938x->flyback_cur_det_disable == 0)1013			snd_soc_component_write_field(component, WCD938X_FLYBACK_EN,1014						      WCD938X_EN_CUR_DET_MASK, 1);1015		break;1016	}1017 1018	return 0;1019}1020 1021static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,1022				     struct snd_kcontrol *kcontrol,1023				     int event)1024{1025	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1026	u16 dmic_clk_reg, dmic_clk_en_reg;1027	u8 dmic_sel_mask, dmic_clk_mask;1028 1029	switch (w->shift) {1030	case 0:1031	case 1:1032		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;1033		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;1034		dmic_clk_mask = WCD938X_DMIC1_RATE_MASK;1035		dmic_sel_mask = WCD938X_AMIC1_IN_SEL_MASK;1036		break;1037	case 2:1038	case 3:1039		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;1040		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL;1041		dmic_clk_mask = WCD938X_DMIC2_RATE_MASK;1042		dmic_sel_mask = WCD938X_AMIC3_IN_SEL_MASK;1043		break;1044	case 4:1045	case 5:1046		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;1047		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC3_CTL;1048		dmic_clk_mask = WCD938X_DMIC3_RATE_MASK;1049		dmic_sel_mask = WCD938X_AMIC4_IN_SEL_MASK;1050		break;1051	case 6:1052	case 7:1053		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;1054		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC4_CTL;1055		dmic_clk_mask = WCD938X_DMIC4_RATE_MASK;1056		dmic_sel_mask = WCD938X_AMIC5_IN_SEL_MASK;1057		break;1058	default:1059		dev_err(component->dev, "%s: Invalid DMIC Selection\n",1060			__func__);1061		return -EINVAL;1062	}1063 1064	switch (event) {1065	case SND_SOC_DAPM_PRE_PMU:1066		snd_soc_component_write_field(component,1067				WCD938X_DIGITAL_CDC_AMIC_CTL,1068				dmic_sel_mask,1069				WCD938X_AMIC1_IN_SEL_DMIC);1070		/* 250us sleep as per HW requirement */1071		usleep_range(250, 260);1072		/* Setting DMIC clock rate to 2.4MHz */1073		snd_soc_component_write_field(component, dmic_clk_reg,1074					      dmic_clk_mask,1075					      WCD938X_DMIC4_RATE_2P4MHZ);1076		snd_soc_component_write_field(component, dmic_clk_en_reg,1077					      WCD938X_DMIC_CLK_EN_MASK, 1);1078		/* enable clock scaling */1079		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_DMIC_CTL,1080					      WCD938X_DMIC_CLK_SCALING_EN_MASK, 0x3);1081		break;1082	case SND_SOC_DAPM_POST_PMD:1083		snd_soc_component_write_field(component,1084				WCD938X_DIGITAL_CDC_AMIC_CTL,1085				dmic_sel_mask, WCD938X_AMIC1_IN_SEL_AMIC);1086		snd_soc_component_write_field(component, dmic_clk_en_reg,1087					      WCD938X_DMIC_CLK_EN_MASK, 0);1088		break;1089	}1090	return 0;1091}1092 1093static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,1094			       struct snd_kcontrol *kcontrol, int event)1095{1096	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1097	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1098	int bank;1099	int rate;1100 1101	bank = (wcd938x_swr_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev)) ? 0 : 1;1102	bank = bank ? 0 : 1;1103 1104	switch (event) {1105	case SND_SOC_DAPM_PRE_PMU:1106		if (strnstr(w->name, "ADC", sizeof("ADC"))) {1107			int i = 0, mode = 0;1108 1109			if (test_bit(WCD_ADC1, &wcd938x->status_mask))1110				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];1111			if (test_bit(WCD_ADC2, &wcd938x->status_mask))1112				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];1113			if (test_bit(WCD_ADC3, &wcd938x->status_mask))1114				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];1115			if (test_bit(WCD_ADC4, &wcd938x->status_mask))1116				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];1117 1118			if (mode != 0) {1119				for (i = 0; i < ADC_MODE_ULP2; i++) {1120					if (mode & (1 << i)) {1121						i++;1122						break;1123					}1124				}1125			}1126			rate = wcd938x_get_clk_rate(i);1127			wcd938x_set_swr_clk_rate(component, rate, bank);1128			/* Copy clk settings to active bank */1129			wcd938x_set_swr_clk_rate(component, rate, !bank);1130		}1131		break;1132	case SND_SOC_DAPM_POST_PMD:1133		if (strnstr(w->name, "ADC", sizeof("ADC"))) {1134			rate = wcd938x_get_clk_rate(ADC_MODE_INVALID);1135			wcd938x_set_swr_clk_rate(component, rate, !bank);1136			wcd938x_set_swr_clk_rate(component, rate, bank);1137		}1138		break;1139	}1140 1141	return 0;1142}1143 1144static int wcd938x_get_adc_mode(int val)1145{1146	int ret = 0;1147 1148	switch (val) {1149	case ADC_MODE_INVALID:1150		ret = ADC_MODE_VAL_NORMAL;1151		break;1152	case ADC_MODE_HIFI:1153		ret = ADC_MODE_VAL_HIFI;1154		break;1155	case ADC_MODE_LO_HIF:1156		ret = ADC_MODE_VAL_LO_HIF;1157		break;1158	case ADC_MODE_NORMAL:1159		ret = ADC_MODE_VAL_NORMAL;1160		break;1161	case ADC_MODE_LP:1162		ret = ADC_MODE_VAL_LP;1163		break;1164	case ADC_MODE_ULP1:1165		ret = ADC_MODE_VAL_ULP1;1166		break;1167	case ADC_MODE_ULP2:1168		ret = ADC_MODE_VAL_ULP2;1169		break;1170	default:1171		ret = -EINVAL;1172		break;1173	}1174	return ret;1175}1176 1177static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,1178				    struct snd_kcontrol *kcontrol, int event)1179{1180	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1181	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1182 1183	switch (event) {1184	case SND_SOC_DAPM_PRE_PMU:1185		snd_soc_component_write_field(component,1186					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,1187					      WCD938X_ANA_TX_CLK_EN_MASK, 1);1188		snd_soc_component_write_field(component,1189					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,1190					      WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);1191		set_bit(w->shift, &wcd938x->status_mask);1192		break;1193	case SND_SOC_DAPM_POST_PMD:1194		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,1195					      WCD938X_ANA_TX_CLK_EN_MASK, 0);1196		clear_bit(w->shift, &wcd938x->status_mask);1197		break;1198	}1199 1200	return 0;1201}1202 1203static void wcd938x_tx_channel_config(struct snd_soc_component *component,1204				     int channel, int mode)1205{1206	int reg, mask;1207 1208	switch (channel) {1209	case 0:1210		reg = WCD938X_ANA_TX_CH2;1211		mask = WCD938X_HPF1_INIT_MASK;1212		break;1213	case 1:1214		reg = WCD938X_ANA_TX_CH2;1215		mask = WCD938X_HPF2_INIT_MASK;1216		break;1217	case 2:1218		reg = WCD938X_ANA_TX_CH4;1219		mask = WCD938X_HPF3_INIT_MASK;1220		break;1221	case 3:1222		reg = WCD938X_ANA_TX_CH4;1223		mask = WCD938X_HPF4_INIT_MASK;1224		break;1225	default:1226		return;1227	}1228 1229	snd_soc_component_write_field(component, reg, mask, mode);1230}1231 1232static int wcd938x_adc_enable_req(struct snd_soc_dapm_widget *w,1233				  struct snd_kcontrol *kcontrol, int event)1234{1235	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1236	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1237	int mode;1238 1239	switch (event) {1240	case SND_SOC_DAPM_PRE_PMU:1241		snd_soc_component_write_field(component,1242				WCD938X_DIGITAL_CDC_REQ_CTL,1243				WCD938X_FS_RATE_4P8_MASK, 1);1244		snd_soc_component_write_field(component,1245				WCD938X_DIGITAL_CDC_REQ_CTL,1246				WCD938X_NO_NOTCH_MASK, 0);1247		wcd938x_tx_channel_config(component, w->shift, 1);1248		mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);1249		if (mode < 0) {1250			dev_info(component->dev, "Invalid ADC mode\n");1251			return -EINVAL;1252		}1253		switch (w->shift) {1254		case 0:1255			snd_soc_component_write_field(component,1256				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,1257				WCD938X_TXD0_MODE_MASK, mode);1258			snd_soc_component_write_field(component,1259						WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1260						WCD938X_TXD0_CLK_EN_MASK, 1);1261			break;1262		case 1:1263			snd_soc_component_write_field(component,1264				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,1265				WCD938X_TXD1_MODE_MASK, mode);1266			snd_soc_component_write_field(component,1267					      WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1268					      WCD938X_TXD1_CLK_EN_MASK, 1);1269			break;1270		case 2:1271			snd_soc_component_write_field(component,1272				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,1273				WCD938X_TXD2_MODE_MASK, mode);1274			snd_soc_component_write_field(component,1275				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1276				WCD938X_TXD2_CLK_EN_MASK, 1);1277			break;1278		case 3:1279			snd_soc_component_write_field(component,1280				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,1281				WCD938X_TXD3_MODE_MASK, mode);1282			snd_soc_component_write_field(component,1283				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1284				WCD938X_TXD3_CLK_EN_MASK, 1);1285			break;1286		default:1287			break;1288		}1289 1290		wcd938x_tx_channel_config(component, w->shift, 0);1291		break;1292	case SND_SOC_DAPM_POST_PMD:1293		switch (w->shift) {1294		case 0:1295			snd_soc_component_write_field(component,1296				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,1297				WCD938X_TXD0_MODE_MASK, 0);1298			snd_soc_component_write_field(component,1299				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1300				WCD938X_TXD0_CLK_EN_MASK, 0);1301			break;1302		case 1:1303			snd_soc_component_write_field(component,1304				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,1305				WCD938X_TXD1_MODE_MASK, 0);1306			snd_soc_component_write_field(component,1307				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1308				WCD938X_TXD1_CLK_EN_MASK, 0);1309			break;1310		case 2:1311			snd_soc_component_write_field(component,1312				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,1313				WCD938X_TXD2_MODE_MASK, 0);1314			snd_soc_component_write_field(component,1315				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1316				WCD938X_TXD2_CLK_EN_MASK, 0);1317			break;1318		case 3:1319			snd_soc_component_write_field(component,1320				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,1321				WCD938X_TXD3_MODE_MASK, 0);1322			snd_soc_component_write_field(component,1323				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1324				WCD938X_TXD3_CLK_EN_MASK, 0);1325			break;1326		default:1327			break;1328		}1329		snd_soc_component_write_field(component,1330				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,1331				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 0);1332		break;1333	}1334 1335	return 0;1336}1337 1338static int wcd938x_micbias_control(struct snd_soc_component *component,1339				   int micb_num, int req, bool is_dapm)1340{1341	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1342	int micb_index = micb_num - 1;1343	u16 micb_reg;1344 1345	switch (micb_num) {1346	case MIC_BIAS_1:1347		micb_reg = WCD938X_ANA_MICB1;1348		break;1349	case MIC_BIAS_2:1350		micb_reg = WCD938X_ANA_MICB2;1351		break;1352	case MIC_BIAS_3:1353		micb_reg = WCD938X_ANA_MICB3;1354		break;1355	case MIC_BIAS_4:1356		micb_reg = WCD938X_ANA_MICB4;1357		break;1358	default:1359		dev_err(component->dev, "%s: Invalid micbias number: %d\n",1360			__func__, micb_num);1361		return -EINVAL;1362	}1363 1364	switch (req) {1365	case MICB_PULLUP_ENABLE:1366		wcd938x->pullup_ref[micb_index]++;1367		if ((wcd938x->pullup_ref[micb_index] == 1) &&1368		    (wcd938x->micb_ref[micb_index] == 0))1369			snd_soc_component_write_field(component, micb_reg,1370						      WCD938X_MICB_EN_MASK,1371						      WCD938X_MICB_PULL_UP);1372		break;1373	case MICB_PULLUP_DISABLE:1374		if (wcd938x->pullup_ref[micb_index] > 0)1375			wcd938x->pullup_ref[micb_index]--;1376 1377		if ((wcd938x->pullup_ref[micb_index] == 0) &&1378		    (wcd938x->micb_ref[micb_index] == 0))1379			snd_soc_component_write_field(component, micb_reg,1380						      WCD938X_MICB_EN_MASK, 0);1381		break;1382	case MICB_ENABLE:1383		wcd938x->micb_ref[micb_index]++;1384		if (wcd938x->micb_ref[micb_index] == 1) {1385			snd_soc_component_write_field(component,1386				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,1387				WCD938X_TX_CLK_EN_MASK, 0xF);1388			snd_soc_component_write_field(component,1389				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,1390				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);1391			snd_soc_component_write_field(component,1392			       WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL,1393			       WCD938X_TX_SC_CLK_EN_MASK, 1);1394 1395			snd_soc_component_write_field(component, micb_reg,1396						      WCD938X_MICB_EN_MASK,1397						      WCD938X_MICB_ENABLE);1398			if (micb_num  == MIC_BIAS_2)1399				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,1400						      WCD_EVENT_POST_MICBIAS_2_ON);1401		}1402		if (micb_num  == MIC_BIAS_2 && is_dapm)1403			wcd_mbhc_event_notify(wcd938x->wcd_mbhc,1404					      WCD_EVENT_POST_DAPM_MICBIAS_2_ON);1405 1406 1407		break;1408	case MICB_DISABLE:1409		if (wcd938x->micb_ref[micb_index] > 0)1410			wcd938x->micb_ref[micb_index]--;1411 1412		if ((wcd938x->micb_ref[micb_index] == 0) &&1413		    (wcd938x->pullup_ref[micb_index] > 0))1414			snd_soc_component_write_field(component, micb_reg,1415						      WCD938X_MICB_EN_MASK,1416						      WCD938X_MICB_PULL_UP);1417		else if ((wcd938x->micb_ref[micb_index] == 0) &&1418			 (wcd938x->pullup_ref[micb_index] == 0)) {1419			if (micb_num  == MIC_BIAS_2)1420				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,1421						      WCD_EVENT_PRE_MICBIAS_2_OFF);1422 1423			snd_soc_component_write_field(component, micb_reg,1424						      WCD938X_MICB_EN_MASK, 0);1425			if (micb_num  == MIC_BIAS_2)1426				wcd_mbhc_event_notify(wcd938x->wcd_mbhc,1427						      WCD_EVENT_POST_MICBIAS_2_OFF);1428		}1429		if (is_dapm && micb_num  == MIC_BIAS_2)1430			wcd_mbhc_event_notify(wcd938x->wcd_mbhc,1431					      WCD_EVENT_POST_DAPM_MICBIAS_2_OFF);1432		break;1433	}1434 1435	return 0;1436}1437 1438static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,1439					struct snd_kcontrol *kcontrol,1440					int event)1441{1442	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1443	int micb_num = w->shift;1444 1445	switch (event) {1446	case SND_SOC_DAPM_PRE_PMU:1447		wcd938x_micbias_control(component, micb_num, MICB_ENABLE, true);1448		break;1449	case SND_SOC_DAPM_POST_PMU:1450		/* 1 msec delay as per HW requirement */1451		usleep_range(1000, 1100);1452		break;1453	case SND_SOC_DAPM_POST_PMD:1454		wcd938x_micbias_control(component, micb_num, MICB_DISABLE, true);1455		break;1456	}1457 1458	return 0;1459}1460 1461static int wcd938x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,1462					       struct snd_kcontrol *kcontrol,1463					       int event)1464{1465	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1466	int micb_num = w->shift;1467 1468	switch (event) {1469	case SND_SOC_DAPM_PRE_PMU:1470		wcd938x_micbias_control(component, micb_num,1471					MICB_PULLUP_ENABLE, true);1472		break;1473	case SND_SOC_DAPM_POST_PMU:1474		/* 1 msec delay as per HW requirement */1475		usleep_range(1000, 1100);1476		break;1477	case SND_SOC_DAPM_POST_PMD:1478		wcd938x_micbias_control(component, micb_num,1479					MICB_PULLUP_DISABLE, true);1480		break;1481	}1482 1483	return 0;1484}1485 1486static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,1487			       struct snd_ctl_elem_value *ucontrol)1488{1489	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1490	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1491	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;1492	int path = e->shift_l;1493 1494	ucontrol->value.enumerated.item[0] = wcd938x->tx_mode[path];1495 1496	return 0;1497}1498 1499static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,1500			       struct snd_ctl_elem_value *ucontrol)1501{1502	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1503	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1504	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;1505	int path = e->shift_l;1506 1507	if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0])1508		return 0;1509 1510	wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0];1511 1512	return 1;1513}1514 1515static int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,1516				 struct snd_ctl_elem_value *ucontrol)1517{1518	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1519	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1520 1521	ucontrol->value.enumerated.item[0] = wcd938x->hph_mode;1522 1523	return 0;1524}1525 1526static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,1527				   struct snd_ctl_elem_value *ucontrol)1528{1529	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1530	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1531 1532	if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0])1533		return 0;1534 1535	wcd938x->hph_mode = ucontrol->value.enumerated.item[0];1536 1537	return 1;1538}1539 1540static int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol,1541				   struct snd_ctl_elem_value *ucontrol)1542{1543	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1544	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1545 1546	if (wcd938x->comp1_enable) {1547		dev_err(component->dev, "Can not set EAR PA Gain, compander1 is enabled\n");1548		return -EINVAL;1549	}1550 1551	snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL,1552				      WCD938X_EAR_GAIN_MASK,1553				      ucontrol->value.integer.value[0]);1554 1555	return 1;1556}1557 1558static int wcd938x_get_compander(struct snd_kcontrol *kcontrol,1559				 struct snd_ctl_elem_value *ucontrol)1560{1561 1562	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1563	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1564	struct soc_mixer_control *mc;1565	bool hphr;1566 1567	mc = (struct soc_mixer_control *)(kcontrol->private_value);1568	hphr = mc->shift;1569 1570	if (hphr)1571		ucontrol->value.integer.value[0] = wcd938x->comp2_enable;1572	else1573		ucontrol->value.integer.value[0] = wcd938x->comp1_enable;1574 1575	return 0;1576}1577 1578static int wcd938x_set_compander(struct snd_kcontrol *kcontrol,1579				 struct snd_ctl_elem_value *ucontrol)1580{1581	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1582	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1583	struct wcd938x_sdw_priv *wcd;1584	int value = ucontrol->value.integer.value[0];1585	int portidx;1586	struct soc_mixer_control *mc;1587	bool hphr;1588 1589	mc = (struct soc_mixer_control *)(kcontrol->private_value);1590	hphr = mc->shift;1591 1592	wcd = wcd938x->sdw_priv[AIF1_PB];1593 1594	if (hphr)1595		wcd938x->comp2_enable = value;1596	else1597		wcd938x->comp1_enable = value;1598 1599	portidx = wcd->ch_info[mc->reg].port_num;1600 1601	if (value)1602		wcd938x_connect_port(wcd, portidx, mc->reg, true);1603	else1604		wcd938x_connect_port(wcd, portidx, mc->reg, false);1605 1606	return 1;1607}1608 1609static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol,1610			    struct snd_ctl_elem_value *ucontrol)1611{1612	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1613	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1614 1615	ucontrol->value.integer.value[0] = wcd938x->ldoh;1616 1617	return 0;1618}1619 1620static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,1621			    struct snd_ctl_elem_value *ucontrol)1622{1623	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1624	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);1625 1626	if (wcd938x->ldoh == ucontrol->value.integer.value[0])1627		return 0;1628 1629	wcd938x->ldoh = ucontrol->value.integer.value[0];1630 1631	return 1;1632}1633 1634static const char * const tx_mode_mux_text_wcd9380[] = {1635	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",1636};1637 1638static const char * const tx_mode_mux_text[] = {1639	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",1640	"ADC_ULP1", "ADC_ULP2",1641};1642 1643static const char * const rx_hph_mode_mux_text_wcd9380[] = {1644	"CLS_H_INVALID", "CLS_H_INVALID_1", "CLS_H_LP", "CLS_AB",1645	"CLS_H_LOHIFI", "CLS_H_ULP", "CLS_H_INVALID_2", "CLS_AB_LP",1646	"CLS_AB_LOHIFI",1647};1648 1649static const char * const rx_hph_mode_mux_text[] = {1650	"CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",1651	"CLS_H_ULP", "CLS_AB_HIFI", "CLS_AB_LP", "CLS_AB_LOHIFI",1652};1653 1654static const char * const adc2_mux_text[] = {1655	"INP2", "INP3"1656};1657 1658static const char * const adc3_mux_text[] = {1659	"INP4", "INP6"1660};1661 1662static const char * const adc4_mux_text[] = {1663	"INP5", "INP7"1664};1665 1666static const char * const rdac3_mux_text[] = {1667	"RX1", "RX3"1668};1669 1670static const char * const hdr12_mux_text[] = {1671	"NO_HDR12", "HDR12"1672};1673 1674static const char * const hdr34_mux_text[] = {1675	"NO_HDR34", "HDR34"1676};1677 1678static const struct soc_enum tx0_mode_enum_wcd9380 =1679	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text_wcd9380),1680			tx_mode_mux_text_wcd9380);1681 1682static const struct soc_enum tx1_mode_enum_wcd9380 =1683	SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text_wcd9380),1684			tx_mode_mux_text_wcd9380);1685 1686static const struct soc_enum tx2_mode_enum_wcd9380 =1687	SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text_wcd9380),1688			tx_mode_mux_text_wcd9380);1689 1690static const struct soc_enum tx3_mode_enum_wcd9380 =1691	SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text_wcd9380),1692			tx_mode_mux_text_wcd9380);1693 1694static const struct soc_enum tx0_mode_enum_wcd9385 =1695	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text),1696			tx_mode_mux_text);1697 1698static const struct soc_enum tx1_mode_enum_wcd9385 =1699	SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text),1700			tx_mode_mux_text);1701 1702static const struct soc_enum tx2_mode_enum_wcd9385 =1703	SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text),1704			tx_mode_mux_text);1705 1706static const struct soc_enum tx3_mode_enum_wcd9385 =1707	SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text),1708			tx_mode_mux_text);1709 1710static const struct soc_enum rx_hph_mode_mux_enum_wcd9380 =1711		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text_wcd9380),1712				    rx_hph_mode_mux_text_wcd9380);1713 1714static const struct soc_enum rx_hph_mode_mux_enum =1715		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),1716				    rx_hph_mode_mux_text);1717 1718static const struct soc_enum adc2_enum =1719		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 7,1720				ARRAY_SIZE(adc2_mux_text), adc2_mux_text);1721 1722static const struct soc_enum adc3_enum =1723		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 6,1724				ARRAY_SIZE(adc3_mux_text), adc3_mux_text);1725 1726static const struct soc_enum adc4_enum =1727		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 5,1728				ARRAY_SIZE(adc4_mux_text), adc4_mux_text);1729 1730static const struct soc_enum hdr12_enum =1731		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 4,1732				ARRAY_SIZE(hdr12_mux_text), hdr12_mux_text);1733 1734static const struct soc_enum hdr34_enum =1735		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 3,1736				ARRAY_SIZE(hdr34_mux_text), hdr34_mux_text);1737 1738static const struct soc_enum rdac3_enum =1739		SOC_ENUM_SINGLE(WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0,1740				ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text);1741 1742static const struct snd_kcontrol_new adc1_switch[] = {1743	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1744};1745 1746static const struct snd_kcontrol_new adc2_switch[] = {1747	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1748};1749 1750static const struct snd_kcontrol_new adc3_switch[] = {1751	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1752};1753 1754static const struct snd_kcontrol_new adc4_switch[] = {1755	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1756};1757 1758static const struct snd_kcontrol_new dmic1_switch[] = {1759	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1760};1761 1762static const struct snd_kcontrol_new dmic2_switch[] = {1763	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1764};1765 1766static const struct snd_kcontrol_new dmic3_switch[] = {1767	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1768};1769 1770static const struct snd_kcontrol_new dmic4_switch[] = {1771	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1772};1773 1774static const struct snd_kcontrol_new dmic5_switch[] = {1775	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1776};1777 1778static const struct snd_kcontrol_new dmic6_switch[] = {1779	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1780};1781 1782static const struct snd_kcontrol_new dmic7_switch[] = {1783	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1784};1785 1786static const struct snd_kcontrol_new dmic8_switch[] = {1787	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1788};1789 1790static const struct snd_kcontrol_new ear_rdac_switch[] = {1791	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1792};1793 1794static const struct snd_kcontrol_new aux_rdac_switch[] = {1795	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1796};1797 1798static const struct snd_kcontrol_new hphl_rdac_switch[] = {1799	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1800};1801 1802static const struct snd_kcontrol_new hphr_rdac_switch[] = {1803	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)1804};1805 1806static const struct snd_kcontrol_new tx_adc2_mux =1807	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);1808 1809static const struct snd_kcontrol_new tx_adc3_mux =1810	SOC_DAPM_ENUM("ADC3 MUX Mux", adc3_enum);1811 1812static const struct snd_kcontrol_new tx_adc4_mux =1813	SOC_DAPM_ENUM("ADC4 MUX Mux", adc4_enum);1814 1815static const struct snd_kcontrol_new tx_hdr12_mux =1816	SOC_DAPM_ENUM("HDR12 MUX Mux", hdr12_enum);1817 1818static const struct snd_kcontrol_new tx_hdr34_mux =1819	SOC_DAPM_ENUM("HDR34 MUX Mux", hdr34_enum);1820 1821static const struct snd_kcontrol_new rx_rdac3_mux =1822	SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum);1823 1824static const struct snd_kcontrol_new wcd9380_snd_controls[] = {1825	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum_wcd9380,1826		     wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),1827	SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9380,1828		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1829	SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9380,1830		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1831	SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9380,1832		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1833	SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9380,1834		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1835};1836 1837static const struct snd_kcontrol_new wcd9385_snd_controls[] = {1838	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,1839		     wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),1840	SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9385,1841		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1842	SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9385,1843		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1844	SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9385,1845		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1846	SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9385,1847		     wcd938x_tx_mode_get, wcd938x_tx_mode_put),1848};1849 1850static int wcd938x_get_swr_port(struct snd_kcontrol *kcontrol,1851			    struct snd_ctl_elem_value *ucontrol)1852{1853	struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);1854	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp);1855	struct wcd938x_sdw_priv *wcd;1856	struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;1857	int dai_id = mixer->shift;1858	int portidx, ch_idx = mixer->reg;1859 1860 1861	wcd = wcd938x->sdw_priv[dai_id];1862	portidx = wcd->ch_info[ch_idx].port_num;1863 1864	ucontrol->value.integer.value[0] = wcd->port_enable[portidx];1865 1866	return 0;1867}1868 1869static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol,1870			    struct snd_ctl_elem_value *ucontrol)1871{1872	struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);1873	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp);1874	struct wcd938x_sdw_priv *wcd;1875	struct soc_mixer_control *mixer =1876		(struct soc_mixer_control *)kcontrol->private_value;1877	int ch_idx = mixer->reg;1878	int portidx;1879	int dai_id = mixer->shift;1880	bool enable;1881 1882	wcd = wcd938x->sdw_priv[dai_id];1883 1884	portidx = wcd->ch_info[ch_idx].port_num;1885	if (ucontrol->value.integer.value[0])1886		enable = true;1887	else1888		enable = false;1889 1890	wcd->port_enable[portidx] = enable;1891 1892	wcd938x_connect_port(wcd, portidx, ch_idx, enable);1893 1894	return 1;1895 1896}1897 1898/* MBHC related */1899static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component,1900				   bool enable)1901{1902	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1,1903				      WCD938X_MBHC_CTL_RCO_EN_MASK, enable);1904}1905 1906static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component,1907					   bool enable)1908{1909	snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT,1910				      WCD938X_ANA_MBHC_BIAS_EN, enable);1911}1912 1913static void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component,1914					 int *btn_low, int *btn_high,1915					 int num_btn, bool is_micbias)1916{1917	int i, vth;1918 1919	if (num_btn > WCD_MBHC_DEF_BUTTONS) {1920		dev_err(component->dev, "%s: invalid number of buttons: %d\n",1921			__func__, num_btn);1922		return;1923	}1924 1925	for (i = 0; i < num_btn; i++) {1926		vth = ((btn_high[i] * 2) / 25) & 0x3F;1927		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i,1928					   WCD938X_MBHC_BTN_VTH_MASK, vth);1929		dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n",1930			__func__, i, btn_high[i], vth);1931	}1932}1933 1934static bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num)1935{1936	u8 val;1937 1938	if (micb_num == MIC_BIAS_2) {1939		val = snd_soc_component_read_field(component,1940						   WCD938X_ANA_MICB2,1941						   WCD938X_MICB_EN_MASK);1942		if (val == WCD938X_MICB_ENABLE)1943			return true;1944	}1945	return false;1946}1947 1948static void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component,1949							int pull_up_cur)1950{1951	/* Default pull up current to 2uA */1952	if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA)1953		pull_up_cur = HS_PULLUP_I_2P0_UA;1954 1955	snd_soc_component_write_field(component,1956				      WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT,1957				      WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur);1958}1959 1960static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component,1961					int micb_num, int req)1962{1963	return wcd938x_micbias_control(component, micb_num, req, false);1964}1965 1966static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component,1967					   bool enable)1968{1969	if (enable) {1970		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,1971				    WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C);1972		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,1973				    WCD938X_RAMP_EN_MASK, 1);1974	} else {1975		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,1976				    WCD938X_RAMP_EN_MASK, 0);1977		snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP,1978				    WCD938X_RAMP_SHIFT_CTRL_MASK, 0);1979	}1980}1981 1982static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv)1983{1984	/* min micbias voltage is 1V and maximum is 2.85V */1985	if (micb_mv < 1000 || micb_mv > 2850)1986		return -EINVAL;1987 1988	return (micb_mv - 1000) / 50;1989}1990 1991static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,1992					    int req_volt, int micb_num)1993{1994	struct wcd938x_priv *wcd938x =  snd_soc_component_get_drvdata(component);1995	int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0;1996 1997	switch (micb_num) {1998	case MIC_BIAS_1:1999		micb_reg = WCD938X_ANA_MICB1;2000		break;2001	case MIC_BIAS_2:2002		micb_reg = WCD938X_ANA_MICB2;2003		break;2004	case MIC_BIAS_3:2005		micb_reg = WCD938X_ANA_MICB3;2006		break;2007	case MIC_BIAS_4:2008		micb_reg = WCD938X_ANA_MICB4;2009		break;2010	default:2011		return -EINVAL;2012	}2013	mutex_lock(&wcd938x->micb_lock);2014	/*2015	 * If requested micbias voltage is same as current micbias2016	 * voltage, then just return. Otherwise, adjust voltage as2017	 * per requested value. If micbias is already enabled, then2018	 * to avoid slow micbias ramp-up or down enable pull-up2019	 * momentarily, change the micbias value and then re-enable2020	 * micbias.2021	 */2022	micb_en = snd_soc_component_read_field(component, micb_reg,2023						WCD938X_MICB_EN_MASK);2024	cur_vout_ctl = snd_soc_component_read_field(component, micb_reg,2025						    WCD938X_MICB_VOUT_MASK);2026 2027	req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt);2028	if (req_vout_ctl < 0) {2029		ret = -EINVAL;2030		goto exit;2031	}2032 2033	if (cur_vout_ctl == req_vout_ctl) {2034		ret = 0;2035		goto exit;2036	}2037 2038	if (micb_en == WCD938X_MICB_ENABLE)2039		snd_soc_component_write_field(component, micb_reg,2040					      WCD938X_MICB_EN_MASK,2041					      WCD938X_MICB_PULL_UP);2042 2043	snd_soc_component_write_field(component, micb_reg,2044				      WCD938X_MICB_VOUT_MASK,2045				      req_vout_ctl);2046 2047	if (micb_en == WCD938X_MICB_ENABLE) {2048		snd_soc_component_write_field(component, micb_reg,2049					      WCD938X_MICB_EN_MASK,2050					      WCD938X_MICB_ENABLE);2051		/*2052		 * Add 2ms delay as per HW requirement after enabling2053		 * micbias2054		 */2055		usleep_range(2000, 2100);2056	}2057exit:2058	mutex_unlock(&wcd938x->micb_lock);2059	return ret;2060}2061 2062static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component,2063						int micb_num, bool req_en)2064{2065	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2066	int micb_mv;2067 2068	if (micb_num != MIC_BIAS_2)2069		return -EINVAL;2070	/*2071	 * If device tree micbias level is already above the minimum2072	 * voltage needed to detect threshold microphone, then do2073	 * not change the micbias, just return.2074	 */2075	if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)2076		return 0;2077 2078	micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv;2079 2080	return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);2081}2082 2083static void wcd938x_mbhc_get_result_params(struct snd_soc_component *component,2084						s16 *d1_a, u16 noff,2085						int32_t *zdet)2086{2087	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2088	int i;2089	int val, val1;2090	s16 c1;2091	s32 x1, d1;2092	int32_t denom;2093	static const int minCode_param[] = {2094		3277, 1639, 820, 410, 205, 103, 52, 262095	};2096 2097	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20);2098	for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) {2099		regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val);2100		if (val & 0x80)2101			break;2102	}2103	val = val << 0x8;2104	regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1);2105	val |= val1;2106	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00);2107	x1 = WCD938X_MBHC_GET_X1(val);2108	c1 = WCD938X_MBHC_GET_C1(val);2109	/* If ramp is not complete, give additional 5ms */2110	if ((c1 < 2) && x1)2111		usleep_range(5000, 5050);2112 2113	if (!c1 || !x1) {2114		dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n",2115			c1, x1);2116		goto ramp_down;2117	}2118	d1 = d1_a[c1];2119	denom = (x1 * d1) - (1 << (14 - noff));2120	if (denom > 0)2121		*zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom;2122	else if (x1 < minCode_param[noff])2123		*zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;2124 2125	dev_dbg(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n",2126		__func__, d1, c1, x1, *zdet);2127ramp_down:2128	i = 0;2129	while (x1) {2130		regmap_read(wcd938x->regmap,2131				 WCD938X_ANA_MBHC_RESULT_1, &val);2132		regmap_read(wcd938x->regmap,2133				 WCD938X_ANA_MBHC_RESULT_2, &val1);2134		val = val << 0x08;2135		val |= val1;2136		x1 = WCD938X_MBHC_GET_X1(val);2137		i++;2138		if (i == WCD938X_ZDET_NUM_MEASUREMENTS)2139			break;2140	}2141}2142 2143static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,2144				 struct wcd938x_mbhc_zdet_param *zdet_param,2145				 int32_t *zl, int32_t *zr, s16 *d1_a)2146{2147	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2148	int32_t zdet = 0;2149 2150	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,2151				WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl);2152	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5,2153				    WCD938X_VTH_MASK, zdet_param->btn5);2154	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6,2155				      WCD938X_VTH_MASK, zdet_param->btn6);2156	snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7,2157				     WCD938X_VTH_MASK, zdet_param->btn7);2158	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL,2159				WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff);2160	snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL,2161				0x0F, zdet_param->nshift);2162 2163	if (!zl)2164		goto z_right;2165	/* Start impedance measurement for HPH_L */2166	regmap_update_bits(wcd938x->regmap,2167			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);2168	dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",2169		__func__, zdet_param->noff);2170	wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);2171	regmap_update_bits(wcd938x->regmap,2172			   WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);2173 2174	*zl = zdet;2175 2176z_right:2177	if (!zr)2178		return;2179	/* Start impedance measurement for HPH_R */2180	regmap_update_bits(wcd938x->regmap,2181			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);2182	dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",2183		__func__, zdet_param->noff);2184	wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);2185	regmap_update_bits(wcd938x->regmap,2186			   WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);2187 2188	*zr = zdet;2189}2190 2191static void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,2192					int32_t *z_val, int flag_l_r)2193{2194	s16 q1;2195	int q1_cal;2196 2197	if (*z_val < (WCD938X_ZDET_VAL_400/1000))2198		q1 = snd_soc_component_read(component,2199			WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r));2200	else2201		q1 = snd_soc_component_read(component,2202			WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r));2203	if (q1 & 0x80)2204		q1_cal = (10000 - ((q1 & 0x7F) * 25));2205	else2206		q1_cal = (10000 + (q1 * 25));2207	if (q1_cal > 0)2208		*z_val = ((*z_val) * 10000) / q1_cal;2209}2210 2211static void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component,2212					    uint32_t *zl, uint32_t *zr)2213{2214	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2215	s16 reg0, reg1, reg2, reg3, reg4;2216	int32_t z1L, z1R, z1Ls;2217	int zMono, z_diff1, z_diff2;2218	bool is_fsm_disable = false;2219	struct wcd938x_mbhc_zdet_param zdet_param[] = {2220		{4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */2221		{2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */2222		{1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */2223		{1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */2224	};2225	struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL;2226	s16 d1_a[][4] = {2227		{0, 30, 90, 30},2228		{0, 30, 30, 5},2229		{0, 30, 30, 5},2230		{0, 30, 30, 5},2231	};2232	s16 *d1 = NULL;2233 2234	reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5);2235	reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6);2236	reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7);2237	reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK);2238	reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL);2239 2240	if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) {2241		is_fsm_disable = true;2242		regmap_update_bits(wcd938x->regmap,2243				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x00);2244	}2245 2246	/* For NO-jack, disable L_DET_EN before Z-det measurements */2247	if (wcd938x->mbhc_cfg.hphl_swh)2248		regmap_update_bits(wcd938x->regmap,2249				   WCD938X_ANA_MBHC_MECH, 0x80, 0x00);2250 2251	/* Turn off 100k pull down on HPHL */2252	regmap_update_bits(wcd938x->regmap,2253			   WCD938X_ANA_MBHC_MECH, 0x01, 0x00);2254 2255	/* Disable surge protection before impedance detection.2256	 * This is done to give correct value for high impedance.2257	 */2258	regmap_update_bits(wcd938x->regmap,2259			   WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00);2260	/* 1ms delay needed after disable surge protection */2261	usleep_range(1000, 1010);2262 2263	/* First get impedance on Left */2264	d1 = d1_a[1];2265	zdet_param_ptr = &zdet_param[1];2266	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);2267 2268	if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L))2269		goto left_ch_impedance;2270 2271	/* Second ramp for left ch */2272	if (z1L < WCD938X_ZDET_VAL_32) {2273		zdet_param_ptr = &zdet_param[0];2274		d1 = d1_a[0];2275	} else if ((z1L > WCD938X_ZDET_VAL_400) &&2276		  (z1L <= WCD938X_ZDET_VAL_1200)) {2277		zdet_param_ptr = &zdet_param[2];2278		d1 = d1_a[2];2279	} else if (z1L > WCD938X_ZDET_VAL_1200) {2280		zdet_param_ptr = &zdet_param[3];2281		d1 = d1_a[3];2282	}2283	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1);2284 2285left_ch_impedance:2286	if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) ||2287		(z1L > WCD938X_ZDET_VAL_100K)) {2288		*zl = WCD938X_ZDET_FLOATING_IMPEDANCE;2289		zdet_param_ptr = &zdet_param[1];2290		d1 = d1_a[1];2291	} else {2292		*zl = z1L/1000;2293		wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0);2294	}2295	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",2296		__func__, *zl);2297 2298	/* Start of right impedance ramp and calculation */2299	wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);2300	if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) {2301		if (((z1R > WCD938X_ZDET_VAL_1200) &&2302			(zdet_param_ptr->noff == 0x6)) ||2303			((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE))2304			goto right_ch_impedance;2305		/* Second ramp for right ch */2306		if (z1R < WCD938X_ZDET_VAL_32) {2307			zdet_param_ptr = &zdet_param[0];2308			d1 = d1_a[0];2309		} else if ((z1R > WCD938X_ZDET_VAL_400) &&2310			(z1R <= WCD938X_ZDET_VAL_1200)) {2311			zdet_param_ptr = &zdet_param[2];2312			d1 = d1_a[2];2313		} else if (z1R > WCD938X_ZDET_VAL_1200) {2314			zdet_param_ptr = &zdet_param[3];2315			d1 = d1_a[3];2316		}2317		wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1);2318	}2319right_ch_impedance:2320	if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) ||2321		(z1R > WCD938X_ZDET_VAL_100K)) {2322		*zr = WCD938X_ZDET_FLOATING_IMPEDANCE;2323	} else {2324		*zr = z1R/1000;2325		wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1);2326	}2327	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",2328		__func__, *zr);2329 2330	/* Mono/stereo detection */2331	if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) &&2332		(*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) {2333		dev_dbg(component->dev,2334			"%s: plug type is invalid or extension cable\n",2335			__func__);2336		goto zdet_complete;2337	}2338	if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) ||2339	    (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) ||2340	    ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) ||2341	    ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) {2342		dev_dbg(component->dev,2343			"%s: Mono plug type with one ch floating or shorted to GND\n",2344			__func__);2345		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);2346		goto zdet_complete;2347	}2348	snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,2349				      WCD938X_HPHPA_GND_OVR_MASK, 1);2350	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,2351				      WCD938X_HPHPA_GND_R_MASK, 1);2352	if (*zl < (WCD938X_ZDET_VAL_32/1000))2353		wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1);2354	else2355		wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1);2356	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,2357				      WCD938X_HPHPA_GND_R_MASK, 0);2358	snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST,2359				      WCD938X_HPHPA_GND_OVR_MASK, 0);2360	z1Ls /= 1000;2361	wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0);2362	/* Parallel of left Z and 9 ohm pull down resistor */2363	zMono = ((*zl) * 9) / ((*zl) + 9);2364	z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls);2365	z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl));2366	if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) {2367		dev_dbg(component->dev, "%s: stereo plug type detected\n",2368			__func__);2369		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO);2370	} else {2371		dev_dbg(component->dev, "%s: MONO plug type detected\n",2372			__func__);2373		wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO);2374	}2375 2376	/* Enable surge protection again after impedance detection */2377	regmap_update_bits(wcd938x->regmap,2378			   WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0);2379zdet_complete:2380	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0);2381	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1);2382	snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2);2383	/* Turn on 100k pull down on HPHL */2384	regmap_update_bits(wcd938x->regmap,2385			   WCD938X_ANA_MBHC_MECH, 0x01, 0x01);2386 2387	/* For NO-jack, re-enable L_DET_EN after Z-det measurements */2388	if (wcd938x->mbhc_cfg.hphl_swh)2389		regmap_update_bits(wcd938x->regmap,2390				   WCD938X_ANA_MBHC_MECH, 0x80, 0x80);2391 2392	snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4);2393	snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3);2394	if (is_fsm_disable)2395		regmap_update_bits(wcd938x->regmap,2396				   WCD938X_ANA_MBHC_ELECT, 0x80, 0x80);2397}2398 2399static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component,2400			bool enable)2401{2402	if (enable) {2403		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,2404					      WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1);2405		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,2406					      WCD938X_MBHC_GND_DET_EN_MASK, 1);2407	} else {2408		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,2409					      WCD938X_MBHC_GND_DET_EN_MASK, 0);2410		snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH,2411					      WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0);2412	}2413}2414 2415static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component,2416					  bool enable)2417{2418	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,2419				      WCD938X_HPHPA_GND_R_MASK, enable);2420	snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2,2421				      WCD938X_HPHPA_GND_L_MASK, enable);2422}2423 2424static void wcd938x_mbhc_moisture_config(struct snd_soc_component *component)2425{2426	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2427 2428	if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {2429		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2430				    WCD938X_M_RTH_CTL_MASK, R_OFF);2431		return;2432	}2433 2434	/* Do not enable moisture detection if jack type is NC */2435	if (!wcd938x->mbhc_cfg.hphl_swh) {2436		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",2437			__func__);2438		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2439				    WCD938X_M_RTH_CTL_MASK, R_OFF);2440		return;2441	}2442 2443	snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2444			    WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);2445}2446 2447static void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable)2448{2449	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2450 2451	if (enable)2452		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2453					WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref);2454	else2455		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2456				    WCD938X_M_RTH_CTL_MASK, R_OFF);2457}2458 2459static bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component)2460{2461	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2462	bool ret = false;2463 2464	if (wcd938x->mbhc_cfg.moist_rref == R_OFF) {2465		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2466				    WCD938X_M_RTH_CTL_MASK, R_OFF);2467		goto done;2468	}2469 2470	/* Do not enable moisture detection if jack type is NC */2471	if (!wcd938x->mbhc_cfg.hphl_swh) {2472		dev_dbg(component->dev, "%s: disable moisture detection for NC\n",2473			__func__);2474		snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2,2475				    WCD938X_M_RTH_CTL_MASK, R_OFF);2476		goto done;2477	}2478 2479	/*2480	 * If moisture_en is already enabled, then skip to plug type2481	 * detection.2482	 */2483	if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK))2484		goto done;2485 2486	wcd938x_mbhc_moisture_detect_en(component, true);2487	/* Read moisture comparator status */2488	ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS)2489				& 0x20) ? 0 : 1);2490 2491done:2492	return ret;2493 2494}2495 2496static void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component,2497						bool enable)2498{2499	snd_soc_component_write_field(component,2500			      WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,2501			      WCD938X_MOISTURE_EN_POLLING_MASK, enable);2502}2503 2504static const struct wcd_mbhc_cb mbhc_cb = {2505	.clk_setup = wcd938x_mbhc_clk_setup,2506	.mbhc_bias = wcd938x_mbhc_mbhc_bias_control,2507	.set_btn_thr = wcd938x_mbhc_program_btn_thr,2508	.micbias_enable_status = wcd938x_mbhc_micb_en_status,2509	.hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control,2510	.mbhc_micbias_control = wcd938x_mbhc_request_micbias,2511	.mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control,2512	.mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic,2513	.compute_impedance = wcd938x_wcd_mbhc_calc_impedance,2514	.mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl,2515	.hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl,2516	.mbhc_moisture_config = wcd938x_mbhc_moisture_config,2517	.mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status,2518	.mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl,2519	.mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en,2520};2521 2522static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol,2523			      struct snd_ctl_elem_value *ucontrol)2524{2525	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);2526	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2527 2528	ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc);2529 2530	return 0;2531}2532 2533static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol,2534				   struct snd_ctl_elem_value *ucontrol)2535{2536	uint32_t zl, zr;2537	bool hphr;2538	struct soc_mixer_control *mc;2539	struct snd_soc_component *component =2540					snd_soc_kcontrol_component(kcontrol);2541	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2542 2543	mc = (struct soc_mixer_control *)(kcontrol->private_value);2544	hphr = mc->shift;2545	wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr);2546	dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr);2547	ucontrol->value.integer.value[0] = hphr ? zr : zl;2548 2549	return 0;2550}2551 2552static const struct snd_kcontrol_new hph_type_detect_controls[] = {2553	SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0,2554		       wcd938x_get_hph_type, NULL),2555};2556 2557static const struct snd_kcontrol_new impedance_detect_controls[] = {2558	SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0,2559		       wcd938x_hph_impedance_get, NULL),2560	SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0,2561		       wcd938x_hph_impedance_get, NULL),2562};2563 2564static int wcd938x_mbhc_init(struct snd_soc_component *component)2565{2566	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2567	struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids;2568 2569	intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip,2570						    WCD938X_IRQ_MBHC_SW_DET);2571	intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip,2572							   WCD938X_IRQ_MBHC_BUTTON_PRESS_DET);2573	intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip,2574							     WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET);2575	intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip,2576							WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET);2577	intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip,2578							WCD938X_IRQ_MBHC_ELECT_INS_REM_DET);2579	intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip,2580						    WCD938X_IRQ_HPHL_OCP_INT);2581	intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip,2582						     WCD938X_IRQ_HPHR_OCP_INT);2583 2584	wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);2585	if (IS_ERR(wcd938x->wcd_mbhc))2586		return PTR_ERR(wcd938x->wcd_mbhc);2587 2588	snd_soc_add_component_controls(component, impedance_detect_controls,2589				       ARRAY_SIZE(impedance_detect_controls));2590	snd_soc_add_component_controls(component, hph_type_detect_controls,2591				       ARRAY_SIZE(hph_type_detect_controls));2592 2593	return 0;2594}2595 2596static void wcd938x_mbhc_deinit(struct snd_soc_component *component)2597{2598	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);2599 2600	wcd_mbhc_deinit(wcd938x->wcd_mbhc);2601}2602 2603/* END MBHC */2604 2605static const struct snd_kcontrol_new wcd938x_snd_controls[] = {2606	SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0,2607		       wcd938x_get_compander, wcd938x_set_compander),2608	SOC_SINGLE_EXT("HPHR_COMP Switch", WCD938X_COMP_R, 1, 1, 0,2609		       wcd938x_get_compander, wcd938x_set_compander),2610	SOC_SINGLE_EXT("HPHL Switch", WCD938X_HPH_L, 0, 1, 0,2611		       wcd938x_get_swr_port, wcd938x_set_swr_port),2612	SOC_SINGLE_EXT("HPHR Switch", WCD938X_HPH_R, 0, 1, 0,2613		       wcd938x_get_swr_port, wcd938x_set_swr_port),2614	SOC_SINGLE_EXT("CLSH Switch", WCD938X_CLSH, 0, 1, 0,2615		       wcd938x_get_swr_port, wcd938x_set_swr_port),2616	SOC_SINGLE_EXT("LO Switch", WCD938X_LO, 0, 1, 0,2617		       wcd938x_get_swr_port, wcd938x_set_swr_port),2618	SOC_SINGLE_EXT("DSD_L Switch", WCD938X_DSD_L, 0, 1, 0,2619		       wcd938x_get_swr_port, wcd938x_set_swr_port),2620	SOC_SINGLE_EXT("DSD_R Switch", WCD938X_DSD_R, 0, 1, 0,2621		       wcd938x_get_swr_port, wcd938x_set_swr_port),2622	SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 1, line_gain),2623	SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 1, line_gain),2624	WCD938X_EAR_PA_GAIN_TLV("EAR_PA Volume", WCD938X_ANA_EAR_COMPANDER_CTL,2625				2, 0x10, 0, ear_pa_gain),2626	SOC_SINGLE_EXT("ADC1 Switch", WCD938X_ADC1, 1, 1, 0,2627		       wcd938x_get_swr_port, wcd938x_set_swr_port),2628	SOC_SINGLE_EXT("ADC2 Switch", WCD938X_ADC2, 1, 1, 0,2629		       wcd938x_get_swr_port, wcd938x_set_swr_port),2630	SOC_SINGLE_EXT("ADC3 Switch", WCD938X_ADC3, 1, 1, 0,2631		       wcd938x_get_swr_port, wcd938x_set_swr_port),2632	SOC_SINGLE_EXT("ADC4 Switch", WCD938X_ADC4, 1, 1, 0,2633		       wcd938x_get_swr_port, wcd938x_set_swr_port),2634	SOC_SINGLE_EXT("DMIC0 Switch", WCD938X_DMIC0, 1, 1, 0,2635		       wcd938x_get_swr_port, wcd938x_set_swr_port),2636	SOC_SINGLE_EXT("DMIC1 Switch", WCD938X_DMIC1, 1, 1, 0,2637		       wcd938x_get_swr_port, wcd938x_set_swr_port),2638	SOC_SINGLE_EXT("MBHC Switch", WCD938X_MBHC, 1, 1, 0,2639		       wcd938x_get_swr_port, wcd938x_set_swr_port),2640	SOC_SINGLE_EXT("DMIC2 Switch", WCD938X_DMIC2, 1, 1, 0,2641		       wcd938x_get_swr_port, wcd938x_set_swr_port),2642	SOC_SINGLE_EXT("DMIC3 Switch", WCD938X_DMIC3, 1, 1, 0,2643		       wcd938x_get_swr_port, wcd938x_set_swr_port),2644	SOC_SINGLE_EXT("DMIC4 Switch", WCD938X_DMIC4, 1, 1, 0,2645		       wcd938x_get_swr_port, wcd938x_set_swr_port),2646	SOC_SINGLE_EXT("DMIC5 Switch", WCD938X_DMIC5, 1, 1, 0,2647		       wcd938x_get_swr_port, wcd938x_set_swr_port),2648	SOC_SINGLE_EXT("DMIC6 Switch", WCD938X_DMIC6, 1, 1, 0,2649		       wcd938x_get_swr_port, wcd938x_set_swr_port),2650	SOC_SINGLE_EXT("DMIC7 Switch", WCD938X_DMIC7, 1, 1, 0,2651		       wcd938x_get_swr_port, wcd938x_set_swr_port),2652	SOC_SINGLE_EXT("LDOH Enable Switch", SND_SOC_NOPM, 0, 1, 0,2653		       wcd938x_ldoh_get, wcd938x_ldoh_put),2654 2655	SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0, analog_gain),2656	SOC_SINGLE_TLV("ADC2 Volume", WCD938X_ANA_TX_CH2, 0, 20, 0, analog_gain),2657	SOC_SINGLE_TLV("ADC3 Volume", WCD938X_ANA_TX_CH3, 0, 20, 0, analog_gain),2658	SOC_SINGLE_TLV("ADC4 Volume", WCD938X_ANA_TX_CH4, 0, 20, 0, analog_gain),2659};2660 2661static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {2662 2663	/*input widgets*/2664	SND_SOC_DAPM_INPUT("AMIC1"),2665	SND_SOC_DAPM_INPUT("AMIC2"),2666	SND_SOC_DAPM_INPUT("AMIC3"),2667	SND_SOC_DAPM_INPUT("AMIC4"),2668	SND_SOC_DAPM_INPUT("AMIC5"),2669	SND_SOC_DAPM_INPUT("AMIC6"),2670	SND_SOC_DAPM_INPUT("AMIC7"),2671	SND_SOC_DAPM_MIC("Analog Mic1", NULL),2672	SND_SOC_DAPM_MIC("Analog Mic2", NULL),2673	SND_SOC_DAPM_MIC("Analog Mic3", NULL),2674	SND_SOC_DAPM_MIC("Analog Mic4", NULL),2675	SND_SOC_DAPM_MIC("Analog Mic5", NULL),2676 2677	/*tx widgets*/2678	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,2679			   wcd938x_codec_enable_adc,2680			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2681	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0,2682			   wcd938x_codec_enable_adc,2683			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2684	SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 2, 0,2685			   wcd938x_codec_enable_adc,2686			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2687	SND_SOC_DAPM_ADC_E("ADC4", NULL, SND_SOC_NOPM, 3, 0,2688			   wcd938x_codec_enable_adc,2689			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2690	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,2691			   wcd938x_codec_enable_dmic,2692			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2693	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0,2694			   wcd938x_codec_enable_dmic,2695			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2696	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 2, 0,2697			   wcd938x_codec_enable_dmic,2698			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2699	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 3, 0,2700			   wcd938x_codec_enable_dmic,2701			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2702	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 4, 0,2703			   wcd938x_codec_enable_dmic,2704			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2705	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 5, 0,2706			   wcd938x_codec_enable_dmic,2707			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2708	SND_SOC_DAPM_ADC_E("DMIC7", NULL, SND_SOC_NOPM, 6, 0,2709			   wcd938x_codec_enable_dmic,2710			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2711	SND_SOC_DAPM_ADC_E("DMIC8", NULL, SND_SOC_NOPM, 7, 0,2712			   wcd938x_codec_enable_dmic,2713			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2714 2715	SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0,2716			     NULL, 0, wcd938x_adc_enable_req,2717			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2718	SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 1, 0,2719			     NULL, 0, wcd938x_adc_enable_req,2720			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2721	SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 2, 0,2722			     NULL, 0, wcd938x_adc_enable_req,2723			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2724	SND_SOC_DAPM_MIXER_E("ADC4 REQ", SND_SOC_NOPM, 3, 0, NULL, 0,2725			     wcd938x_adc_enable_req,2726			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2727 2728	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),2729	SND_SOC_DAPM_MUX("ADC3 MUX", SND_SOC_NOPM, 0, 0, &tx_adc3_mux),2730	SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0, &tx_adc4_mux),2731	SND_SOC_DAPM_MUX("HDR12 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr12_mux),2732	SND_SOC_DAPM_MUX("HDR34 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr34_mux),2733 2734	/*tx mixers*/2735	SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch,2736			     ARRAY_SIZE(adc1_switch), wcd938x_tx_swr_ctrl,2737			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2738	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0, adc2_switch,2739			     ARRAY_SIZE(adc2_switch), wcd938x_tx_swr_ctrl,2740			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2741	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch,2742			     ARRAY_SIZE(adc3_switch), wcd938x_tx_swr_ctrl,2743			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2744	SND_SOC_DAPM_MIXER_E("ADC4_MIXER", SND_SOC_NOPM, 0, 0, adc4_switch,2745			     ARRAY_SIZE(adc4_switch), wcd938x_tx_swr_ctrl,2746			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2747	SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch,2748			     ARRAY_SIZE(dmic1_switch), wcd938x_tx_swr_ctrl,2749			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2750	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0, 0, dmic2_switch,2751			     ARRAY_SIZE(dmic2_switch), wcd938x_tx_swr_ctrl,2752			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2753	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0, 0, dmic3_switch,2754			     ARRAY_SIZE(dmic3_switch), wcd938x_tx_swr_ctrl,2755			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2756	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0, 0, dmic4_switch,2757			     ARRAY_SIZE(dmic4_switch), wcd938x_tx_swr_ctrl,2758			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2759	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0, 0, dmic5_switch,2760			     ARRAY_SIZE(dmic5_switch), wcd938x_tx_swr_ctrl,2761			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2762	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0, 0, dmic6_switch,2763			     ARRAY_SIZE(dmic6_switch), wcd938x_tx_swr_ctrl,2764			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2765	SND_SOC_DAPM_MIXER_E("DMIC7_MIXER", SND_SOC_NOPM, 0, 0, dmic7_switch,2766			     ARRAY_SIZE(dmic7_switch), wcd938x_tx_swr_ctrl,2767			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2768	SND_SOC_DAPM_MIXER_E("DMIC8_MIXER", SND_SOC_NOPM, 0, 0, dmic8_switch,2769			     ARRAY_SIZE(dmic8_switch), wcd938x_tx_swr_ctrl,2770			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),2771	/* micbias widgets*/2772	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,2773			    wcd938x_codec_enable_micbias,2774			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2775			    SND_SOC_DAPM_POST_PMD),2776	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,2777			    wcd938x_codec_enable_micbias,2778			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2779			    SND_SOC_DAPM_POST_PMD),2780	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,2781			    wcd938x_codec_enable_micbias,2782			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2783			    SND_SOC_DAPM_POST_PMD),2784	SND_SOC_DAPM_SUPPLY("MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,2785			    wcd938x_codec_enable_micbias,2786			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2787			    SND_SOC_DAPM_POST_PMD),2788 2789	/* micbias pull up widgets*/2790	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,2791				wcd938x_codec_enable_micbias_pullup,2792				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2793				SND_SOC_DAPM_POST_PMD),2794	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,2795				wcd938x_codec_enable_micbias_pullup,2796				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2797				SND_SOC_DAPM_POST_PMD),2798	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,2799				wcd938x_codec_enable_micbias_pullup,2800				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2801				SND_SOC_DAPM_POST_PMD),2802	SND_SOC_DAPM_SUPPLY("VA MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,2803				wcd938x_codec_enable_micbias_pullup,2804				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2805				SND_SOC_DAPM_POST_PMD),2806 2807	/*output widgets tx*/2808	SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),2809	SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),2810	SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"),2811	SND_SOC_DAPM_OUTPUT("ADC4_OUTPUT"),2812	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),2813	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),2814	SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"),2815	SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"),2816	SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"),2817	SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"),2818	SND_SOC_DAPM_OUTPUT("DMIC7_OUTPUT"),2819	SND_SOC_DAPM_OUTPUT("DMIC8_OUTPUT"),2820 2821	SND_SOC_DAPM_INPUT("IN1_HPHL"),2822	SND_SOC_DAPM_INPUT("IN2_HPHR"),2823	SND_SOC_DAPM_INPUT("IN3_AUX"),2824 2825	/*rx widgets*/2826	SND_SOC_DAPM_PGA_E("EAR PGA", WCD938X_ANA_EAR, 7, 0, NULL, 0,2827			   wcd938x_codec_enable_ear_pa,2828			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2829			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2830	SND_SOC_DAPM_PGA_E("AUX PGA", WCD938X_AUX_AUXPA, 7, 0, NULL, 0,2831			   wcd938x_codec_enable_aux_pa,2832			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2833			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2834	SND_SOC_DAPM_PGA_E("HPHL PGA", WCD938X_ANA_HPH, 7, 0, NULL, 0,2835			   wcd938x_codec_enable_hphl_pa,2836			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2837			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2838	SND_SOC_DAPM_PGA_E("HPHR PGA", WCD938X_ANA_HPH, 6, 0, NULL, 0,2839			   wcd938x_codec_enable_hphr_pa,2840			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2841			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2842 2843	SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,2844			   wcd938x_codec_hphl_dac_event,2845			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2846			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2847	SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0,2848			   wcd938x_codec_hphr_dac_event,2849			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2850			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2851	SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0,2852			   wcd938x_codec_ear_dac_event,2853			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2854			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2855	SND_SOC_DAPM_DAC_E("RDAC4", NULL, SND_SOC_NOPM, 0, 0,2856			   wcd938x_codec_aux_dac_event,2857			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2858			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),2859 2860	SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),2861 2862	SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0, NULL, 0),2863	SND_SOC_DAPM_SUPPLY("RXCLK", SND_SOC_NOPM, 0, 0,2864			    wcd938x_codec_enable_rxclk,2865			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |2866			    SND_SOC_DAPM_POST_PMD),2867 2868	SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0, NULL, 0),2869 2870	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),2871	SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),2872	SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),2873 2874	/* rx mixer widgets*/2875	SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0,2876			   ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)),2877	SND_SOC_DAPM_MIXER("AUX_RDAC", SND_SOC_NOPM, 0, 0,2878			   aux_rdac_switch, ARRAY_SIZE(aux_rdac_switch)),2879	SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0,2880			   hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)),2881	SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0,2882			   hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)),2883 2884	/*output widgets rx*/2885	SND_SOC_DAPM_OUTPUT("EAR"),2886	SND_SOC_DAPM_OUTPUT("AUX"),2887	SND_SOC_DAPM_OUTPUT("HPHL"),2888	SND_SOC_DAPM_OUTPUT("HPHR"),2889 2890};2891 2892static const struct snd_soc_dapm_route wcd938x_audio_map[] = {2893	{"ADC1_OUTPUT", NULL, "ADC1_MIXER"},2894	{"ADC1_MIXER", "Switch", "ADC1 REQ"},2895	{"ADC1 REQ", NULL, "ADC1"},2896	{"ADC1", NULL, "AMIC1"},2897 2898	{"ADC2_OUTPUT", NULL, "ADC2_MIXER"},2899	{"ADC2_MIXER", "Switch", "ADC2 REQ"},2900	{"ADC2 REQ", NULL, "ADC2"},2901	{"ADC2", NULL, "HDR12 MUX"},2902	{"HDR12 MUX", "NO_HDR12", "ADC2 MUX"},2903	{"HDR12 MUX", "HDR12", "AMIC1"},2904	{"ADC2 MUX", "INP3", "AMIC3"},2905	{"ADC2 MUX", "INP2", "AMIC2"},2906 2907	{"ADC3_OUTPUT", NULL, "ADC3_MIXER"},2908	{"ADC3_MIXER", "Switch", "ADC3 REQ"},2909	{"ADC3 REQ", NULL, "ADC3"},2910	{"ADC3", NULL, "HDR34 MUX"},2911	{"HDR34 MUX", "NO_HDR34", "ADC3 MUX"},2912	{"HDR34 MUX", "HDR34", "AMIC5"},2913	{"ADC3 MUX", "INP4", "AMIC4"},2914	{"ADC3 MUX", "INP6", "AMIC6"},2915 2916	{"ADC4_OUTPUT", NULL, "ADC4_MIXER"},2917	{"ADC4_MIXER", "Switch", "ADC4 REQ"},2918	{"ADC4 REQ", NULL, "ADC4"},2919	{"ADC4", NULL, "ADC4 MUX"},2920	{"ADC4 MUX", "INP5", "AMIC5"},2921	{"ADC4 MUX", "INP7", "AMIC7"},2922 2923	{"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"},2924	{"DMIC1_MIXER", "Switch", "DMIC1"},2925 2926	{"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"},2927	{"DMIC2_MIXER", "Switch", "DMIC2"},2928 2929	{"DMIC3_OUTPUT", NULL, "DMIC3_MIXER"},2930	{"DMIC3_MIXER", "Switch", "DMIC3"},2931 2932	{"DMIC4_OUTPUT", NULL, "DMIC4_MIXER"},2933	{"DMIC4_MIXER", "Switch", "DMIC4"},2934 2935	{"DMIC5_OUTPUT", NULL, "DMIC5_MIXER"},2936	{"DMIC5_MIXER", "Switch", "DMIC5"},2937 2938	{"DMIC6_OUTPUT", NULL, "DMIC6_MIXER"},2939	{"DMIC6_MIXER", "Switch", "DMIC6"},2940 2941	{"DMIC7_OUTPUT", NULL, "DMIC7_MIXER"},2942	{"DMIC7_MIXER", "Switch", "DMIC7"},2943 2944	{"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"},2945	{"DMIC8_MIXER", "Switch", "DMIC8"},2946 2947	{"IN1_HPHL", NULL, "VDD_BUCK"},2948	{"IN1_HPHL", NULL, "CLS_H_PORT"},2949 2950	{"RX1", NULL, "IN1_HPHL"},2951	{"RX1", NULL, "RXCLK"},2952	{"RDAC1", NULL, "RX1"},2953	{"HPHL_RDAC", "Switch", "RDAC1"},2954	{"HPHL PGA", NULL, "HPHL_RDAC"},2955	{"HPHL", NULL, "HPHL PGA"},2956 2957	{"IN2_HPHR", NULL, "VDD_BUCK"},2958	{"IN2_HPHR", NULL, "CLS_H_PORT"},2959	{"RX2", NULL, "IN2_HPHR"},2960	{"RDAC2", NULL, "RX2"},2961	{"RX2", NULL, "RXCLK"},2962	{"HPHR_RDAC", "Switch", "RDAC2"},2963	{"HPHR PGA", NULL, "HPHR_RDAC"},2964	{"HPHR", NULL, "HPHR PGA"},2965 2966	{"IN3_AUX", NULL, "VDD_BUCK"},2967	{"IN3_AUX", NULL, "CLS_H_PORT"},2968	{"RX3", NULL, "IN3_AUX"},2969	{"RDAC4", NULL, "RX3"},2970	{"RX3", NULL, "RXCLK"},2971	{"AUX_RDAC", "Switch", "RDAC4"},2972	{"AUX PGA", NULL, "AUX_RDAC"},2973	{"AUX", NULL, "AUX PGA"},2974 2975	{"RDAC3_MUX", "RX3", "RX3"},2976	{"RDAC3_MUX", "RX1", "RX1"},2977	{"RDAC3", NULL, "RDAC3_MUX"},2978	{"EAR_RDAC", "Switch", "RDAC3"},2979	{"EAR PGA", NULL, "EAR_RDAC"},2980	{"EAR", NULL, "EAR PGA"},2981};2982 2983static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x)2984{2985	int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;2986 2987	/* set micbias voltage */2988	vout_ctl_1 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb1_mv);2989	vout_ctl_2 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb2_mv);2990	vout_ctl_3 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb3_mv);2991	vout_ctl_4 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb4_mv);2992	if (vout_ctl_1 < 0 || vout_ctl_2 < 0 || vout_ctl_3 < 0 || vout_ctl_4 < 0)2993		return -EINVAL;2994 2995	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB1,2996			   WCD938X_MICB_VOUT_MASK, vout_ctl_1);2997	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB2,2998			   WCD938X_MICB_VOUT_MASK, vout_ctl_2);2999	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB3,3000			   WCD938X_MICB_VOUT_MASK, vout_ctl_3);3001	regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB4,3002			   WCD938X_MICB_VOUT_MASK, vout_ctl_4);3003 3004	return 0;3005}3006 3007static irqreturn_t wcd938x_wd_handle_irq(int irq, void *data)3008{3009	return IRQ_HANDLED;3010}3011 3012static const struct irq_chip wcd_irq_chip = {3013	.name = "WCD938x",3014};3015 3016static int wcd_irq_chip_map(struct irq_domain *irqd, unsigned int virq,3017			irq_hw_number_t hw)3018{3019	irq_set_chip_and_handler(virq, &wcd_irq_chip, handle_simple_irq);3020	irq_set_nested_thread(virq, 1);3021	irq_set_noprobe(virq);3022 3023	return 0;3024}3025 3026static const struct irq_domain_ops wcd_domain_ops = {3027	.map = wcd_irq_chip_map,3028};3029 3030static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev)3031{3032 3033	wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL);3034	if (!(wcd->virq)) {3035		dev_err(dev, "%s: Failed to add IRQ domain\n", __func__);3036		return -EINVAL;3037	}3038 3039	return devm_regmap_add_irq_chip(dev, wcd->regmap,3040					irq_create_mapping(wcd->virq, 0),3041					IRQF_ONESHOT, 0, &wcd938x_regmap_irq_chip,3042					&wcd->irq_chip);3043}3044 3045static int wcd938x_soc_codec_probe(struct snd_soc_component *component)3046{3047	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);3048	struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev;3049	struct device *dev = component->dev;3050	unsigned long time_left;3051	int ret, i;3052 3053	time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,3054						msecs_to_jiffies(2000));3055	if (!time_left) {3056		dev_err(dev, "soundwire device init timeout\n");3057		return -ETIMEDOUT;3058	}3059 3060	snd_soc_component_init_regmap(component, wcd938x->regmap);3061 3062	ret = pm_runtime_resume_and_get(dev);3063	if (ret < 0)3064		return ret;3065 3066	wcd938x->variant = snd_soc_component_read_field(component,3067						 WCD938X_DIGITAL_EFUSE_REG_0,3068						 WCD938X_ID_MASK);3069 3070	wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X);3071	if (IS_ERR(wcd938x->clsh_info)) {3072		pm_runtime_put(dev);3073		return PTR_ERR(wcd938x->clsh_info);3074	}3075 3076	wcd938x_io_init(wcd938x);3077	/* Set all interrupts as edge triggered */3078	for (i = 0; i < wcd938x_regmap_irq_chip.num_regs; i++) {3079		regmap_write(wcd938x->regmap,3080			     (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);3081	}3082 3083	pm_runtime_put(dev);3084 3085	wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,3086						       WCD938X_IRQ_HPHR_PDM_WD_INT);3087	wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,3088						       WCD938X_IRQ_HPHL_PDM_WD_INT);3089	wcd938x->aux_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,3090						       WCD938X_IRQ_AUX_PDM_WD_INT);3091 3092	/* Request for watchdog interrupt */3093	ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq,3094				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,3095				   "HPHR PDM WD INT", wcd938x);3096	if (ret) {3097		dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret);3098		goto err_free_clsh_ctrl;3099	}3100 3101	ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq,3102				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,3103				   "HPHL PDM WD INT", wcd938x);3104	if (ret) {3105		dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret);3106		goto err_free_hphr_pdm_wd_int;3107	}3108 3109	ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq,3110				   IRQF_ONESHOT | IRQF_TRIGGER_RISING,3111				   "AUX PDM WD INT", wcd938x);3112	if (ret) {3113		dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret);3114		goto err_free_hphl_pdm_wd_int;3115	}3116 3117	/* Disable watchdog interrupt for HPH and AUX */3118	disable_irq_nosync(wcd938x->hphr_pdm_wd_int);3119	disable_irq_nosync(wcd938x->hphl_pdm_wd_int);3120	disable_irq_nosync(wcd938x->aux_pdm_wd_int);3121 3122	switch (wcd938x->variant) {3123	case WCD9380:3124		ret = snd_soc_add_component_controls(component, wcd9380_snd_controls,3125					ARRAY_SIZE(wcd9380_snd_controls));3126		if (ret < 0) {3127			dev_err(component->dev,3128				"%s: Failed to add snd ctrls for variant: %d\n",3129				__func__, wcd938x->variant);3130			goto err_free_aux_pdm_wd_int;3131		}3132		break;3133	case WCD9385:3134		ret = snd_soc_add_component_controls(component, wcd9385_snd_controls,3135					ARRAY_SIZE(wcd9385_snd_controls));3136		if (ret < 0) {3137			dev_err(component->dev,3138				"%s: Failed to add snd ctrls for variant: %d\n",3139				__func__, wcd938x->variant);3140			goto err_free_aux_pdm_wd_int;3141		}3142		break;3143	default:3144		break;3145	}3146 3147	ret = wcd938x_mbhc_init(component);3148	if (ret) {3149		dev_err(component->dev,  "mbhc initialization failed\n");3150		goto err_free_aux_pdm_wd_int;3151	}3152 3153	return 0;3154 3155err_free_aux_pdm_wd_int:3156	free_irq(wcd938x->aux_pdm_wd_int, wcd938x);3157err_free_hphl_pdm_wd_int:3158	free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);3159err_free_hphr_pdm_wd_int:3160	free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);3161err_free_clsh_ctrl:3162	wcd_clsh_ctrl_free(wcd938x->clsh_info);3163 3164	return ret;3165}3166 3167static void wcd938x_soc_codec_remove(struct snd_soc_component *component)3168{3169	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);3170 3171	wcd938x_mbhc_deinit(component);3172 3173	free_irq(wcd938x->aux_pdm_wd_int, wcd938x);3174	free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);3175	free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);3176 3177	wcd_clsh_ctrl_free(wcd938x->clsh_info);3178}3179 3180static int wcd938x_codec_set_jack(struct snd_soc_component *comp,3181				  struct snd_soc_jack *jack, void *data)3182{3183	struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev);3184 3185	if (jack)3186		return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack);3187	else3188		wcd_mbhc_stop(wcd->wcd_mbhc);3189 3190	return 0;3191}3192 3193static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {3194	.name = "wcd938x_codec",3195	.probe = wcd938x_soc_codec_probe,3196	.remove = wcd938x_soc_codec_remove,3197	.controls = wcd938x_snd_controls,3198	.num_controls = ARRAY_SIZE(wcd938x_snd_controls),3199	.dapm_widgets = wcd938x_dapm_widgets,3200	.num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets),3201	.dapm_routes = wcd938x_audio_map,3202	.num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map),3203	.set_jack = wcd938x_codec_set_jack,3204	.endianness = 1,3205};3206 3207static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd)3208{3209	struct device_node *np = dev->of_node;3210	u32 prop_val = 0;3211	int rc = 0;3212 3213	rc = of_property_read_u32(np, "qcom,micbias1-microvolt",  &prop_val);3214	if (!rc)3215		wcd->micb1_mv = prop_val/1000;3216	else3217		dev_info(dev, "%s: Micbias1 DT property not found\n", __func__);3218 3219	rc = of_property_read_u32(np, "qcom,micbias2-microvolt",  &prop_val);3220	if (!rc)3221		wcd->micb2_mv = prop_val/1000;3222	else3223		dev_info(dev, "%s: Micbias2 DT property not found\n", __func__);3224 3225	rc = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val);3226	if (!rc)3227		wcd->micb3_mv = prop_val/1000;3228	else3229		dev_info(dev, "%s: Micbias3 DT property not found\n", __func__);3230 3231	rc = of_property_read_u32(np, "qcom,micbias4-microvolt",  &prop_val);3232	if (!rc)3233		wcd->micb4_mv = prop_val/1000;3234	else3235		dev_info(dev, "%s: Micbias4 DT property not found\n", __func__);3236}3237 3238static bool wcd938x_swap_gnd_mic(struct snd_soc_component *component, bool active)3239{3240	int value;3241 3242	struct wcd938x_priv *wcd938x;3243 3244	wcd938x = snd_soc_component_get_drvdata(component);3245 3246	value = gpiod_get_value(wcd938x->us_euro_gpio);3247 3248	gpiod_set_value(wcd938x->us_euro_gpio, !value);3249 3250	return true;3251}3252 3253 3254static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev)3255{3256	struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg;3257	int ret;3258 3259	wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0);3260	if (wcd938x->reset_gpio < 0)3261		return dev_err_probe(dev, wcd938x->reset_gpio,3262				     "Failed to get reset gpio\n");3263 3264	wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro",3265						GPIOD_OUT_LOW);3266	if (IS_ERR(wcd938x->us_euro_gpio))3267		return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio),3268				     "us-euro swap Control GPIO not found\n");3269 3270	cfg->swap_gnd_mic = wcd938x_swap_gnd_mic;3271 3272	wcd938x->supplies[0].supply = "vdd-rxtx";3273	wcd938x->supplies[1].supply = "vdd-io";3274	wcd938x->supplies[2].supply = "vdd-buck";3275	wcd938x->supplies[3].supply = "vdd-mic-bias";3276 3277	ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies);3278	if (ret)3279		return dev_err_probe(dev, ret, "Failed to get supplies\n");3280 3281	ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies);3282	if (ret) {3283		regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);3284		return dev_err_probe(dev, ret, "Failed to enable supplies\n");3285	}3286 3287	wcd938x_dt_parse_micbias_info(dev, wcd938x);3288 3289	cfg->mbhc_micbias = MIC_BIAS_2;3290	cfg->anc_micbias = MIC_BIAS_2;3291	cfg->v_hs_max = WCD_MBHC_HS_V_MAX;3292	cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS;3293	cfg->micb_mv = wcd938x->micb2_mv;3294	cfg->linein_th = 5000;3295	cfg->hs_thr = 1700;3296	cfg->hph_thr = 50;3297 3298	wcd_dt_parse_mbhc_data(dev, cfg);3299 3300	return 0;3301}3302 3303static int wcd938x_reset(struct wcd938x_priv *wcd938x)3304{3305	gpio_direction_output(wcd938x->reset_gpio, 0);3306	/* 20us sleep required after pulling the reset gpio to LOW */3307	usleep_range(20, 30);3308	gpio_set_value(wcd938x->reset_gpio, 1);3309	/* 20us sleep required after pulling the reset gpio to HIGH */3310	usleep_range(20, 30);3311 3312	return 0;3313}3314 3315static int wcd938x_codec_hw_params(struct snd_pcm_substream *substream,3316				struct snd_pcm_hw_params *params,3317				struct snd_soc_dai *dai)3318{3319	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);3320	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];3321 3322	return wcd938x_sdw_hw_params(wcd, substream, params, dai);3323}3324 3325static int wcd938x_codec_free(struct snd_pcm_substream *substream,3326			      struct snd_soc_dai *dai)3327{3328	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);3329	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];3330 3331	return wcd938x_sdw_free(wcd, substream, dai);3332}3333 3334static int wcd938x_codec_set_sdw_stream(struct snd_soc_dai *dai,3335				  void *stream, int direction)3336{3337	struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev);3338	struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id];3339 3340	return wcd938x_sdw_set_sdw_stream(wcd, dai, stream, direction);3341 3342}3343 3344static const struct snd_soc_dai_ops wcd938x_sdw_dai_ops = {3345	.hw_params = wcd938x_codec_hw_params,3346	.hw_free = wcd938x_codec_free,3347	.set_stream = wcd938x_codec_set_sdw_stream,3348};3349 3350static struct snd_soc_dai_driver wcd938x_dais[] = {3351	[AIF1_PB] = {3352		.name = "wcd938x-sdw-rx",3353		.playback = {3354			.stream_name = "WCD AIF1 Playback",3355			.rates = WCD938X_RATES_MASK | WCD938X_FRAC_RATES_MASK,3356			.formats = WCD938X_FORMATS_S16_S24_LE,3357			.rate_max = 192000,3358			.rate_min = 8000,3359			.channels_min = 1,3360			.channels_max = 2,3361		},3362		.ops = &wcd938x_sdw_dai_ops,3363	},3364	[AIF1_CAP] = {3365		.name = "wcd938x-sdw-tx",3366		.capture = {3367			.stream_name = "WCD AIF1 Capture",3368			.rates = WCD938X_RATES_MASK,3369			.formats = SNDRV_PCM_FMTBIT_S16_LE,3370			.rate_min = 8000,3371			.rate_max = 192000,3372			.channels_min = 1,3373			.channels_max = 4,3374		},3375		.ops = &wcd938x_sdw_dai_ops,3376	},3377};3378 3379static int wcd938x_bind(struct device *dev)3380{3381	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);3382	int ret;3383 3384	ret = component_bind_all(dev, wcd938x);3385	if (ret) {3386		dev_err(dev, "%s: Slave bind failed, ret = %d\n",3387			__func__, ret);3388		return ret;3389	}3390 3391	wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode);3392	if (!wcd938x->rxdev) {3393		dev_err(dev, "could not find slave with matching of node\n");3394		ret = -EINVAL;3395		goto err_unbind;3396	}3397	wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev);3398	wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x;3399 3400	wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode);3401	if (!wcd938x->txdev) {3402		dev_err(dev, "could not find txslave with matching of node\n");3403		ret = -EINVAL;3404		goto err_put_rxdev;3405	}3406	wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev);3407	wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x;3408	wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev);3409 3410	/* As TX is main CSR reg interface, which should not be suspended first.3411	 * expicilty add the dependency link */3412	if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS |3413			    DL_FLAG_PM_RUNTIME)) {3414		dev_err(dev, "could not devlink tx and rx\n");3415		ret = -EINVAL;3416		goto err_put_txdev;3417	}3418 3419	if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS |3420					DL_FLAG_PM_RUNTIME)) {3421		dev_err(dev, "could not devlink wcd and tx\n");3422		ret = -EINVAL;3423		goto err_remove_rxtx_link;3424	}3425 3426	if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS |3427					DL_FLAG_PM_RUNTIME)) {3428		dev_err(dev, "could not devlink wcd and rx\n");3429		ret = -EINVAL;3430		goto err_remove_tx_link;3431	}3432 3433	wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL);3434	if (!wcd938x->regmap) {3435		dev_err(dev, "could not get TX device regmap\n");3436		ret = -EINVAL;3437		goto err_remove_rx_link;3438	}3439 3440	ret = wcd938x_irq_init(wcd938x, dev);3441	if (ret) {3442		dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret);3443		goto err_remove_rx_link;3444	}3445 3446	wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq;3447	wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq;3448 3449	ret = wcd938x_set_micbias_data(wcd938x);3450	if (ret < 0) {3451		dev_err(dev, "%s: bad micbias pdata\n", __func__);3452		goto err_remove_rx_link;3453	}3454 3455	ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x,3456					 wcd938x_dais, ARRAY_SIZE(wcd938x_dais));3457	if (ret) {3458		dev_err(dev, "%s: Codec registration failed\n",3459				__func__);3460		goto err_remove_rx_link;3461	}3462 3463	return 0;3464 3465err_remove_rx_link:3466	device_link_remove(dev, wcd938x->rxdev);3467err_remove_tx_link:3468	device_link_remove(dev, wcd938x->txdev);3469err_remove_rxtx_link:3470	device_link_remove(wcd938x->rxdev, wcd938x->txdev);3471err_put_txdev:3472	put_device(wcd938x->txdev);3473err_put_rxdev:3474	put_device(wcd938x->rxdev);3475err_unbind:3476	component_unbind_all(dev, wcd938x);3477 3478	return ret;3479}3480 3481static void wcd938x_unbind(struct device *dev)3482{3483	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);3484 3485	snd_soc_unregister_component(dev);3486	device_link_remove(dev, wcd938x->txdev);3487	device_link_remove(dev, wcd938x->rxdev);3488	device_link_remove(wcd938x->rxdev, wcd938x->txdev);3489	put_device(wcd938x->txdev);3490	put_device(wcd938x->rxdev);3491	component_unbind_all(dev, wcd938x);3492}3493 3494static const struct component_master_ops wcd938x_comp_ops = {3495	.bind   = wcd938x_bind,3496	.unbind = wcd938x_unbind,3497};3498 3499static int wcd938x_add_slave_components(struct wcd938x_priv *wcd938x,3500					struct device *dev,3501					struct component_match **matchptr)3502{3503	struct device_node *np;3504 3505	np = dev->of_node;3506 3507	wcd938x->rxnode = of_parse_phandle(np, "qcom,rx-device", 0);3508	if (!wcd938x->rxnode) {3509		dev_err(dev, "%s: Rx-device node not defined\n", __func__);3510		return -ENODEV;3511	}3512 3513	of_node_get(wcd938x->rxnode);3514	component_match_add_release(dev, matchptr, component_release_of,3515				    component_compare_of, wcd938x->rxnode);3516 3517	wcd938x->txnode = of_parse_phandle(np, "qcom,tx-device", 0);3518	if (!wcd938x->txnode) {3519		dev_err(dev, "%s: Tx-device node not defined\n", __func__);3520		return -ENODEV;3521	}3522	of_node_get(wcd938x->txnode);3523	component_match_add_release(dev, matchptr, component_release_of,3524				    component_compare_of, wcd938x->txnode);3525	return 0;3526}3527 3528static int wcd938x_probe(struct platform_device *pdev)3529{3530	struct component_match *match = NULL;3531	struct wcd938x_priv *wcd938x = NULL;3532	struct device *dev = &pdev->dev;3533	int ret;3534 3535	wcd938x = devm_kzalloc(dev, sizeof(struct wcd938x_priv),3536				GFP_KERNEL);3537	if (!wcd938x)3538		return -ENOMEM;3539 3540	dev_set_drvdata(dev, wcd938x);3541	mutex_init(&wcd938x->micb_lock);3542 3543	ret = wcd938x_populate_dt_data(wcd938x, dev);3544	if (ret)3545		return ret;3546 3547	ret = wcd938x_add_slave_components(wcd938x, dev, &match);3548	if (ret)3549		goto err_disable_regulators;3550 3551	wcd938x_reset(wcd938x);3552 3553	ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match);3554	if (ret)3555		goto err_disable_regulators;3556 3557	pm_runtime_set_autosuspend_delay(dev, 1000);3558	pm_runtime_use_autosuspend(dev);3559	pm_runtime_mark_last_busy(dev);3560	pm_runtime_set_active(dev);3561	pm_runtime_enable(dev);3562	pm_runtime_idle(dev);3563 3564	return 0;3565 3566err_disable_regulators:3567	regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies);3568	regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);3569 3570	return ret;3571}3572 3573static void wcd938x_remove(struct platform_device *pdev)3574{3575	struct device *dev = &pdev->dev;3576	struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);3577 3578	component_master_del(dev, &wcd938x_comp_ops);3579 3580	pm_runtime_disable(dev);3581	pm_runtime_set_suspended(dev);3582	pm_runtime_dont_use_autosuspend(dev);3583 3584	regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies);3585	regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies);3586}3587 3588#if defined(CONFIG_OF)3589static const struct of_device_id wcd938x_dt_match[] = {3590	{ .compatible = "qcom,wcd9380-codec" },3591	{ .compatible = "qcom,wcd9385-codec" },3592	{}3593};3594MODULE_DEVICE_TABLE(of, wcd938x_dt_match);3595#endif3596 3597static struct platform_driver wcd938x_codec_driver = {3598	.probe = wcd938x_probe,3599	.remove = wcd938x_remove,3600	.driver = {3601		.name = "wcd938x_codec",3602		.of_match_table = of_match_ptr(wcd938x_dt_match),3603		.suppress_bind_attrs = true,3604	},3605};3606 3607module_platform_driver(wcd938x_codec_driver);3608MODULE_DESCRIPTION("WCD938X Codec driver");3609MODULE_LICENSE("GPL");3610