18d78602aSSrinivas Kandagatla // SPDX-License-Identifier: GPL-2.0-only 28d78602aSSrinivas Kandagatla // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. 38d78602aSSrinivas Kandagatla 48d78602aSSrinivas Kandagatla #include <linux/module.h> 58d78602aSSrinivas Kandagatla #include <linux/slab.h> 68d78602aSSrinivas Kandagatla #include <linux/platform_device.h> 78d78602aSSrinivas Kandagatla #include <linux/device.h> 88d78602aSSrinivas Kandagatla #include <linux/delay.h> 9db0b4aedSSrinivasa Rao Mandadapu #include <linux/gpio/consumer.h> 108d78602aSSrinivas Kandagatla #include <linux/kernel.h> 118d78602aSSrinivas Kandagatla #include <linux/pm_runtime.h> 128d78602aSSrinivas Kandagatla #include <linux/component.h> 138d78602aSSrinivas Kandagatla #include <sound/tlv.h> 148d78602aSSrinivas Kandagatla #include <linux/of_gpio.h> 158d78602aSSrinivas Kandagatla #include <linux/of.h> 168d78602aSSrinivas Kandagatla #include <sound/jack.h> 178d78602aSSrinivas Kandagatla #include <sound/pcm.h> 188d78602aSSrinivas Kandagatla #include <sound/pcm_params.h> 198d78602aSSrinivas Kandagatla #include <linux/regmap.h> 208d78602aSSrinivas Kandagatla #include <sound/soc.h> 218d78602aSSrinivas Kandagatla #include <sound/soc-dapm.h> 228d78602aSSrinivas Kandagatla #include <linux/regulator/consumer.h> 238d78602aSSrinivas Kandagatla 248d78602aSSrinivas Kandagatla #include "wcd-clsh-v2.h" 25bcee7ed0SSrinivas Kandagatla #include "wcd-mbhc-v2.h" 268d78602aSSrinivas Kandagatla #include "wcd938x.h" 278d78602aSSrinivas Kandagatla 288d78602aSSrinivas Kandagatla #define WCD938X_MAX_MICBIAS (4) 298d78602aSSrinivas Kandagatla #define WCD938X_MAX_SUPPLY (4) 308d78602aSSrinivas Kandagatla #define WCD938X_MBHC_MAX_BUTTONS (8) 318d78602aSSrinivas Kandagatla #define TX_ADC_MAX (4) 328d78602aSSrinivas Kandagatla #define WCD938X_TX_MAX_SWR_PORTS (5) 338d78602aSSrinivas Kandagatla 348d78602aSSrinivas Kandagatla #define WCD938X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ 358d78602aSSrinivas Kandagatla SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ 368d78602aSSrinivas Kandagatla SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) 378d78602aSSrinivas Kandagatla /* Fractional Rates */ 388d78602aSSrinivas Kandagatla #define WCD938X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ 398d78602aSSrinivas Kandagatla SNDRV_PCM_RATE_176400) 408d78602aSSrinivas Kandagatla #define WCD938X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \ 418d78602aSSrinivas Kandagatla SNDRV_PCM_FMTBIT_S24_LE) 428d78602aSSrinivas Kandagatla /* Convert from vout ctl to micbias voltage in mV */ 438d78602aSSrinivas Kandagatla #define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) 448d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_0P6MHZ (600000) 458d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_1P2MHZ (1200000) 468d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_2P4MHZ (2400000) 478d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_4P8MHZ (4800000) 488d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_9P6MHZ (9600000) 498d78602aSSrinivas Kandagatla #define SWR_CLK_RATE_11P2896MHZ (1128960) 508d78602aSSrinivas Kandagatla 518d78602aSSrinivas Kandagatla #define WCD938X_DRV_NAME "wcd938x_codec" 528d78602aSSrinivas Kandagatla #define WCD938X_VERSION_1_0 (1) 538d78602aSSrinivas Kandagatla #define EAR_RX_PATH_AUX (1) 548d78602aSSrinivas Kandagatla 558d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_HIFI 0x01 568d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_LO_HIF 0x02 578d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_NORMAL 0x03 588d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_LP 0x05 598d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_ULP1 0x09 608d78602aSSrinivas Kandagatla #define ADC_MODE_VAL_ULP2 0x0B 618d78602aSSrinivas Kandagatla 628d78602aSSrinivas Kandagatla /* Z value defined in milliohm */ 638d78602aSSrinivas Kandagatla #define WCD938X_ZDET_VAL_32 (32000) 648d78602aSSrinivas Kandagatla #define WCD938X_ZDET_VAL_400 (400000) 658d78602aSSrinivas Kandagatla #define WCD938X_ZDET_VAL_1200 (1200000) 668d78602aSSrinivas Kandagatla #define WCD938X_ZDET_VAL_100K (100000000) 678d78602aSSrinivas Kandagatla /* Z floating defined in ohms */ 688d78602aSSrinivas Kandagatla #define WCD938X_ZDET_FLOATING_IMPEDANCE (0x0FFFFFFE) 698d78602aSSrinivas Kandagatla #define WCD938X_ZDET_NUM_MEASUREMENTS (900) 708d78602aSSrinivas Kandagatla #define WCD938X_MBHC_GET_C1(c) ((c & 0xC000) >> 14) 718d78602aSSrinivas Kandagatla #define WCD938X_MBHC_GET_X1(x) (x & 0x3FFF) 728d78602aSSrinivas Kandagatla /* Z value compared in milliOhm */ 738d78602aSSrinivas Kandagatla #define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) 748d78602aSSrinivas Kandagatla #define WCD938X_MBHC_ZDET_CONST (86 * 16384) 758d78602aSSrinivas Kandagatla #define WCD938X_MBHC_MOISTURE_RREF R_24_KOHM 768d78602aSSrinivas Kandagatla #define WCD_MBHC_HS_V_MAX 1600 778d78602aSSrinivas Kandagatla 78e8ba1e05SSrinivas Kandagatla #define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ 79e8ba1e05SSrinivas Kandagatla { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 80e8ba1e05SSrinivas Kandagatla .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 81e8ba1e05SSrinivas Kandagatla SNDRV_CTL_ELEM_ACCESS_READWRITE,\ 82e8ba1e05SSrinivas Kandagatla .tlv.p = (tlv_array), \ 83e8ba1e05SSrinivas Kandagatla .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 84e8ba1e05SSrinivas Kandagatla .put = wcd938x_ear_pa_put_gain, \ 85e8ba1e05SSrinivas Kandagatla .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } 86e8ba1e05SSrinivas Kandagatla 878d78602aSSrinivas Kandagatla enum { 888d78602aSSrinivas Kandagatla WCD9380 = 0, 898d78602aSSrinivas Kandagatla WCD9385 = 5, 908d78602aSSrinivas Kandagatla }; 918d78602aSSrinivas Kandagatla 928d78602aSSrinivas Kandagatla enum { 938d78602aSSrinivas Kandagatla TX_HDR12 = 0, 948d78602aSSrinivas Kandagatla TX_HDR34, 958d78602aSSrinivas Kandagatla TX_HDR_MAX, 968d78602aSSrinivas Kandagatla }; 978d78602aSSrinivas Kandagatla 988d78602aSSrinivas Kandagatla enum { 998d78602aSSrinivas Kandagatla WCD_RX1, 1008d78602aSSrinivas Kandagatla WCD_RX2, 1018d78602aSSrinivas Kandagatla WCD_RX3 1028d78602aSSrinivas Kandagatla }; 1038d78602aSSrinivas Kandagatla 1048d78602aSSrinivas Kandagatla enum { 1058d78602aSSrinivas Kandagatla /* INTR_CTRL_INT_MASK_0 */ 1068d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0, 1078d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 1088d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_ELECT_INS_REM_DET, 1098d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 1108d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_SW_DET, 1118d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHR_OCP_INT, 1128d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHR_CNP_INT, 1138d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHL_OCP_INT, 1148d78602aSSrinivas Kandagatla 1158d78602aSSrinivas Kandagatla /* INTR_CTRL_INT_MASK_1 */ 1168d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHL_CNP_INT, 1178d78602aSSrinivas Kandagatla WCD938X_IRQ_EAR_CNP_INT, 1188d78602aSSrinivas Kandagatla WCD938X_IRQ_EAR_SCD_INT, 1198d78602aSSrinivas Kandagatla WCD938X_IRQ_AUX_CNP_INT, 1208d78602aSSrinivas Kandagatla WCD938X_IRQ_AUX_SCD_INT, 1218d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHL_PDM_WD_INT, 1228d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHR_PDM_WD_INT, 1238d78602aSSrinivas Kandagatla WCD938X_IRQ_AUX_PDM_WD_INT, 1248d78602aSSrinivas Kandagatla 1258d78602aSSrinivas Kandagatla /* INTR_CTRL_INT_MASK_2 */ 1268d78602aSSrinivas Kandagatla WCD938X_IRQ_LDORT_SCD_INT, 1278d78602aSSrinivas Kandagatla WCD938X_IRQ_MBHC_MOISTURE_INT, 1288d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHL_SURGE_DET_INT, 1298d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHR_SURGE_DET_INT, 1308d78602aSSrinivas Kandagatla WCD938X_NUM_IRQS, 1318d78602aSSrinivas Kandagatla }; 1328d78602aSSrinivas Kandagatla 1338d78602aSSrinivas Kandagatla enum { 1348d78602aSSrinivas Kandagatla WCD_ADC1 = 0, 1358d78602aSSrinivas Kandagatla WCD_ADC2, 1368d78602aSSrinivas Kandagatla WCD_ADC3, 1378d78602aSSrinivas Kandagatla WCD_ADC4, 1388d78602aSSrinivas Kandagatla ALLOW_BUCK_DISABLE, 1398d78602aSSrinivas Kandagatla HPH_COMP_DELAY, 1408d78602aSSrinivas Kandagatla HPH_PA_DELAY, 1418d78602aSSrinivas Kandagatla AMIC2_BCS_ENABLE, 1428d78602aSSrinivas Kandagatla WCD_SUPPLIES_LPM_MODE, 1438d78602aSSrinivas Kandagatla }; 1448d78602aSSrinivas Kandagatla 1458d78602aSSrinivas Kandagatla enum { 1468d78602aSSrinivas Kandagatla ADC_MODE_INVALID = 0, 1478d78602aSSrinivas Kandagatla ADC_MODE_HIFI, 1488d78602aSSrinivas Kandagatla ADC_MODE_LO_HIF, 1498d78602aSSrinivas Kandagatla ADC_MODE_NORMAL, 1508d78602aSSrinivas Kandagatla ADC_MODE_LP, 1518d78602aSSrinivas Kandagatla ADC_MODE_ULP1, 1528d78602aSSrinivas Kandagatla ADC_MODE_ULP2, 1538d78602aSSrinivas Kandagatla }; 1548d78602aSSrinivas Kandagatla 1558d78602aSSrinivas Kandagatla enum { 1568d78602aSSrinivas Kandagatla AIF1_PB = 0, 1578d78602aSSrinivas Kandagatla AIF1_CAP, 1588d78602aSSrinivas Kandagatla NUM_CODEC_DAIS, 1598d78602aSSrinivas Kandagatla }; 1608d78602aSSrinivas Kandagatla 161d5add08fSSrinivas Kandagatla static u8 tx_mode_bit[] = { 162d5add08fSSrinivas Kandagatla [ADC_MODE_INVALID] = 0x00, 163d5add08fSSrinivas Kandagatla [ADC_MODE_HIFI] = 0x01, 164d5add08fSSrinivas Kandagatla [ADC_MODE_LO_HIF] = 0x02, 165d5add08fSSrinivas Kandagatla [ADC_MODE_NORMAL] = 0x04, 166d5add08fSSrinivas Kandagatla [ADC_MODE_LP] = 0x08, 167d5add08fSSrinivas Kandagatla [ADC_MODE_ULP1] = 0x10, 168d5add08fSSrinivas Kandagatla [ADC_MODE_ULP2] = 0x20, 169d5add08fSSrinivas Kandagatla }; 170d5add08fSSrinivas Kandagatla 1718d78602aSSrinivas Kandagatla struct wcd938x_priv { 1728d78602aSSrinivas Kandagatla struct sdw_slave *tx_sdw_dev; 1738d78602aSSrinivas Kandagatla struct wcd938x_sdw_priv *sdw_priv[NUM_CODEC_DAIS]; 1748d78602aSSrinivas Kandagatla struct device *txdev; 1758d78602aSSrinivas Kandagatla struct device *rxdev; 1768d78602aSSrinivas Kandagatla struct device_node *rxnode, *txnode; 1778d78602aSSrinivas Kandagatla struct regmap *regmap; 178bcee7ed0SSrinivas Kandagatla struct mutex micb_lock; 179bcee7ed0SSrinivas Kandagatla /* mbhc module */ 180bcee7ed0SSrinivas Kandagatla struct wcd_mbhc *wcd_mbhc; 181bcee7ed0SSrinivas Kandagatla struct wcd_mbhc_config mbhc_cfg; 182bcee7ed0SSrinivas Kandagatla struct wcd_mbhc_intr intr_ids; 1838d78602aSSrinivas Kandagatla struct wcd_clsh_ctrl *clsh_info; 1848d78602aSSrinivas Kandagatla struct irq_domain *virq; 1858d78602aSSrinivas Kandagatla struct regmap_irq_chip *wcd_regmap_irq_chip; 1868d78602aSSrinivas Kandagatla struct regmap_irq_chip_data *irq_chip; 1878d78602aSSrinivas Kandagatla struct regulator_bulk_data supplies[WCD938X_MAX_SUPPLY]; 1888d78602aSSrinivas Kandagatla struct snd_soc_jack *jack; 1898d78602aSSrinivas Kandagatla unsigned long status_mask; 1908d78602aSSrinivas Kandagatla s32 micb_ref[WCD938X_MAX_MICBIAS]; 1918d78602aSSrinivas Kandagatla s32 pullup_ref[WCD938X_MAX_MICBIAS]; 1928d78602aSSrinivas Kandagatla u32 hph_mode; 1938d78602aSSrinivas Kandagatla u32 tx_mode[TX_ADC_MAX]; 1948d78602aSSrinivas Kandagatla int flyback_cur_det_disable; 1958d78602aSSrinivas Kandagatla int ear_rx_path; 1968d78602aSSrinivas Kandagatla int variant; 1978d78602aSSrinivas Kandagatla int reset_gpio; 198db0b4aedSSrinivasa Rao Mandadapu struct gpio_desc *us_euro_gpio; 1998d78602aSSrinivas Kandagatla u32 micb1_mv; 2008d78602aSSrinivas Kandagatla u32 micb2_mv; 2018d78602aSSrinivas Kandagatla u32 micb3_mv; 2028d78602aSSrinivas Kandagatla u32 micb4_mv; 2038d78602aSSrinivas Kandagatla int hphr_pdm_wd_int; 2048d78602aSSrinivas Kandagatla int hphl_pdm_wd_int; 2058d78602aSSrinivas Kandagatla int aux_pdm_wd_int; 2068d78602aSSrinivas Kandagatla bool comp1_enable; 2078d78602aSSrinivas Kandagatla bool comp2_enable; 2088d78602aSSrinivas Kandagatla bool ldoh; 2098d78602aSSrinivas Kandagatla bool bcs_dis; 2108d78602aSSrinivas Kandagatla }; 2118d78602aSSrinivas Kandagatla 212e8ba1e05SSrinivas Kandagatla static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); 213e8ba1e05SSrinivas Kandagatla static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000); 214e8ba1e05SSrinivas Kandagatla static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000); 215e8ba1e05SSrinivas Kandagatla 216bcee7ed0SSrinivas Kandagatla struct wcd938x_mbhc_zdet_param { 217bcee7ed0SSrinivas Kandagatla u16 ldo_ctl; 218bcee7ed0SSrinivas Kandagatla u16 noff; 219bcee7ed0SSrinivas Kandagatla u16 nshift; 220bcee7ed0SSrinivas Kandagatla u16 btn5; 221bcee7ed0SSrinivas Kandagatla u16 btn6; 222bcee7ed0SSrinivas Kandagatla u16 btn7; 223bcee7ed0SSrinivas Kandagatla }; 224bcee7ed0SSrinivas Kandagatla 225bcee7ed0SSrinivas Kandagatla static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 226bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80), 227bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40), 228bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20), 229bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30), 230bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08), 231bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F), 232bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04), 233bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10), 234bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08), 235bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01), 236bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06), 237bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80), 238bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F), 239bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03), 240bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03), 241bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08), 242bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10), 243bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20), 244bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80), 245bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40), 246bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10), 247bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07), 248bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70), 249bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF), 250bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0), 251bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF), 252bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40), 253bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80), 254bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0), 255bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10), 256bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02), 257bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01), 258bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70), 259bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20), 260bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40), 261bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10), 262bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01), 263bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01), 264bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80), 265bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20), 266bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08), 267bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40), 268bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80), 269bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF), 270bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F), 271bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10), 272bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04), 273bcee7ed0SSrinivas Kandagatla WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02), 274bcee7ed0SSrinivas Kandagatla }; 275bcee7ed0SSrinivas Kandagatla 2768d78602aSSrinivas Kandagatla static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = { 2778d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01), 2788d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02), 2798d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_DET, 0, 0x04), 2808d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, 0x08), 2818d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_SW_DET, 0, 0x10), 2828d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_OCP_INT, 0, 0x20), 2838d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_CNP_INT, 0, 0x40), 2848d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_OCP_INT, 0, 0x80), 2858d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_CNP_INT, 1, 0x01), 2868d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_EAR_CNP_INT, 1, 0x02), 2878d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_EAR_SCD_INT, 1, 0x04), 2888d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_AUX_CNP_INT, 1, 0x08), 2898d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_AUX_SCD_INT, 1, 0x10), 2908d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_PDM_WD_INT, 1, 0x20), 2918d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_PDM_WD_INT, 1, 0x40), 2928d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_AUX_PDM_WD_INT, 1, 0x80), 2938d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_LDORT_SCD_INT, 2, 0x01), 2948d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_MOISTURE_INT, 2, 0x02), 2958d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHL_SURGE_DET_INT, 2, 0x04), 2968d78602aSSrinivas Kandagatla REGMAP_IRQ_REG(WCD938X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08), 2978d78602aSSrinivas Kandagatla }; 2988d78602aSSrinivas Kandagatla 2998d78602aSSrinivas Kandagatla static struct regmap_irq_chip wcd938x_regmap_irq_chip = { 3008d78602aSSrinivas Kandagatla .name = "wcd938x", 3018d78602aSSrinivas Kandagatla .irqs = wcd938x_irqs, 3028d78602aSSrinivas Kandagatla .num_irqs = ARRAY_SIZE(wcd938x_irqs), 3038d78602aSSrinivas Kandagatla .num_regs = 3, 3048d78602aSSrinivas Kandagatla .status_base = WCD938X_DIGITAL_INTR_STATUS_0, 3058d78602aSSrinivas Kandagatla .mask_base = WCD938X_DIGITAL_INTR_MASK_0, 3068d78602aSSrinivas Kandagatla .ack_base = WCD938X_DIGITAL_INTR_CLEAR_0, 3078d78602aSSrinivas Kandagatla .use_ack = 1, 3088d78602aSSrinivas Kandagatla .runtime_pm = true, 3098d78602aSSrinivas Kandagatla .irq_drv_data = NULL, 3108d78602aSSrinivas Kandagatla }; 3118d78602aSSrinivas Kandagatla 312d5add08fSSrinivas Kandagatla static int wcd938x_get_clk_rate(int mode) 313d5add08fSSrinivas Kandagatla { 314d5add08fSSrinivas Kandagatla int rate; 315d5add08fSSrinivas Kandagatla 316d5add08fSSrinivas Kandagatla switch (mode) { 317d5add08fSSrinivas Kandagatla case ADC_MODE_ULP2: 318d5add08fSSrinivas Kandagatla rate = SWR_CLK_RATE_0P6MHZ; 319d5add08fSSrinivas Kandagatla break; 320d5add08fSSrinivas Kandagatla case ADC_MODE_ULP1: 321d5add08fSSrinivas Kandagatla rate = SWR_CLK_RATE_1P2MHZ; 322d5add08fSSrinivas Kandagatla break; 323d5add08fSSrinivas Kandagatla case ADC_MODE_LP: 324d5add08fSSrinivas Kandagatla rate = SWR_CLK_RATE_4P8MHZ; 325d5add08fSSrinivas Kandagatla break; 326d5add08fSSrinivas Kandagatla case ADC_MODE_NORMAL: 327d5add08fSSrinivas Kandagatla case ADC_MODE_LO_HIF: 328d5add08fSSrinivas Kandagatla case ADC_MODE_HIFI: 329d5add08fSSrinivas Kandagatla case ADC_MODE_INVALID: 330d5add08fSSrinivas Kandagatla default: 331d5add08fSSrinivas Kandagatla rate = SWR_CLK_RATE_9P6MHZ; 332d5add08fSSrinivas Kandagatla break; 333d5add08fSSrinivas Kandagatla } 334d5add08fSSrinivas Kandagatla 335d5add08fSSrinivas Kandagatla return rate; 336d5add08fSSrinivas Kandagatla } 337d5add08fSSrinivas Kandagatla 338d5add08fSSrinivas Kandagatla static int wcd938x_set_swr_clk_rate(struct snd_soc_component *component, int rate, int bank) 339d5add08fSSrinivas Kandagatla { 340d5add08fSSrinivas Kandagatla u8 mask = (bank ? 0xF0 : 0x0F); 341d5add08fSSrinivas Kandagatla u8 val = 0; 342d5add08fSSrinivas Kandagatla 343d5add08fSSrinivas Kandagatla switch (rate) { 344d5add08fSSrinivas Kandagatla case SWR_CLK_RATE_0P6MHZ: 345d5add08fSSrinivas Kandagatla val = (bank ? 0x60 : 0x06); 346d5add08fSSrinivas Kandagatla break; 347d5add08fSSrinivas Kandagatla case SWR_CLK_RATE_1P2MHZ: 348d5add08fSSrinivas Kandagatla val = (bank ? 0x50 : 0x05); 349d5add08fSSrinivas Kandagatla break; 350d5add08fSSrinivas Kandagatla case SWR_CLK_RATE_2P4MHZ: 351d5add08fSSrinivas Kandagatla val = (bank ? 0x30 : 0x03); 352d5add08fSSrinivas Kandagatla break; 353d5add08fSSrinivas Kandagatla case SWR_CLK_RATE_4P8MHZ: 354d5add08fSSrinivas Kandagatla val = (bank ? 0x10 : 0x01); 355d5add08fSSrinivas Kandagatla break; 356d5add08fSSrinivas Kandagatla case SWR_CLK_RATE_9P6MHZ: 357d5add08fSSrinivas Kandagatla default: 358d5add08fSSrinivas Kandagatla val = 0x00; 359d5add08fSSrinivas Kandagatla break; 360d5add08fSSrinivas Kandagatla } 361d5add08fSSrinivas Kandagatla snd_soc_component_update_bits(component, WCD938X_DIGITAL_SWR_TX_CLK_RATE, 362d5add08fSSrinivas Kandagatla mask, val); 363d5add08fSSrinivas Kandagatla 364d5add08fSSrinivas Kandagatla return 0; 365d5add08fSSrinivas Kandagatla } 366d5add08fSSrinivas Kandagatla 3678d78602aSSrinivas Kandagatla static int wcd938x_io_init(struct wcd938x_priv *wcd938x) 3688d78602aSSrinivas Kandagatla { 3698d78602aSSrinivas Kandagatla struct regmap *rm = wcd938x->regmap; 3708d78602aSSrinivas Kandagatla 3718d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x0E, 0x0E); 3728d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x80, 0x80); 3738d78602aSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 3748d78602aSSrinivas Kandagatla usleep_range(1000, 1010); 3758d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_SLEEP_CTL, 0x40, 0x40); 3768d78602aSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 3778d78602aSSrinivas Kandagatla usleep_range(1000, 1010); 3788d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_LDORXTX_CONFIG, 0x10, 0x00); 3798d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_BIAS_VBG_FINE_ADJ, 3808d78602aSSrinivas Kandagatla 0xF0, 0x80); 3818d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x80, 0x80); 3828d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x40); 3838d78602aSSrinivas Kandagatla /* 10 msec delay as per HW requirement */ 3848d78602aSSrinivas Kandagatla usleep_range(10000, 10010); 3858d78602aSSrinivas Kandagatla 3868d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_ANA_BIAS, 0x40, 0x00); 3878d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL, 3888d78602aSSrinivas Kandagatla 0xF0, 0x00); 3898d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW, 3908d78602aSSrinivas Kandagatla 0x1F, 0x15); 3918d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW, 3928d78602aSSrinivas Kandagatla 0x1F, 0x15); 3938d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_HPH_REFBUFF_UHQA_CTL, 3948d78602aSSrinivas Kandagatla 0xC0, 0x80); 3958d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_CDC_DMIC_CTL, 3968d78602aSSrinivas Kandagatla 0x02, 0x02); 3978d78602aSSrinivas Kandagatla 3988d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP, 3998d78602aSSrinivas Kandagatla 0xFF, 0x14); 4008d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP, 4018d78602aSSrinivas Kandagatla 0x1F, 0x08); 4028d78602aSSrinivas Kandagatla 4038d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0xFF, 0x55); 4048d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0xFF, 0x44); 4058d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0xFF, 0x11); 4068d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0xFF, 0x00); 4078d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0xFF, 0x00); 4088d78602aSSrinivas Kandagatla 4098d78602aSSrinivas Kandagatla /* Set Noise Filter Resistor value */ 4108d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_MICB1_TEST_CTL_1, 0xE0, 0xE0); 4118d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_MICB2_TEST_CTL_1, 0xE0, 0xE0); 4128d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_MICB3_TEST_CTL_1, 0xE0, 0xE0); 4138d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_MICB4_TEST_CTL_1, 0xE0, 0xE0); 4148d78602aSSrinivas Kandagatla 4158d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_TX_3_4_TEST_BLK_EN2, 0x01, 0x00); 4168d78602aSSrinivas Kandagatla regmap_update_bits(rm, WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); 4178d78602aSSrinivas Kandagatla 4188d78602aSSrinivas Kandagatla return 0; 4198d78602aSSrinivas Kandagatla 4208d78602aSSrinivas Kandagatla } 4218d78602aSSrinivas Kandagatla 422e8ba1e05SSrinivas Kandagatla static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, 423e8ba1e05SSrinivas Kandagatla struct sdw_port_config *port_config, 424e8ba1e05SSrinivas Kandagatla u8 enable) 425e8ba1e05SSrinivas Kandagatla { 426e8ba1e05SSrinivas Kandagatla u8 ch_mask, port_num; 427e8ba1e05SSrinivas Kandagatla 428e8ba1e05SSrinivas Kandagatla port_num = ch_info->port_num; 429e8ba1e05SSrinivas Kandagatla ch_mask = ch_info->ch_mask; 430e8ba1e05SSrinivas Kandagatla 431e8ba1e05SSrinivas Kandagatla port_config->num = port_num; 432e8ba1e05SSrinivas Kandagatla 433e8ba1e05SSrinivas Kandagatla if (enable) 434e8ba1e05SSrinivas Kandagatla port_config->ch_mask |= ch_mask; 435e8ba1e05SSrinivas Kandagatla else 436e8ba1e05SSrinivas Kandagatla port_config->ch_mask &= ~ch_mask; 437e8ba1e05SSrinivas Kandagatla 438e8ba1e05SSrinivas Kandagatla return 0; 439e8ba1e05SSrinivas Kandagatla } 440e8ba1e05SSrinivas Kandagatla 441c5c1546aSSrinivas Kandagatla static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 port_num, u8 ch_id, u8 enable) 442e8ba1e05SSrinivas Kandagatla { 443e8ba1e05SSrinivas Kandagatla return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id], 444c5c1546aSSrinivas Kandagatla &wcd->port_config[port_num - 1], 445e8ba1e05SSrinivas Kandagatla enable); 446e8ba1e05SSrinivas Kandagatla } 447e8ba1e05SSrinivas Kandagatla 4488da9db0cSSrinivas Kandagatla static int wcd938x_codec_enable_rxclk(struct snd_soc_dapm_widget *w, 4498da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 4508da9db0cSSrinivas Kandagatla int event) 4518da9db0cSSrinivas Kandagatla { 4528da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4538da9db0cSSrinivas Kandagatla 4548da9db0cSSrinivas Kandagatla switch (event) { 4558da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 4568da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 4578da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_CLK_EN_MASK, 1); 4588da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 4598da9db0cSSrinivas Kandagatla WCD938X_RX_BIAS_EN_MASK, 1); 4608da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX0_CTL, 4618da9db0cSSrinivas Kandagatla WCD938X_DEM_DITHER_ENABLE_MASK, 0); 4628da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX1_CTL, 4638da9db0cSSrinivas Kandagatla WCD938X_DEM_DITHER_ENABLE_MASK, 0); 4648da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_RX2_CTL, 4658da9db0cSSrinivas Kandagatla WCD938X_DEM_DITHER_ENABLE_MASK, 0); 4668da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 4678da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 1); 4688da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_AUX_AUXPA, 4698da9db0cSSrinivas Kandagatla WCD938X_AUXPA_CLK_EN_MASK, 1); 4708da9db0cSSrinivas Kandagatla break; 4718da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 4728da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 4738da9db0cSSrinivas Kandagatla WCD938X_VNEG_EN_MASK, 0); 4748da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 4758da9db0cSSrinivas Kandagatla WCD938X_VPOS_EN_MASK, 0); 4768da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 4778da9db0cSSrinivas Kandagatla WCD938X_RX_BIAS_EN_MASK, 0); 4788da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 4798da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_DIV2_CLK_EN_MASK, 0); 4808da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 4818da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_CLK_EN_MASK, 0); 4828da9db0cSSrinivas Kandagatla break; 4838da9db0cSSrinivas Kandagatla } 4848da9db0cSSrinivas Kandagatla return 0; 4858da9db0cSSrinivas Kandagatla } 4868da9db0cSSrinivas Kandagatla 4878da9db0cSSrinivas Kandagatla static int wcd938x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, 4888da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 4898da9db0cSSrinivas Kandagatla int event) 4908da9db0cSSrinivas Kandagatla { 4918da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 4928da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 4938da9db0cSSrinivas Kandagatla 4948da9db0cSSrinivas Kandagatla switch (event) { 4958da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 4968da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 4978da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 4988da9db0cSSrinivas Kandagatla WCD938X_RXD0_CLK_EN_MASK, 0x01); 4998da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5008da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 5018da9db0cSSrinivas Kandagatla WCD938X_HPHL_RX_EN_MASK, 1); 5028da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5038da9db0cSSrinivas Kandagatla WCD938X_HPH_RDAC_CLK_CTL1, 5048da9db0cSSrinivas Kandagatla WCD938X_CHOP_CLK_EN_MASK, 0); 5058da9db0cSSrinivas Kandagatla break; 5068da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 5078da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5088da9db0cSSrinivas Kandagatla WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L, 5098da9db0cSSrinivas Kandagatla WCD938X_HPH_RES_DIV_MASK, 0x02); 5108da9db0cSSrinivas Kandagatla if (wcd938x->comp1_enable) { 5118da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5128da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 5138da9db0cSSrinivas Kandagatla WCD938X_HPHL_COMP_EN_MASK, 1); 5148da9db0cSSrinivas Kandagatla /* 5msec compander delay as per HW requirement */ 5158da9db0cSSrinivas Kandagatla if (!wcd938x->comp2_enable || (snd_soc_component_read(component, 5168da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x01)) 5178da9db0cSSrinivas Kandagatla usleep_range(5000, 5010); 5188da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1, 5198da9db0cSSrinivas Kandagatla WCD938X_AUTOCHOP_TIMER_EN, 0); 5208da9db0cSSrinivas Kandagatla } else { 5218da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5228da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 5238da9db0cSSrinivas Kandagatla WCD938X_HPHL_COMP_EN_MASK, 0); 5248da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5258da9db0cSSrinivas Kandagatla WCD938X_HPH_L_EN, 5268da9db0cSSrinivas Kandagatla WCD938X_GAIN_SRC_SEL_MASK, 5278da9db0cSSrinivas Kandagatla WCD938X_GAIN_SRC_SEL_REGISTER); 5288da9db0cSSrinivas Kandagatla 5298da9db0cSSrinivas Kandagatla } 5308da9db0cSSrinivas Kandagatla break; 5318da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 5328da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5338da9db0cSSrinivas Kandagatla WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 5348da9db0cSSrinivas Kandagatla WCD938X_HPH_RES_DIV_MASK, 0x1); 5358da9db0cSSrinivas Kandagatla break; 5368da9db0cSSrinivas Kandagatla } 5378da9db0cSSrinivas Kandagatla 5388da9db0cSSrinivas Kandagatla return 0; 5398da9db0cSSrinivas Kandagatla } 5408da9db0cSSrinivas Kandagatla 5418da9db0cSSrinivas Kandagatla static int wcd938x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, 5428da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 5438da9db0cSSrinivas Kandagatla int event) 5448da9db0cSSrinivas Kandagatla { 5458da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 5468da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 5478da9db0cSSrinivas Kandagatla 5488da9db0cSSrinivas Kandagatla switch (event) { 5498da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 5508da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5518da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 5528da9db0cSSrinivas Kandagatla WCD938X_RXD1_CLK_EN_MASK, 1); 5538da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5548da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 5558da9db0cSSrinivas Kandagatla WCD938X_HPHR_RX_EN_MASK, 1); 5568da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5578da9db0cSSrinivas Kandagatla WCD938X_HPH_RDAC_CLK_CTL1, 5588da9db0cSSrinivas Kandagatla WCD938X_CHOP_CLK_EN_MASK, 0); 5598da9db0cSSrinivas Kandagatla break; 5608da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 5618da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5628da9db0cSSrinivas Kandagatla WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 5638da9db0cSSrinivas Kandagatla WCD938X_HPH_RES_DIV_MASK, 0x02); 5648da9db0cSSrinivas Kandagatla if (wcd938x->comp2_enable) { 5658da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5668da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 5678da9db0cSSrinivas Kandagatla WCD938X_HPHR_COMP_EN_MASK, 1); 5688da9db0cSSrinivas Kandagatla /* 5msec compander delay as per HW requirement */ 5698da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable || 5708da9db0cSSrinivas Kandagatla (snd_soc_component_read(component, 5718da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0) & 0x02)) 5728da9db0cSSrinivas Kandagatla usleep_range(5000, 5010); 5738da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1, 5748da9db0cSSrinivas Kandagatla WCD938X_AUTOCHOP_TIMER_EN, 0); 5758da9db0cSSrinivas Kandagatla } else { 5768da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5778da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 5788da9db0cSSrinivas Kandagatla WCD938X_HPHR_COMP_EN_MASK, 0); 5798da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5808da9db0cSSrinivas Kandagatla WCD938X_HPH_R_EN, 5818da9db0cSSrinivas Kandagatla WCD938X_GAIN_SRC_SEL_MASK, 5828da9db0cSSrinivas Kandagatla WCD938X_GAIN_SRC_SEL_REGISTER); 5838da9db0cSSrinivas Kandagatla } 5848da9db0cSSrinivas Kandagatla break; 5858da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 5868da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 5878da9db0cSSrinivas Kandagatla WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 5888da9db0cSSrinivas Kandagatla WCD938X_HPH_RES_DIV_MASK, 0x01); 5898da9db0cSSrinivas Kandagatla break; 5908da9db0cSSrinivas Kandagatla } 5918da9db0cSSrinivas Kandagatla 5928da9db0cSSrinivas Kandagatla return 0; 5938da9db0cSSrinivas Kandagatla } 5948da9db0cSSrinivas Kandagatla 5958da9db0cSSrinivas Kandagatla static int wcd938x_codec_ear_dac_event(struct snd_soc_dapm_widget *w, 5968da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 5978da9db0cSSrinivas Kandagatla int event) 5988da9db0cSSrinivas Kandagatla { 5998da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 6008da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 6018da9db0cSSrinivas Kandagatla 6028da9db0cSSrinivas Kandagatla switch (event) { 6038da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 6048da9db0cSSrinivas Kandagatla wcd938x->ear_rx_path = 6058da9db0cSSrinivas Kandagatla snd_soc_component_read( 6068da9db0cSSrinivas Kandagatla component, WCD938X_DIGITAL_CDC_EAR_PATH_CTL); 6078da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) { 6088da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6098da9db0cSSrinivas Kandagatla WCD938X_EAR_EAR_DAC_CON, 6108da9db0cSSrinivas Kandagatla WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 0); 6118da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6128da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 6138da9db0cSSrinivas Kandagatla WCD938X_AUX_EN_MASK, 1); 6148da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6158da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 6168da9db0cSSrinivas Kandagatla WCD938X_RXD2_CLK_EN_MASK, 1); 6178da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6188da9db0cSSrinivas Kandagatla WCD938X_ANA_EAR_COMPANDER_CTL, 6198da9db0cSSrinivas Kandagatla WCD938X_GAIN_OVRD_REG_MASK, 1); 6208da9db0cSSrinivas Kandagatla } else { 6218da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6228da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 6238da9db0cSSrinivas Kandagatla WCD938X_HPHL_RX_EN_MASK, 1); 6248da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6258da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 6268da9db0cSSrinivas Kandagatla WCD938X_RXD0_CLK_EN_MASK, 1); 6278da9db0cSSrinivas Kandagatla if (wcd938x->comp1_enable) 6288da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6298da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 6308da9db0cSSrinivas Kandagatla WCD938X_HPHL_COMP_EN_MASK, 1); 6318da9db0cSSrinivas Kandagatla } 6328da9db0cSSrinivas Kandagatla /* 5 msec delay as per HW requirement */ 6338da9db0cSSrinivas Kandagatla usleep_range(5000, 5010); 6348da9db0cSSrinivas Kandagatla if (wcd938x->flyback_cur_det_disable == 0) 6358da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_FLYBACK_EN, 6368da9db0cSSrinivas Kandagatla WCD938X_EN_CUR_DET_MASK, 0); 6378da9db0cSSrinivas Kandagatla wcd938x->flyback_cur_det_disable++; 6388da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, 6398da9db0cSSrinivas Kandagatla WCD_CLSH_EVENT_PRE_DAC, 6408da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_EAR, 6418da9db0cSSrinivas Kandagatla wcd938x->hph_mode); 6428da9db0cSSrinivas Kandagatla break; 6438da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 6448da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) { 6458da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6468da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 6478da9db0cSSrinivas Kandagatla WCD938X_AUX_EN_MASK, 0); 6488da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6498da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 6508da9db0cSSrinivas Kandagatla WCD938X_RXD2_CLK_EN_MASK, 0); 6518da9db0cSSrinivas Kandagatla } else { 6528da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6538da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 6548da9db0cSSrinivas Kandagatla WCD938X_HPHL_RX_EN_MASK, 0); 6558da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6568da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 6578da9db0cSSrinivas Kandagatla WCD938X_RXD0_CLK_EN_MASK, 0); 6588da9db0cSSrinivas Kandagatla if (wcd938x->comp1_enable) 6598da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6608da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_COMP_CTL_0, 6618da9db0cSSrinivas Kandagatla WCD938X_HPHL_COMP_EN_MASK, 0); 6628da9db0cSSrinivas Kandagatla } 6638da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL, 6648da9db0cSSrinivas Kandagatla WCD938X_GAIN_OVRD_REG_MASK, 0); 6658da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6668da9db0cSSrinivas Kandagatla WCD938X_EAR_EAR_DAC_CON, 6678da9db0cSSrinivas Kandagatla WCD938X_DAC_SAMPLE_EDGE_SEL_MASK, 1); 6688da9db0cSSrinivas Kandagatla break; 6698da9db0cSSrinivas Kandagatla } 6708da9db0cSSrinivas Kandagatla return 0; 6718da9db0cSSrinivas Kandagatla 6728da9db0cSSrinivas Kandagatla } 6738da9db0cSSrinivas Kandagatla 6748da9db0cSSrinivas Kandagatla static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w, 6758da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 6768da9db0cSSrinivas Kandagatla int event) 6778da9db0cSSrinivas Kandagatla { 6788da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 6798da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 6808da9db0cSSrinivas Kandagatla 6818da9db0cSSrinivas Kandagatla switch (event) { 6828da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 6838da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6848da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 6858da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 1); 6868da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6878da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 6888da9db0cSSrinivas Kandagatla WCD938X_RXD2_CLK_EN_MASK, 1); 6898da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 6908da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 6918da9db0cSSrinivas Kandagatla WCD938X_AUX_EN_MASK, 1); 6928da9db0cSSrinivas Kandagatla if (wcd938x->flyback_cur_det_disable == 0) 6938da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_FLYBACK_EN, 6948da9db0cSSrinivas Kandagatla WCD938X_EN_CUR_DET_MASK, 0); 6958da9db0cSSrinivas Kandagatla wcd938x->flyback_cur_det_disable++; 6968da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, 6978da9db0cSSrinivas Kandagatla WCD_CLSH_EVENT_PRE_DAC, 6988da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_AUX, 6998da9db0cSSrinivas Kandagatla wcd938x->hph_mode); 7008da9db0cSSrinivas Kandagatla break; 7018da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 7028da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 7038da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 7048da9db0cSSrinivas Kandagatla WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0); 7058da9db0cSSrinivas Kandagatla break; 7068da9db0cSSrinivas Kandagatla } 7074d0b79ecSkernel test robot return 0; 7088da9db0cSSrinivas Kandagatla 7098da9db0cSSrinivas Kandagatla } 7108da9db0cSSrinivas Kandagatla 7118da9db0cSSrinivas Kandagatla static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, 7128da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 7138da9db0cSSrinivas Kandagatla { 7148da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 7158da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 7168da9db0cSSrinivas Kandagatla int hph_mode = wcd938x->hph_mode; 7178da9db0cSSrinivas Kandagatla 7188da9db0cSSrinivas Kandagatla switch (event) { 7198da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 7208da9db0cSSrinivas Kandagatla if (wcd938x->ldoh) 7218da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_LDOH_MODE, 7228da9db0cSSrinivas Kandagatla WCD938X_LDOH_EN_MASK, 1); 7238da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC, 7248da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_HPHR, hph_mode); 7258da9db0cSSrinivas Kandagatla wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI); 7268da9db0cSSrinivas Kandagatla 7278da9db0cSSrinivas Kandagatla if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI || 7288da9db0cSSrinivas Kandagatla hph_mode == CLS_H_ULP) { 7298da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 7308da9db0cSSrinivas Kandagatla WCD938X_HPH_REFBUFF_LP_CTL, 7318da9db0cSSrinivas Kandagatla WCD938X_PREREF_FLIT_BYPASS_MASK, 1); 7328da9db0cSSrinivas Kandagatla } 7338da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 7348da9db0cSSrinivas Kandagatla WCD938X_HPHR_REF_EN_MASK, 1); 7358da9db0cSSrinivas Kandagatla wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode); 7368da9db0cSSrinivas Kandagatla /* 100 usec delay as per HW requirement */ 7378da9db0cSSrinivas Kandagatla usleep_range(100, 110); 7388da9db0cSSrinivas Kandagatla set_bit(HPH_PA_DELAY, &wcd938x->status_mask); 7398da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 7408da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_PDM_WD_CTL1, 7418da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0x3); 7428da9db0cSSrinivas Kandagatla break; 7438da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 7448da9db0cSSrinivas Kandagatla /* 7458da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 7468da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 7478da9db0cSSrinivas Kandagatla * 20ms delay is required. 7488da9db0cSSrinivas Kandagatla */ 7498da9db0cSSrinivas Kandagatla if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) { 7508da9db0cSSrinivas Kandagatla if (!wcd938x->comp2_enable) 7518da9db0cSSrinivas Kandagatla usleep_range(20000, 20100); 7528da9db0cSSrinivas Kandagatla else 7538da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 7548da9db0cSSrinivas Kandagatla 7558da9db0cSSrinivas Kandagatla if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI || 7568da9db0cSSrinivas Kandagatla hph_mode == CLS_H_ULP) 7578da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 7588da9db0cSSrinivas Kandagatla WCD938X_HPH_REFBUFF_LP_CTL, 7598da9db0cSSrinivas Kandagatla WCD938X_PREREF_FLIT_BYPASS_MASK, 0); 7608da9db0cSSrinivas Kandagatla clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); 7618da9db0cSSrinivas Kandagatla } 7628da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1, 7638da9db0cSSrinivas Kandagatla WCD938X_AUTOCHOP_TIMER_EN, 1); 7648da9db0cSSrinivas Kandagatla if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI || 7658da9db0cSSrinivas Kandagatla hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI) 7668da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 7678da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_MASK, 7688da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_CLASS_AB); 7698da9db0cSSrinivas Kandagatla enable_irq(wcd938x->hphr_pdm_wd_int); 7708da9db0cSSrinivas Kandagatla break; 7718da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMD: 7728da9db0cSSrinivas Kandagatla disable_irq_nosync(wcd938x->hphr_pdm_wd_int); 7738da9db0cSSrinivas Kandagatla /* 7748da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 7758da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 7768da9db0cSSrinivas Kandagatla * 20ms delay is required. 7778da9db0cSSrinivas Kandagatla */ 7788da9db0cSSrinivas Kandagatla if (!wcd938x->comp2_enable) 7798da9db0cSSrinivas Kandagatla usleep_range(20000, 20100); 7808da9db0cSSrinivas Kandagatla else 7818da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 7828da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 7838da9db0cSSrinivas Kandagatla WCD938X_HPHR_EN_MASK, 0); 784bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 785bcee7ed0SSrinivas Kandagatla WCD_EVENT_PRE_HPHR_PA_OFF); 7868da9db0cSSrinivas Kandagatla set_bit(HPH_PA_DELAY, &wcd938x->status_mask); 7878da9db0cSSrinivas Kandagatla break; 7888da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 7898da9db0cSSrinivas Kandagatla /* 7908da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 7918da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 7928da9db0cSSrinivas Kandagatla * 20ms delay is required. 7938da9db0cSSrinivas Kandagatla */ 7948da9db0cSSrinivas Kandagatla if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) { 7958da9db0cSSrinivas Kandagatla if (!wcd938x->comp2_enable) 7968da9db0cSSrinivas Kandagatla usleep_range(20000, 20100); 7978da9db0cSSrinivas Kandagatla else 7988da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 7998da9db0cSSrinivas Kandagatla clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); 8008da9db0cSSrinivas Kandagatla } 801bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 802bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_HPHR_PA_OFF); 8038da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 8048da9db0cSSrinivas Kandagatla WCD938X_HPHR_REF_EN_MASK, 0); 8058da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1, 8068da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0); 8078da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA, 8088da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_HPHR, hph_mode); 8098da9db0cSSrinivas Kandagatla if (wcd938x->ldoh) 8108da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_LDOH_MODE, 8118da9db0cSSrinivas Kandagatla WCD938X_LDOH_EN_MASK, 0); 8128da9db0cSSrinivas Kandagatla break; 8138da9db0cSSrinivas Kandagatla } 8148da9db0cSSrinivas Kandagatla 8158da9db0cSSrinivas Kandagatla return 0; 8168da9db0cSSrinivas Kandagatla } 8178da9db0cSSrinivas Kandagatla 8188da9db0cSSrinivas Kandagatla static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, 8198da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 8208da9db0cSSrinivas Kandagatla { 8218da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 8228da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 8238da9db0cSSrinivas Kandagatla int hph_mode = wcd938x->hph_mode; 8248da9db0cSSrinivas Kandagatla 8258da9db0cSSrinivas Kandagatla switch (event) { 8268da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 8278da9db0cSSrinivas Kandagatla if (wcd938x->ldoh) 8288da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_LDOH_MODE, 8298da9db0cSSrinivas Kandagatla WCD938X_LDOH_EN_MASK, 1); 8308da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_PRE_DAC, 8318da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_HPHL, hph_mode); 8328da9db0cSSrinivas Kandagatla wcd_clsh_set_hph_mode(wcd938x->clsh_info, CLS_H_HIFI); 8338da9db0cSSrinivas Kandagatla if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI || 8348da9db0cSSrinivas Kandagatla hph_mode == CLS_H_ULP) { 8358da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 8368da9db0cSSrinivas Kandagatla WCD938X_HPH_REFBUFF_LP_CTL, 8378da9db0cSSrinivas Kandagatla WCD938X_PREREF_FLIT_BYPASS_MASK, 1); 8388da9db0cSSrinivas Kandagatla } 8398da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 8408da9db0cSSrinivas Kandagatla WCD938X_HPHL_REF_EN_MASK, 1); 8418da9db0cSSrinivas Kandagatla wcd_clsh_set_hph_mode(wcd938x->clsh_info, hph_mode); 8428da9db0cSSrinivas Kandagatla /* 100 usec delay as per HW requirement */ 8438da9db0cSSrinivas Kandagatla usleep_range(100, 110); 8448da9db0cSSrinivas Kandagatla set_bit(HPH_PA_DELAY, &wcd938x->status_mask); 8458da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 8468da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_PDM_WD_CTL0, 8478da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0x3); 8488da9db0cSSrinivas Kandagatla break; 8498da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 8508da9db0cSSrinivas Kandagatla /* 8518da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 8528da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 8538da9db0cSSrinivas Kandagatla * 20ms delay is required. 8548da9db0cSSrinivas Kandagatla */ 8558da9db0cSSrinivas Kandagatla if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) { 8568da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable) 8578da9db0cSSrinivas Kandagatla usleep_range(20000, 20100); 8588da9db0cSSrinivas Kandagatla else 8598da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 8608da9db0cSSrinivas Kandagatla if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI || 8618da9db0cSSrinivas Kandagatla hph_mode == CLS_H_ULP) 8628da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 8638da9db0cSSrinivas Kandagatla WCD938X_HPH_REFBUFF_LP_CTL, 8648da9db0cSSrinivas Kandagatla WCD938X_PREREF_FLIT_BYPASS_MASK, 0); 8658da9db0cSSrinivas Kandagatla clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); 8668da9db0cSSrinivas Kandagatla } 8678da9db0cSSrinivas Kandagatla 8688da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_NEW_INT_HPH_TIMER1, 8698da9db0cSSrinivas Kandagatla WCD938X_AUTOCHOP_TIMER_EN, 1); 8708da9db0cSSrinivas Kandagatla if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI || 8718da9db0cSSrinivas Kandagatla hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI) 8728da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 8738da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_MASK, 8748da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_CLASS_AB); 8758da9db0cSSrinivas Kandagatla enable_irq(wcd938x->hphl_pdm_wd_int); 8768da9db0cSSrinivas Kandagatla break; 8778da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMD: 8788da9db0cSSrinivas Kandagatla disable_irq_nosync(wcd938x->hphl_pdm_wd_int); 8798da9db0cSSrinivas Kandagatla /* 8808da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 8818da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 8828da9db0cSSrinivas Kandagatla * 20ms delay is required. 8838da9db0cSSrinivas Kandagatla */ 8848da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable) 8858da9db0cSSrinivas Kandagatla usleep_range(20000, 20100); 8868da9db0cSSrinivas Kandagatla else 8878da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 8888da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 8898da9db0cSSrinivas Kandagatla WCD938X_HPHL_EN_MASK, 0); 890bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF); 8918da9db0cSSrinivas Kandagatla set_bit(HPH_PA_DELAY, &wcd938x->status_mask); 8928da9db0cSSrinivas Kandagatla break; 8938da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 8948da9db0cSSrinivas Kandagatla /* 8958da9db0cSSrinivas Kandagatla * 7ms sleep is required if compander is enabled as per 8968da9db0cSSrinivas Kandagatla * HW requirement. If compander is disabled, then 8978da9db0cSSrinivas Kandagatla * 20ms delay is required. 8988da9db0cSSrinivas Kandagatla */ 8998da9db0cSSrinivas Kandagatla if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) { 9008da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable) 9018da9db0cSSrinivas Kandagatla usleep_range(21000, 21100); 9028da9db0cSSrinivas Kandagatla else 9038da9db0cSSrinivas Kandagatla usleep_range(7000, 7100); 9048da9db0cSSrinivas Kandagatla clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); 9058da9db0cSSrinivas Kandagatla } 906bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 907bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_HPHL_PA_OFF); 9088da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_HPH, 9098da9db0cSSrinivas Kandagatla WCD938X_HPHL_REF_EN_MASK, 0); 9108da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0, 9118da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0); 9128da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA, 9138da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_HPHL, hph_mode); 9148da9db0cSSrinivas Kandagatla if (wcd938x->ldoh) 9158da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_LDOH_MODE, 9168da9db0cSSrinivas Kandagatla WCD938X_LDOH_EN_MASK, 0); 9178da9db0cSSrinivas Kandagatla break; 9188da9db0cSSrinivas Kandagatla } 9198da9db0cSSrinivas Kandagatla 9208da9db0cSSrinivas Kandagatla return 0; 9218da9db0cSSrinivas Kandagatla } 9228da9db0cSSrinivas Kandagatla 9238da9db0cSSrinivas Kandagatla static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w, 9248da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 9258da9db0cSSrinivas Kandagatla { 9268da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 9278da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 9288da9db0cSSrinivas Kandagatla int hph_mode = wcd938x->hph_mode; 9298da9db0cSSrinivas Kandagatla 9308da9db0cSSrinivas Kandagatla switch (event) { 9318da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 9328da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2, 9338da9db0cSSrinivas Kandagatla WCD938X_AUX_PDM_WD_EN_MASK, 1); 9348da9db0cSSrinivas Kandagatla break; 9358da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 9368da9db0cSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 9378da9db0cSSrinivas Kandagatla usleep_range(1000, 1010); 9388da9db0cSSrinivas Kandagatla if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI || 9398da9db0cSSrinivas Kandagatla hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI) 9408da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 9418da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_MASK, 9428da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_CLASS_AB); 9438da9db0cSSrinivas Kandagatla enable_irq(wcd938x->aux_pdm_wd_int); 9448da9db0cSSrinivas Kandagatla break; 9458da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMD: 9468da9db0cSSrinivas Kandagatla disable_irq_nosync(wcd938x->aux_pdm_wd_int); 9478da9db0cSSrinivas Kandagatla break; 9488da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 9498da9db0cSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 9508da9db0cSSrinivas Kandagatla usleep_range(1000, 1010); 9518da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2, 9528da9db0cSSrinivas Kandagatla WCD938X_AUX_PDM_WD_EN_MASK, 0); 9538da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, 9548da9db0cSSrinivas Kandagatla WCD_CLSH_EVENT_POST_PA, 9558da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_AUX, 9568da9db0cSSrinivas Kandagatla hph_mode); 9578da9db0cSSrinivas Kandagatla 9588da9db0cSSrinivas Kandagatla wcd938x->flyback_cur_det_disable--; 9598da9db0cSSrinivas Kandagatla if (wcd938x->flyback_cur_det_disable == 0) 9608da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_FLYBACK_EN, 9618da9db0cSSrinivas Kandagatla WCD938X_EN_CUR_DET_MASK, 1); 9628da9db0cSSrinivas Kandagatla break; 9638da9db0cSSrinivas Kandagatla } 9644d0b79ecSkernel test robot return 0; 9658da9db0cSSrinivas Kandagatla } 9668da9db0cSSrinivas Kandagatla 9678da9db0cSSrinivas Kandagatla static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, 9688da9db0cSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 9698da9db0cSSrinivas Kandagatla { 9708da9db0cSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 9718da9db0cSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 9728da9db0cSSrinivas Kandagatla int hph_mode = wcd938x->hph_mode; 9738da9db0cSSrinivas Kandagatla 9748da9db0cSSrinivas Kandagatla switch (event) { 9758da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 9768da9db0cSSrinivas Kandagatla /* 9778da9db0cSSrinivas Kandagatla * Enable watchdog interrupt for HPHL or AUX 9788da9db0cSSrinivas Kandagatla * depending on mux value 9798da9db0cSSrinivas Kandagatla */ 9808da9db0cSSrinivas Kandagatla wcd938x->ear_rx_path = snd_soc_component_read(component, 9818da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_CDC_EAR_PATH_CTL); 9828da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) 9838da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2, 9848da9db0cSSrinivas Kandagatla WCD938X_AUX_PDM_WD_EN_MASK, 1); 9858da9db0cSSrinivas Kandagatla else 9868da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 9878da9db0cSSrinivas Kandagatla WCD938X_DIGITAL_PDM_WD_CTL0, 9888da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0x3); 9898da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable) 9908da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, 9918da9db0cSSrinivas Kandagatla WCD938X_ANA_EAR_COMPANDER_CTL, 9928da9db0cSSrinivas Kandagatla WCD938X_GAIN_OVRD_REG_MASK, 1); 9938da9db0cSSrinivas Kandagatla 9948da9db0cSSrinivas Kandagatla break; 9958da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 9968da9db0cSSrinivas Kandagatla /* 6 msec delay as per HW requirement */ 9978da9db0cSSrinivas Kandagatla usleep_range(6000, 6010); 9988da9db0cSSrinivas Kandagatla if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI || 9998da9db0cSSrinivas Kandagatla hph_mode == CLS_AB_LP || hph_mode == CLS_AB_LOHIFI) 10008da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_RX_SUPPLIES, 10018da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_MASK, 10028da9db0cSSrinivas Kandagatla WCD938X_REGULATOR_MODE_CLASS_AB); 10038da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) 10048da9db0cSSrinivas Kandagatla enable_irq(wcd938x->aux_pdm_wd_int); 10058da9db0cSSrinivas Kandagatla else 10068da9db0cSSrinivas Kandagatla enable_irq(wcd938x->hphl_pdm_wd_int); 10078da9db0cSSrinivas Kandagatla break; 10088da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMD: 10098da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) 10108da9db0cSSrinivas Kandagatla disable_irq_nosync(wcd938x->aux_pdm_wd_int); 10118da9db0cSSrinivas Kandagatla else 10128da9db0cSSrinivas Kandagatla disable_irq_nosync(wcd938x->hphl_pdm_wd_int); 10138da9db0cSSrinivas Kandagatla break; 10148da9db0cSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 10158da9db0cSSrinivas Kandagatla if (!wcd938x->comp1_enable) 10168da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL, 10178da9db0cSSrinivas Kandagatla WCD938X_GAIN_OVRD_REG_MASK, 0); 10188da9db0cSSrinivas Kandagatla /* 7 msec delay as per HW requirement */ 10198da9db0cSSrinivas Kandagatla usleep_range(7000, 7010); 10208da9db0cSSrinivas Kandagatla if (wcd938x->ear_rx_path & EAR_RX_PATH_AUX) 10218da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL2, 10228da9db0cSSrinivas Kandagatla WCD938X_AUX_PDM_WD_EN_MASK, 0); 10238da9db0cSSrinivas Kandagatla else 10248da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0, 10258da9db0cSSrinivas Kandagatla WCD938X_PDM_WD_EN_MASK, 0); 10268da9db0cSSrinivas Kandagatla 10278da9db0cSSrinivas Kandagatla wcd_clsh_ctrl_set_state(wcd938x->clsh_info, WCD_CLSH_EVENT_POST_PA, 10288da9db0cSSrinivas Kandagatla WCD_CLSH_STATE_EAR, hph_mode); 10298da9db0cSSrinivas Kandagatla 10308da9db0cSSrinivas Kandagatla wcd938x->flyback_cur_det_disable--; 10318da9db0cSSrinivas Kandagatla if (wcd938x->flyback_cur_det_disable == 0) 10328da9db0cSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_FLYBACK_EN, 10338da9db0cSSrinivas Kandagatla WCD938X_EN_CUR_DET_MASK, 1); 10348da9db0cSSrinivas Kandagatla break; 10358da9db0cSSrinivas Kandagatla } 10368da9db0cSSrinivas Kandagatla 10378da9db0cSSrinivas Kandagatla return 0; 10388da9db0cSSrinivas Kandagatla } 10398da9db0cSSrinivas Kandagatla 1040d5add08fSSrinivas Kandagatla static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w, 1041d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 1042d5add08fSSrinivas Kandagatla int event) 1043d5add08fSSrinivas Kandagatla { 1044d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1045d5add08fSSrinivas Kandagatla u16 dmic_clk_reg, dmic_clk_en_reg; 1046d5add08fSSrinivas Kandagatla u8 dmic_sel_mask, dmic_clk_mask; 1047d5add08fSSrinivas Kandagatla 1048d5add08fSSrinivas Kandagatla switch (w->shift) { 1049d5add08fSSrinivas Kandagatla case 0: 1050d5add08fSSrinivas Kandagatla case 1: 1051d5add08fSSrinivas Kandagatla dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2; 1052d5add08fSSrinivas Kandagatla dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL; 1053d5add08fSSrinivas Kandagatla dmic_clk_mask = WCD938X_DMIC1_RATE_MASK; 1054d5add08fSSrinivas Kandagatla dmic_sel_mask = WCD938X_AMIC1_IN_SEL_MASK; 1055d5add08fSSrinivas Kandagatla break; 1056d5add08fSSrinivas Kandagatla case 2: 1057d5add08fSSrinivas Kandagatla case 3: 1058d5add08fSSrinivas Kandagatla dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2; 1059d5add08fSSrinivas Kandagatla dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL; 1060d5add08fSSrinivas Kandagatla dmic_clk_mask = WCD938X_DMIC2_RATE_MASK; 1061d5add08fSSrinivas Kandagatla dmic_sel_mask = WCD938X_AMIC3_IN_SEL_MASK; 1062d5add08fSSrinivas Kandagatla break; 1063d5add08fSSrinivas Kandagatla case 4: 1064d5add08fSSrinivas Kandagatla case 5: 1065d5add08fSSrinivas Kandagatla dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4; 1066d5add08fSSrinivas Kandagatla dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC3_CTL; 1067d5add08fSSrinivas Kandagatla dmic_clk_mask = WCD938X_DMIC3_RATE_MASK; 1068d5add08fSSrinivas Kandagatla dmic_sel_mask = WCD938X_AMIC4_IN_SEL_MASK; 1069d5add08fSSrinivas Kandagatla break; 1070d5add08fSSrinivas Kandagatla case 6: 1071d5add08fSSrinivas Kandagatla case 7: 1072d5add08fSSrinivas Kandagatla dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4; 1073d5add08fSSrinivas Kandagatla dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC4_CTL; 1074d5add08fSSrinivas Kandagatla dmic_clk_mask = WCD938X_DMIC4_RATE_MASK; 1075d5add08fSSrinivas Kandagatla dmic_sel_mask = WCD938X_AMIC5_IN_SEL_MASK; 1076d5add08fSSrinivas Kandagatla break; 1077d5add08fSSrinivas Kandagatla default: 1078d5add08fSSrinivas Kandagatla dev_err(component->dev, "%s: Invalid DMIC Selection\n", 1079d5add08fSSrinivas Kandagatla __func__); 1080d5add08fSSrinivas Kandagatla return -EINVAL; 1081d5add08fSSrinivas Kandagatla } 1082d5add08fSSrinivas Kandagatla 1083d5add08fSSrinivas Kandagatla switch (event) { 1084d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1085d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1086d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_AMIC_CTL, 1087d5add08fSSrinivas Kandagatla dmic_sel_mask, 1088d5add08fSSrinivas Kandagatla WCD938X_AMIC1_IN_SEL_DMIC); 1089d5add08fSSrinivas Kandagatla /* 250us sleep as per HW requirement */ 1090d5add08fSSrinivas Kandagatla usleep_range(250, 260); 1091d5add08fSSrinivas Kandagatla /* Setting DMIC clock rate to 2.4MHz */ 1092d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, dmic_clk_reg, 1093d5add08fSSrinivas Kandagatla dmic_clk_mask, 1094d5add08fSSrinivas Kandagatla WCD938X_DMIC4_RATE_2P4MHZ); 1095d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, dmic_clk_en_reg, 1096d5add08fSSrinivas Kandagatla WCD938X_DMIC_CLK_EN_MASK, 1); 1097d5add08fSSrinivas Kandagatla /* enable clock scaling */ 1098d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_DMIC_CTL, 1099d5add08fSSrinivas Kandagatla WCD938X_DMIC_CLK_SCALING_EN_MASK, 0x3); 1100d5add08fSSrinivas Kandagatla break; 1101d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1102d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1103d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_AMIC_CTL, 1104d5add08fSSrinivas Kandagatla dmic_sel_mask, WCD938X_AMIC1_IN_SEL_AMIC); 1105d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, dmic_clk_en_reg, 1106d5add08fSSrinivas Kandagatla WCD938X_DMIC_CLK_EN_MASK, 0); 1107d5add08fSSrinivas Kandagatla break; 1108d5add08fSSrinivas Kandagatla } 1109d5add08fSSrinivas Kandagatla return 0; 1110d5add08fSSrinivas Kandagatla } 1111d5add08fSSrinivas Kandagatla 1112d5add08fSSrinivas Kandagatla static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, 1113d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 1114d5add08fSSrinivas Kandagatla { 1115d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1116d5add08fSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1117d5add08fSSrinivas Kandagatla int bank; 1118d5add08fSSrinivas Kandagatla int rate; 1119d5add08fSSrinivas Kandagatla 1120d5add08fSSrinivas Kandagatla bank = (wcd938x_swr_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev)) ? 0 : 1; 1121d5add08fSSrinivas Kandagatla bank = bank ? 0 : 1; 1122d5add08fSSrinivas Kandagatla 1123d5add08fSSrinivas Kandagatla switch (event) { 1124d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1125d5add08fSSrinivas Kandagatla if (strnstr(w->name, "ADC", sizeof("ADC"))) { 1126d5add08fSSrinivas Kandagatla int i = 0, mode = 0; 1127d5add08fSSrinivas Kandagatla 1128d5add08fSSrinivas Kandagatla if (test_bit(WCD_ADC1, &wcd938x->status_mask)) 1129d5add08fSSrinivas Kandagatla mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]]; 1130d5add08fSSrinivas Kandagatla if (test_bit(WCD_ADC2, &wcd938x->status_mask)) 1131d5add08fSSrinivas Kandagatla mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]]; 1132d5add08fSSrinivas Kandagatla if (test_bit(WCD_ADC3, &wcd938x->status_mask)) 1133d5add08fSSrinivas Kandagatla mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]]; 1134d5add08fSSrinivas Kandagatla if (test_bit(WCD_ADC4, &wcd938x->status_mask)) 1135d5add08fSSrinivas Kandagatla mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]]; 1136d5add08fSSrinivas Kandagatla 1137d5add08fSSrinivas Kandagatla if (mode != 0) { 1138d5add08fSSrinivas Kandagatla for (i = 0; i < ADC_MODE_ULP2; i++) { 1139d5add08fSSrinivas Kandagatla if (mode & (1 << i)) { 1140d5add08fSSrinivas Kandagatla i++; 1141d5add08fSSrinivas Kandagatla break; 1142d5add08fSSrinivas Kandagatla } 1143d5add08fSSrinivas Kandagatla } 1144d5add08fSSrinivas Kandagatla } 1145d5add08fSSrinivas Kandagatla rate = wcd938x_get_clk_rate(i); 1146d5add08fSSrinivas Kandagatla wcd938x_set_swr_clk_rate(component, rate, bank); 1147d5add08fSSrinivas Kandagatla /* Copy clk settings to active bank */ 1148d5add08fSSrinivas Kandagatla wcd938x_set_swr_clk_rate(component, rate, !bank); 1149d245fff1SSrinivas Kandagatla } 1150d5add08fSSrinivas Kandagatla break; 1151d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1152d5add08fSSrinivas Kandagatla if (strnstr(w->name, "ADC", sizeof("ADC"))) { 1153d5add08fSSrinivas Kandagatla rate = wcd938x_get_clk_rate(ADC_MODE_INVALID); 1154d5add08fSSrinivas Kandagatla wcd938x_set_swr_clk_rate(component, rate, !bank); 1155d5add08fSSrinivas Kandagatla wcd938x_set_swr_clk_rate(component, rate, bank); 1156d5add08fSSrinivas Kandagatla } 1157d5add08fSSrinivas Kandagatla break; 1158d5add08fSSrinivas Kandagatla } 1159d5add08fSSrinivas Kandagatla 1160d5add08fSSrinivas Kandagatla return 0; 1161d5add08fSSrinivas Kandagatla } 1162d5add08fSSrinivas Kandagatla 1163d5add08fSSrinivas Kandagatla static int wcd938x_get_adc_mode(int val) 1164d5add08fSSrinivas Kandagatla { 1165d5add08fSSrinivas Kandagatla int ret = 0; 1166d5add08fSSrinivas Kandagatla 1167d5add08fSSrinivas Kandagatla switch (val) { 1168d5add08fSSrinivas Kandagatla case ADC_MODE_INVALID: 1169d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_NORMAL; 1170d5add08fSSrinivas Kandagatla break; 1171d5add08fSSrinivas Kandagatla case ADC_MODE_HIFI: 1172d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_HIFI; 1173d5add08fSSrinivas Kandagatla break; 1174d5add08fSSrinivas Kandagatla case ADC_MODE_LO_HIF: 1175d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_LO_HIF; 1176d5add08fSSrinivas Kandagatla break; 1177d5add08fSSrinivas Kandagatla case ADC_MODE_NORMAL: 1178d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_NORMAL; 1179d5add08fSSrinivas Kandagatla break; 1180d5add08fSSrinivas Kandagatla case ADC_MODE_LP: 1181d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_LP; 1182d5add08fSSrinivas Kandagatla break; 1183d5add08fSSrinivas Kandagatla case ADC_MODE_ULP1: 1184d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_ULP1; 1185d5add08fSSrinivas Kandagatla break; 1186d5add08fSSrinivas Kandagatla case ADC_MODE_ULP2: 1187d5add08fSSrinivas Kandagatla ret = ADC_MODE_VAL_ULP2; 1188d5add08fSSrinivas Kandagatla break; 1189d5add08fSSrinivas Kandagatla default: 1190d5add08fSSrinivas Kandagatla ret = -EINVAL; 1191d5add08fSSrinivas Kandagatla break; 1192d5add08fSSrinivas Kandagatla } 1193d5add08fSSrinivas Kandagatla return ret; 1194d5add08fSSrinivas Kandagatla } 1195d5add08fSSrinivas Kandagatla 1196d5add08fSSrinivas Kandagatla static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w, 1197d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 1198d5add08fSSrinivas Kandagatla { 1199d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1200d5add08fSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1201d5add08fSSrinivas Kandagatla 1202d5add08fSSrinivas Kandagatla switch (event) { 1203d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1204d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1205d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 1206d5add08fSSrinivas Kandagatla WCD938X_ANA_TX_CLK_EN_MASK, 1); 1207d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1208d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 1209d5add08fSSrinivas Kandagatla WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1); 1210d5add08fSSrinivas Kandagatla set_bit(w->shift, &wcd938x->status_mask); 1211d5add08fSSrinivas Kandagatla break; 1212d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1213d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 1214d5add08fSSrinivas Kandagatla WCD938X_ANA_TX_CLK_EN_MASK, 0); 1215d5add08fSSrinivas Kandagatla clear_bit(w->shift, &wcd938x->status_mask); 1216d5add08fSSrinivas Kandagatla break; 1217d5add08fSSrinivas Kandagatla } 1218d5add08fSSrinivas Kandagatla 1219d5add08fSSrinivas Kandagatla return 0; 1220d5add08fSSrinivas Kandagatla } 1221d5add08fSSrinivas Kandagatla 1222d5add08fSSrinivas Kandagatla static void wcd938x_tx_channel_config(struct snd_soc_component *component, 1223d5add08fSSrinivas Kandagatla int channel, int mode) 1224d5add08fSSrinivas Kandagatla { 1225d5add08fSSrinivas Kandagatla int reg, mask; 1226d5add08fSSrinivas Kandagatla 1227d5add08fSSrinivas Kandagatla switch (channel) { 1228d5add08fSSrinivas Kandagatla case 0: 1229d5add08fSSrinivas Kandagatla reg = WCD938X_ANA_TX_CH2; 1230d5add08fSSrinivas Kandagatla mask = WCD938X_HPF1_INIT_MASK; 1231d5add08fSSrinivas Kandagatla break; 1232d5add08fSSrinivas Kandagatla case 1: 1233d5add08fSSrinivas Kandagatla reg = WCD938X_ANA_TX_CH2; 1234d5add08fSSrinivas Kandagatla mask = WCD938X_HPF2_INIT_MASK; 1235d5add08fSSrinivas Kandagatla break; 1236d5add08fSSrinivas Kandagatla case 2: 1237d5add08fSSrinivas Kandagatla reg = WCD938X_ANA_TX_CH4; 1238d5add08fSSrinivas Kandagatla mask = WCD938X_HPF3_INIT_MASK; 1239d5add08fSSrinivas Kandagatla break; 1240d5add08fSSrinivas Kandagatla case 3: 1241d5add08fSSrinivas Kandagatla reg = WCD938X_ANA_TX_CH4; 1242d5add08fSSrinivas Kandagatla mask = WCD938X_HPF4_INIT_MASK; 1243d5add08fSSrinivas Kandagatla break; 1244d245fff1SSrinivas Kandagatla default: 1245d245fff1SSrinivas Kandagatla return; 1246d5add08fSSrinivas Kandagatla } 1247d5add08fSSrinivas Kandagatla 1248d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, reg, mask, mode); 1249d5add08fSSrinivas Kandagatla } 1250d5add08fSSrinivas Kandagatla 1251d5add08fSSrinivas Kandagatla static int wcd938x_adc_enable_req(struct snd_soc_dapm_widget *w, 1252d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, int event) 1253d5add08fSSrinivas Kandagatla { 1254d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1255d5add08fSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1256d5add08fSSrinivas Kandagatla int mode; 1257d5add08fSSrinivas Kandagatla 1258d5add08fSSrinivas Kandagatla switch (event) { 1259d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1260d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1261d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_REQ_CTL, 1262d5add08fSSrinivas Kandagatla WCD938X_FS_RATE_4P8_MASK, 1); 1263d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1264d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_REQ_CTL, 1265d5add08fSSrinivas Kandagatla WCD938X_NO_NOTCH_MASK, 0); 1266d5add08fSSrinivas Kandagatla wcd938x_tx_channel_config(component, w->shift, 1); 1267d5add08fSSrinivas Kandagatla mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]); 1268d5add08fSSrinivas Kandagatla if (mode < 0) { 1269d5add08fSSrinivas Kandagatla dev_info(component->dev, "Invalid ADC mode\n"); 1270d5add08fSSrinivas Kandagatla return -EINVAL; 1271d5add08fSSrinivas Kandagatla } 1272d5add08fSSrinivas Kandagatla switch (w->shift) { 1273d5add08fSSrinivas Kandagatla case 0: 1274d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1275d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 1276d5add08fSSrinivas Kandagatla WCD938X_TXD0_MODE_MASK, mode); 1277d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1278d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1279d5add08fSSrinivas Kandagatla WCD938X_TXD0_CLK_EN_MASK, 1); 1280d5add08fSSrinivas Kandagatla break; 1281d5add08fSSrinivas Kandagatla case 1: 1282d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1283d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 1284d5add08fSSrinivas Kandagatla WCD938X_TXD1_MODE_MASK, mode); 1285d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1286d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1287d5add08fSSrinivas Kandagatla WCD938X_TXD1_CLK_EN_MASK, 1); 1288d5add08fSSrinivas Kandagatla break; 1289d5add08fSSrinivas Kandagatla case 2: 1290d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1291d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 1292d5add08fSSrinivas Kandagatla WCD938X_TXD2_MODE_MASK, mode); 1293d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1294d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1295d5add08fSSrinivas Kandagatla WCD938X_TXD2_CLK_EN_MASK, 1); 1296d5add08fSSrinivas Kandagatla break; 1297d5add08fSSrinivas Kandagatla case 3: 1298d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1299d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 1300d5add08fSSrinivas Kandagatla WCD938X_TXD3_MODE_MASK, mode); 1301d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1302d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1303d5add08fSSrinivas Kandagatla WCD938X_TXD3_CLK_EN_MASK, 1); 1304d5add08fSSrinivas Kandagatla break; 1305d5add08fSSrinivas Kandagatla default: 1306d5add08fSSrinivas Kandagatla break; 1307d5add08fSSrinivas Kandagatla } 1308d5add08fSSrinivas Kandagatla 1309d5add08fSSrinivas Kandagatla wcd938x_tx_channel_config(component, w->shift, 0); 1310d5add08fSSrinivas Kandagatla break; 1311d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1312d5add08fSSrinivas Kandagatla switch (w->shift) { 1313d5add08fSSrinivas Kandagatla case 0: 1314d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1315d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 1316d5add08fSSrinivas Kandagatla WCD938X_TXD0_MODE_MASK, 0); 1317d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1318d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1319d5add08fSSrinivas Kandagatla WCD938X_TXD0_CLK_EN_MASK, 0); 1320d5add08fSSrinivas Kandagatla break; 1321d5add08fSSrinivas Kandagatla case 1: 1322d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1323d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 1324d5add08fSSrinivas Kandagatla WCD938X_TXD1_MODE_MASK, 0); 1325d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1326d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1327d5add08fSSrinivas Kandagatla WCD938X_TXD1_CLK_EN_MASK, 0); 1328d5add08fSSrinivas Kandagatla break; 1329d5add08fSSrinivas Kandagatla case 2: 1330d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1331d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 1332d5add08fSSrinivas Kandagatla WCD938X_TXD2_MODE_MASK, 0); 1333d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1334d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1335d5add08fSSrinivas Kandagatla WCD938X_TXD2_CLK_EN_MASK, 0); 1336d5add08fSSrinivas Kandagatla break; 1337d5add08fSSrinivas Kandagatla case 3: 1338d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1339d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 1340d5add08fSSrinivas Kandagatla WCD938X_TXD3_MODE_MASK, 0); 1341d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1342d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1343d5add08fSSrinivas Kandagatla WCD938X_TXD3_CLK_EN_MASK, 0); 1344d5add08fSSrinivas Kandagatla break; 1345d5add08fSSrinivas Kandagatla default: 1346d5add08fSSrinivas Kandagatla break; 1347d5add08fSSrinivas Kandagatla } 1348d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1349d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 1350d5add08fSSrinivas Kandagatla WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 0); 1351d5add08fSSrinivas Kandagatla break; 1352d5add08fSSrinivas Kandagatla } 1353d5add08fSSrinivas Kandagatla 1354d5add08fSSrinivas Kandagatla return 0; 1355d5add08fSSrinivas Kandagatla } 1356d5add08fSSrinivas Kandagatla 1357d5add08fSSrinivas Kandagatla static int wcd938x_micbias_control(struct snd_soc_component *component, 1358d5add08fSSrinivas Kandagatla int micb_num, int req, bool is_dapm) 1359d5add08fSSrinivas Kandagatla { 1360d5add08fSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1361d5add08fSSrinivas Kandagatla int micb_index = micb_num - 1; 1362d5add08fSSrinivas Kandagatla u16 micb_reg; 1363d5add08fSSrinivas Kandagatla 1364d5add08fSSrinivas Kandagatla switch (micb_num) { 1365d5add08fSSrinivas Kandagatla case MIC_BIAS_1: 1366d5add08fSSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB1; 1367d5add08fSSrinivas Kandagatla break; 1368d5add08fSSrinivas Kandagatla case MIC_BIAS_2: 1369d5add08fSSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB2; 1370d5add08fSSrinivas Kandagatla break; 1371d5add08fSSrinivas Kandagatla case MIC_BIAS_3: 1372d5add08fSSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB3; 1373d5add08fSSrinivas Kandagatla break; 1374d5add08fSSrinivas Kandagatla case MIC_BIAS_4: 1375d5add08fSSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB4; 1376d5add08fSSrinivas Kandagatla break; 1377d5add08fSSrinivas Kandagatla default: 1378d5add08fSSrinivas Kandagatla dev_err(component->dev, "%s: Invalid micbias number: %d\n", 1379d5add08fSSrinivas Kandagatla __func__, micb_num); 1380d5add08fSSrinivas Kandagatla return -EINVAL; 1381d5add08fSSrinivas Kandagatla } 1382d5add08fSSrinivas Kandagatla 1383d5add08fSSrinivas Kandagatla switch (req) { 1384d5add08fSSrinivas Kandagatla case MICB_PULLUP_ENABLE: 1385d5add08fSSrinivas Kandagatla wcd938x->pullup_ref[micb_index]++; 1386d5add08fSSrinivas Kandagatla if ((wcd938x->pullup_ref[micb_index] == 1) && 1387d5add08fSSrinivas Kandagatla (wcd938x->micb_ref[micb_index] == 0)) 1388d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 1389d5add08fSSrinivas Kandagatla WCD938X_MICB_EN_MASK, 1390d5add08fSSrinivas Kandagatla WCD938X_MICB_PULL_UP); 1391d5add08fSSrinivas Kandagatla break; 1392d5add08fSSrinivas Kandagatla case MICB_PULLUP_DISABLE: 1393d5add08fSSrinivas Kandagatla if (wcd938x->pullup_ref[micb_index] > 0) 1394d5add08fSSrinivas Kandagatla wcd938x->pullup_ref[micb_index]--; 1395d5add08fSSrinivas Kandagatla 1396d5add08fSSrinivas Kandagatla if ((wcd938x->pullup_ref[micb_index] == 0) && 1397d5add08fSSrinivas Kandagatla (wcd938x->micb_ref[micb_index] == 0)) 1398d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 1399d5add08fSSrinivas Kandagatla WCD938X_MICB_EN_MASK, 0); 1400d5add08fSSrinivas Kandagatla break; 1401d5add08fSSrinivas Kandagatla case MICB_ENABLE: 1402d5add08fSSrinivas Kandagatla wcd938x->micb_ref[micb_index]++; 1403d5add08fSSrinivas Kandagatla if (wcd938x->micb_ref[micb_index] == 1) { 1404d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1405d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 1406d5add08fSSrinivas Kandagatla WCD938X_TX_CLK_EN_MASK, 0xF); 1407d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1408d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 1409d5add08fSSrinivas Kandagatla WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1); 1410d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, 1411d5add08fSSrinivas Kandagatla WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL, 1412d5add08fSSrinivas Kandagatla WCD938X_TX_SC_CLK_EN_MASK, 1); 1413d5add08fSSrinivas Kandagatla 1414d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 1415d5add08fSSrinivas Kandagatla WCD938X_MICB_EN_MASK, 1416d5add08fSSrinivas Kandagatla WCD938X_MICB_ENABLE); 1417bcee7ed0SSrinivas Kandagatla if (micb_num == MIC_BIAS_2) 1418bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 1419bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_MICBIAS_2_ON); 1420d5add08fSSrinivas Kandagatla } 1421bcee7ed0SSrinivas Kandagatla if (micb_num == MIC_BIAS_2 && is_dapm) 1422bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 1423bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_DAPM_MICBIAS_2_ON); 1424bcee7ed0SSrinivas Kandagatla 1425d5add08fSSrinivas Kandagatla 1426d5add08fSSrinivas Kandagatla break; 1427d5add08fSSrinivas Kandagatla case MICB_DISABLE: 1428d5add08fSSrinivas Kandagatla if (wcd938x->micb_ref[micb_index] > 0) 1429d5add08fSSrinivas Kandagatla wcd938x->micb_ref[micb_index]--; 1430d5add08fSSrinivas Kandagatla 1431d5add08fSSrinivas Kandagatla if ((wcd938x->micb_ref[micb_index] == 0) && 1432d5add08fSSrinivas Kandagatla (wcd938x->pullup_ref[micb_index] > 0)) 1433d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 1434d5add08fSSrinivas Kandagatla WCD938X_MICB_EN_MASK, 1435d5add08fSSrinivas Kandagatla WCD938X_MICB_PULL_UP); 1436d5add08fSSrinivas Kandagatla else if ((wcd938x->micb_ref[micb_index] == 0) && 1437d5add08fSSrinivas Kandagatla (wcd938x->pullup_ref[micb_index] == 0)) { 1438bcee7ed0SSrinivas Kandagatla if (micb_num == MIC_BIAS_2) 1439bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 1440bcee7ed0SSrinivas Kandagatla WCD_EVENT_PRE_MICBIAS_2_OFF); 1441d5add08fSSrinivas Kandagatla 1442d5add08fSSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 1443d5add08fSSrinivas Kandagatla WCD938X_MICB_EN_MASK, 0); 1444bcee7ed0SSrinivas Kandagatla if (micb_num == MIC_BIAS_2) 1445bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 1446bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_MICBIAS_2_OFF); 1447d5add08fSSrinivas Kandagatla } 1448bcee7ed0SSrinivas Kandagatla if (is_dapm && micb_num == MIC_BIAS_2) 1449bcee7ed0SSrinivas Kandagatla wcd_mbhc_event_notify(wcd938x->wcd_mbhc, 1450bcee7ed0SSrinivas Kandagatla WCD_EVENT_POST_DAPM_MICBIAS_2_OFF); 1451d5add08fSSrinivas Kandagatla break; 1452d5add08fSSrinivas Kandagatla } 1453d5add08fSSrinivas Kandagatla 1454d5add08fSSrinivas Kandagatla return 0; 1455d5add08fSSrinivas Kandagatla } 1456d5add08fSSrinivas Kandagatla 1457d5add08fSSrinivas Kandagatla static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w, 1458d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 1459d5add08fSSrinivas Kandagatla int event) 1460d5add08fSSrinivas Kandagatla { 1461d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1462d5add08fSSrinivas Kandagatla int micb_num = w->shift; 1463d5add08fSSrinivas Kandagatla 1464d5add08fSSrinivas Kandagatla switch (event) { 1465d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1466d5add08fSSrinivas Kandagatla wcd938x_micbias_control(component, micb_num, MICB_ENABLE, true); 1467d5add08fSSrinivas Kandagatla break; 1468d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 1469d5add08fSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 1470d5add08fSSrinivas Kandagatla usleep_range(1000, 1100); 1471d5add08fSSrinivas Kandagatla break; 1472d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1473d5add08fSSrinivas Kandagatla wcd938x_micbias_control(component, micb_num, MICB_DISABLE, true); 1474d5add08fSSrinivas Kandagatla break; 1475d5add08fSSrinivas Kandagatla } 1476d5add08fSSrinivas Kandagatla 1477d5add08fSSrinivas Kandagatla return 0; 1478d5add08fSSrinivas Kandagatla } 1479d5add08fSSrinivas Kandagatla 1480d5add08fSSrinivas Kandagatla static int wcd938x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w, 1481d5add08fSSrinivas Kandagatla struct snd_kcontrol *kcontrol, 1482d5add08fSSrinivas Kandagatla int event) 1483d5add08fSSrinivas Kandagatla { 1484d5add08fSSrinivas Kandagatla struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1485d5add08fSSrinivas Kandagatla int micb_num = w->shift; 1486d5add08fSSrinivas Kandagatla 1487d5add08fSSrinivas Kandagatla switch (event) { 1488d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_PRE_PMU: 1489d5add08fSSrinivas Kandagatla wcd938x_micbias_control(component, micb_num, 1490d5add08fSSrinivas Kandagatla MICB_PULLUP_ENABLE, true); 1491d5add08fSSrinivas Kandagatla break; 1492d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMU: 1493d5add08fSSrinivas Kandagatla /* 1 msec delay as per HW requirement */ 1494d5add08fSSrinivas Kandagatla usleep_range(1000, 1100); 1495d5add08fSSrinivas Kandagatla break; 1496d5add08fSSrinivas Kandagatla case SND_SOC_DAPM_POST_PMD: 1497d5add08fSSrinivas Kandagatla wcd938x_micbias_control(component, micb_num, 1498d5add08fSSrinivas Kandagatla MICB_PULLUP_DISABLE, true); 1499d5add08fSSrinivas Kandagatla break; 1500d5add08fSSrinivas Kandagatla } 1501d5add08fSSrinivas Kandagatla 1502d5add08fSSrinivas Kandagatla return 0; 1503d5add08fSSrinivas Kandagatla } 1504d5add08fSSrinivas Kandagatla 1505e8ba1e05SSrinivas Kandagatla static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol, 1506e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1507e8ba1e05SSrinivas Kandagatla { 1508e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1509e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1510e8ba1e05SSrinivas Kandagatla struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1511e8ba1e05SSrinivas Kandagatla int path = e->shift_l; 1512e8ba1e05SSrinivas Kandagatla 1513cc587b7cSSrinivas Kandagatla ucontrol->value.enumerated.item[0] = wcd938x->tx_mode[path]; 1514e8ba1e05SSrinivas Kandagatla 1515e8ba1e05SSrinivas Kandagatla return 0; 1516e8ba1e05SSrinivas Kandagatla } 1517e8ba1e05SSrinivas Kandagatla 1518e8ba1e05SSrinivas Kandagatla static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol, 1519e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1520e8ba1e05SSrinivas Kandagatla { 1521e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1522e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1523e8ba1e05SSrinivas Kandagatla struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1524e8ba1e05SSrinivas Kandagatla int path = e->shift_l; 1525e8ba1e05SSrinivas Kandagatla 152610e7ff00SMark Brown if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0]) 152710e7ff00SMark Brown return 0; 152810e7ff00SMark Brown 1529e8ba1e05SSrinivas Kandagatla wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0]; 1530e8ba1e05SSrinivas Kandagatla 1531e8ba1e05SSrinivas Kandagatla return 1; 1532e8ba1e05SSrinivas Kandagatla } 1533e8ba1e05SSrinivas Kandagatla 1534e8ba1e05SSrinivas Kandagatla static int wcd938x_rx_hph_mode_get(struct snd_kcontrol *kcontrol, 1535e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1536e8ba1e05SSrinivas Kandagatla { 1537e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1538e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1539e8ba1e05SSrinivas Kandagatla 1540cc587b7cSSrinivas Kandagatla ucontrol->value.enumerated.item[0] = wcd938x->hph_mode; 1541e8ba1e05SSrinivas Kandagatla 1542e8ba1e05SSrinivas Kandagatla return 0; 1543e8ba1e05SSrinivas Kandagatla } 1544e8ba1e05SSrinivas Kandagatla 1545e8ba1e05SSrinivas Kandagatla static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, 1546e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1547e8ba1e05SSrinivas Kandagatla { 1548e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1549e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1550e8ba1e05SSrinivas Kandagatla 155110e7ff00SMark Brown if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0]) 155210e7ff00SMark Brown return 0; 155310e7ff00SMark Brown 1554e8ba1e05SSrinivas Kandagatla wcd938x->hph_mode = ucontrol->value.enumerated.item[0]; 1555e8ba1e05SSrinivas Kandagatla 1556e8ba1e05SSrinivas Kandagatla return 1; 1557e8ba1e05SSrinivas Kandagatla } 1558e8ba1e05SSrinivas Kandagatla 1559e8ba1e05SSrinivas Kandagatla static int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol, 1560e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1561e8ba1e05SSrinivas Kandagatla { 1562e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1563e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1564e8ba1e05SSrinivas Kandagatla 1565e8ba1e05SSrinivas Kandagatla if (wcd938x->comp1_enable) { 1566e8ba1e05SSrinivas Kandagatla dev_err(component->dev, "Can not set EAR PA Gain, compander1 is enabled\n"); 1567e8ba1e05SSrinivas Kandagatla return -EINVAL; 1568e8ba1e05SSrinivas Kandagatla } 1569e8ba1e05SSrinivas Kandagatla 1570e8ba1e05SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_EAR_COMPANDER_CTL, 1571e8ba1e05SSrinivas Kandagatla WCD938X_EAR_GAIN_MASK, 1572e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0]); 1573e8ba1e05SSrinivas Kandagatla 1574bd2347fdSSrinivas Kandagatla return 1; 1575e8ba1e05SSrinivas Kandagatla } 1576e8ba1e05SSrinivas Kandagatla 1577e8ba1e05SSrinivas Kandagatla static int wcd938x_get_compander(struct snd_kcontrol *kcontrol, 1578e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1579e8ba1e05SSrinivas Kandagatla { 1580e8ba1e05SSrinivas Kandagatla 1581e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1582e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1583e8ba1e05SSrinivas Kandagatla struct soc_mixer_control *mc; 1584e8ba1e05SSrinivas Kandagatla bool hphr; 1585e8ba1e05SSrinivas Kandagatla 1586e8ba1e05SSrinivas Kandagatla mc = (struct soc_mixer_control *)(kcontrol->private_value); 1587e8ba1e05SSrinivas Kandagatla hphr = mc->shift; 1588e8ba1e05SSrinivas Kandagatla 1589e8ba1e05SSrinivas Kandagatla if (hphr) 1590e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd938x->comp2_enable; 1591e8ba1e05SSrinivas Kandagatla else 1592e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd938x->comp1_enable; 1593e8ba1e05SSrinivas Kandagatla 1594e8ba1e05SSrinivas Kandagatla return 0; 1595e8ba1e05SSrinivas Kandagatla } 1596e8ba1e05SSrinivas Kandagatla 1597e8ba1e05SSrinivas Kandagatla static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, 1598e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1599e8ba1e05SSrinivas Kandagatla { 1600e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1601e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1602e8ba1e05SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd; 1603e8ba1e05SSrinivas Kandagatla int value = ucontrol->value.integer.value[0]; 1604c5c1546aSSrinivas Kandagatla int portidx; 1605e8ba1e05SSrinivas Kandagatla struct soc_mixer_control *mc; 1606e8ba1e05SSrinivas Kandagatla bool hphr; 1607e8ba1e05SSrinivas Kandagatla 1608e8ba1e05SSrinivas Kandagatla mc = (struct soc_mixer_control *)(kcontrol->private_value); 1609e8ba1e05SSrinivas Kandagatla hphr = mc->shift; 1610e8ba1e05SSrinivas Kandagatla 1611e8ba1e05SSrinivas Kandagatla wcd = wcd938x->sdw_priv[AIF1_PB]; 1612e8ba1e05SSrinivas Kandagatla 1613e8ba1e05SSrinivas Kandagatla if (hphr) 1614e8ba1e05SSrinivas Kandagatla wcd938x->comp2_enable = value; 1615e8ba1e05SSrinivas Kandagatla else 1616e8ba1e05SSrinivas Kandagatla wcd938x->comp1_enable = value; 1617e8ba1e05SSrinivas Kandagatla 1618c5c1546aSSrinivas Kandagatla portidx = wcd->ch_info[mc->reg].port_num; 1619c5c1546aSSrinivas Kandagatla 1620e8ba1e05SSrinivas Kandagatla if (value) 1621c5c1546aSSrinivas Kandagatla wcd938x_connect_port(wcd, portidx, mc->reg, true); 1622e8ba1e05SSrinivas Kandagatla else 1623c5c1546aSSrinivas Kandagatla wcd938x_connect_port(wcd, portidx, mc->reg, false); 1624e8ba1e05SSrinivas Kandagatla 1625bd2347fdSSrinivas Kandagatla return 1; 1626e8ba1e05SSrinivas Kandagatla } 1627e8ba1e05SSrinivas Kandagatla 1628e8ba1e05SSrinivas Kandagatla static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol, 1629e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1630e8ba1e05SSrinivas Kandagatla { 1631e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1632e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1633e8ba1e05SSrinivas Kandagatla 1634e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd938x->ldoh; 1635e8ba1e05SSrinivas Kandagatla 1636e8ba1e05SSrinivas Kandagatla return 0; 1637e8ba1e05SSrinivas Kandagatla } 1638e8ba1e05SSrinivas Kandagatla 1639e8ba1e05SSrinivas Kandagatla static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol, 1640e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1641e8ba1e05SSrinivas Kandagatla { 1642e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1643e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1644e8ba1e05SSrinivas Kandagatla 164510e7ff00SMark Brown if (wcd938x->ldoh == ucontrol->value.integer.value[0]) 164610e7ff00SMark Brown return 0; 164710e7ff00SMark Brown 1648e8ba1e05SSrinivas Kandagatla wcd938x->ldoh = ucontrol->value.integer.value[0]; 1649e8ba1e05SSrinivas Kandagatla 1650e8ba1e05SSrinivas Kandagatla return 1; 1651e8ba1e05SSrinivas Kandagatla } 1652e8ba1e05SSrinivas Kandagatla 1653e8ba1e05SSrinivas Kandagatla static int wcd938x_bcs_get(struct snd_kcontrol *kcontrol, 1654e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1655e8ba1e05SSrinivas Kandagatla { 1656e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1657e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1658e8ba1e05SSrinivas Kandagatla 1659e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd938x->bcs_dis; 1660e8ba1e05SSrinivas Kandagatla 1661e8ba1e05SSrinivas Kandagatla return 0; 1662e8ba1e05SSrinivas Kandagatla } 1663e8ba1e05SSrinivas Kandagatla 1664e8ba1e05SSrinivas Kandagatla static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, 1665e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1666e8ba1e05SSrinivas Kandagatla { 1667e8ba1e05SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1668e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1669e8ba1e05SSrinivas Kandagatla 167010e7ff00SMark Brown if (wcd938x->bcs_dis == ucontrol->value.integer.value[0]) 167110e7ff00SMark Brown return 0; 167210e7ff00SMark Brown 1673e8ba1e05SSrinivas Kandagatla wcd938x->bcs_dis = ucontrol->value.integer.value[0]; 1674e8ba1e05SSrinivas Kandagatla 1675e8ba1e05SSrinivas Kandagatla return 1; 1676e8ba1e05SSrinivas Kandagatla } 1677e8ba1e05SSrinivas Kandagatla 1678e8ba1e05SSrinivas Kandagatla static const char * const tx_mode_mux_text_wcd9380[] = { 1679e8ba1e05SSrinivas Kandagatla "ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP", 1680e8ba1e05SSrinivas Kandagatla }; 1681e8ba1e05SSrinivas Kandagatla 1682e8ba1e05SSrinivas Kandagatla static const char * const tx_mode_mux_text[] = { 1683e8ba1e05SSrinivas Kandagatla "ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP", 1684e8ba1e05SSrinivas Kandagatla "ADC_ULP1", "ADC_ULP2", 1685e8ba1e05SSrinivas Kandagatla }; 1686e8ba1e05SSrinivas Kandagatla 1687e8ba1e05SSrinivas Kandagatla static const char * const rx_hph_mode_mux_text_wcd9380[] = { 1688e8ba1e05SSrinivas Kandagatla "CLS_H_INVALID", "CLS_H_INVALID_1", "CLS_H_LP", "CLS_AB", 1689e8ba1e05SSrinivas Kandagatla "CLS_H_LOHIFI", "CLS_H_ULP", "CLS_H_INVALID_2", "CLS_AB_LP", 1690e8ba1e05SSrinivas Kandagatla "CLS_AB_LOHIFI", 1691e8ba1e05SSrinivas Kandagatla }; 1692e8ba1e05SSrinivas Kandagatla 1693e8ba1e05SSrinivas Kandagatla static const char * const rx_hph_mode_mux_text[] = { 1694e8ba1e05SSrinivas Kandagatla "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI", 1695e8ba1e05SSrinivas Kandagatla "CLS_H_ULP", "CLS_AB_HIFI", "CLS_AB_LP", "CLS_AB_LOHIFI", 1696e8ba1e05SSrinivas Kandagatla }; 1697e8ba1e05SSrinivas Kandagatla 16988da9db0cSSrinivas Kandagatla static const char * const adc2_mux_text[] = { 16998da9db0cSSrinivas Kandagatla "INP2", "INP3" 17008da9db0cSSrinivas Kandagatla }; 17018da9db0cSSrinivas Kandagatla 17028da9db0cSSrinivas Kandagatla static const char * const adc3_mux_text[] = { 17038da9db0cSSrinivas Kandagatla "INP4", "INP6" 17048da9db0cSSrinivas Kandagatla }; 17058da9db0cSSrinivas Kandagatla 17068da9db0cSSrinivas Kandagatla static const char * const adc4_mux_text[] = { 17078da9db0cSSrinivas Kandagatla "INP5", "INP7" 17088da9db0cSSrinivas Kandagatla }; 17098da9db0cSSrinivas Kandagatla 17108da9db0cSSrinivas Kandagatla static const char * const rdac3_mux_text[] = { 17118da9db0cSSrinivas Kandagatla "RX1", "RX3" 17128da9db0cSSrinivas Kandagatla }; 17138da9db0cSSrinivas Kandagatla 17148da9db0cSSrinivas Kandagatla static const char * const hdr12_mux_text[] = { 17158da9db0cSSrinivas Kandagatla "NO_HDR12", "HDR12" 17168da9db0cSSrinivas Kandagatla }; 17178da9db0cSSrinivas Kandagatla 17188da9db0cSSrinivas Kandagatla static const char * const hdr34_mux_text[] = { 17198da9db0cSSrinivas Kandagatla "NO_HDR34", "HDR34" 17208da9db0cSSrinivas Kandagatla }; 17218da9db0cSSrinivas Kandagatla 1722e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx0_mode_enum_wcd9380 = 1723e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text_wcd9380), 1724e8ba1e05SSrinivas Kandagatla tx_mode_mux_text_wcd9380); 1725e8ba1e05SSrinivas Kandagatla 1726e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx1_mode_enum_wcd9380 = 1727e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text_wcd9380), 1728e8ba1e05SSrinivas Kandagatla tx_mode_mux_text_wcd9380); 1729e8ba1e05SSrinivas Kandagatla 1730e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx2_mode_enum_wcd9380 = 1731e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text_wcd9380), 1732e8ba1e05SSrinivas Kandagatla tx_mode_mux_text_wcd9380); 1733e8ba1e05SSrinivas Kandagatla 1734e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx3_mode_enum_wcd9380 = 1735e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text_wcd9380), 1736e8ba1e05SSrinivas Kandagatla tx_mode_mux_text_wcd9380); 1737e8ba1e05SSrinivas Kandagatla 1738e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx0_mode_enum_wcd9385 = 1739e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tx_mode_mux_text), 1740e8ba1e05SSrinivas Kandagatla tx_mode_mux_text); 1741e8ba1e05SSrinivas Kandagatla 1742e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx1_mode_enum_wcd9385 = 1743e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 1, ARRAY_SIZE(tx_mode_mux_text), 1744e8ba1e05SSrinivas Kandagatla tx_mode_mux_text); 1745e8ba1e05SSrinivas Kandagatla 1746e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx2_mode_enum_wcd9385 = 1747e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 2, ARRAY_SIZE(tx_mode_mux_text), 1748e8ba1e05SSrinivas Kandagatla tx_mode_mux_text); 1749e8ba1e05SSrinivas Kandagatla 1750e8ba1e05SSrinivas Kandagatla static const struct soc_enum tx3_mode_enum_wcd9385 = 1751e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE(SND_SOC_NOPM, 3, ARRAY_SIZE(tx_mode_mux_text), 1752e8ba1e05SSrinivas Kandagatla tx_mode_mux_text); 1753e8ba1e05SSrinivas Kandagatla 1754e8ba1e05SSrinivas Kandagatla static const struct soc_enum rx_hph_mode_mux_enum_wcd9380 = 1755e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text_wcd9380), 1756e8ba1e05SSrinivas Kandagatla rx_hph_mode_mux_text_wcd9380); 1757e8ba1e05SSrinivas Kandagatla 1758e8ba1e05SSrinivas Kandagatla static const struct soc_enum rx_hph_mode_mux_enum = 1759e8ba1e05SSrinivas Kandagatla SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text), 1760e8ba1e05SSrinivas Kandagatla rx_hph_mode_mux_text); 1761e8ba1e05SSrinivas Kandagatla 1762d5add08fSSrinivas Kandagatla static const struct soc_enum adc2_enum = 1763d5add08fSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 7, 1764d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc2_mux_text), adc2_mux_text); 1765d5add08fSSrinivas Kandagatla 1766d5add08fSSrinivas Kandagatla static const struct soc_enum adc3_enum = 1767d5add08fSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 6, 1768d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc3_mux_text), adc3_mux_text); 1769d5add08fSSrinivas Kandagatla 1770d5add08fSSrinivas Kandagatla static const struct soc_enum adc4_enum = 1771d5add08fSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 5, 1772d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc4_mux_text), adc4_mux_text); 1773d5add08fSSrinivas Kandagatla 1774d5add08fSSrinivas Kandagatla static const struct soc_enum hdr12_enum = 1775d5add08fSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 4, 1776d5add08fSSrinivas Kandagatla ARRAY_SIZE(hdr12_mux_text), hdr12_mux_text); 1777d5add08fSSrinivas Kandagatla 1778d5add08fSSrinivas Kandagatla static const struct soc_enum hdr34_enum = 1779d5add08fSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 3, 1780d5add08fSSrinivas Kandagatla ARRAY_SIZE(hdr34_mux_text), hdr34_mux_text); 1781d5add08fSSrinivas Kandagatla 17828da9db0cSSrinivas Kandagatla static const struct soc_enum rdac3_enum = 17838da9db0cSSrinivas Kandagatla SOC_ENUM_SINGLE(WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0, 17848da9db0cSSrinivas Kandagatla ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text); 17858da9db0cSSrinivas Kandagatla 1786d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new adc1_switch[] = { 1787d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1788d5add08fSSrinivas Kandagatla }; 1789d5add08fSSrinivas Kandagatla 1790d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new adc2_switch[] = { 1791d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1792d5add08fSSrinivas Kandagatla }; 1793d5add08fSSrinivas Kandagatla 1794d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new adc3_switch[] = { 1795d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1796d5add08fSSrinivas Kandagatla }; 1797d5add08fSSrinivas Kandagatla 1798d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new adc4_switch[] = { 1799d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1800d5add08fSSrinivas Kandagatla }; 1801d5add08fSSrinivas Kandagatla 1802d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic1_switch[] = { 1803d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1804d5add08fSSrinivas Kandagatla }; 1805d5add08fSSrinivas Kandagatla 1806d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic2_switch[] = { 1807d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1808d5add08fSSrinivas Kandagatla }; 1809d5add08fSSrinivas Kandagatla 1810d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic3_switch[] = { 1811d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1812d5add08fSSrinivas Kandagatla }; 1813d5add08fSSrinivas Kandagatla 1814d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic4_switch[] = { 1815d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1816d5add08fSSrinivas Kandagatla }; 1817d5add08fSSrinivas Kandagatla 1818d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic5_switch[] = { 1819d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1820d5add08fSSrinivas Kandagatla }; 1821d5add08fSSrinivas Kandagatla 1822d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic6_switch[] = { 1823d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1824d5add08fSSrinivas Kandagatla }; 1825d5add08fSSrinivas Kandagatla 1826d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic7_switch[] = { 1827d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1828d5add08fSSrinivas Kandagatla }; 1829d5add08fSSrinivas Kandagatla 1830d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new dmic8_switch[] = { 1831d5add08fSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 1832d5add08fSSrinivas Kandagatla }; 1833d5add08fSSrinivas Kandagatla 18348da9db0cSSrinivas Kandagatla static const struct snd_kcontrol_new ear_rdac_switch[] = { 18358da9db0cSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 18368da9db0cSSrinivas Kandagatla }; 18378da9db0cSSrinivas Kandagatla 18388da9db0cSSrinivas Kandagatla static const struct snd_kcontrol_new aux_rdac_switch[] = { 18398da9db0cSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 18408da9db0cSSrinivas Kandagatla }; 18418da9db0cSSrinivas Kandagatla 18428da9db0cSSrinivas Kandagatla static const struct snd_kcontrol_new hphl_rdac_switch[] = { 18438da9db0cSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 18448da9db0cSSrinivas Kandagatla }; 18458da9db0cSSrinivas Kandagatla 18468da9db0cSSrinivas Kandagatla static const struct snd_kcontrol_new hphr_rdac_switch[] = { 18478da9db0cSSrinivas Kandagatla SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 18488da9db0cSSrinivas Kandagatla }; 18498da9db0cSSrinivas Kandagatla 1850d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new tx_adc2_mux = 1851d5add08fSSrinivas Kandagatla SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum); 1852d5add08fSSrinivas Kandagatla 1853d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new tx_adc3_mux = 1854d5add08fSSrinivas Kandagatla SOC_DAPM_ENUM("ADC3 MUX Mux", adc3_enum); 1855d5add08fSSrinivas Kandagatla 1856d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new tx_adc4_mux = 1857d5add08fSSrinivas Kandagatla SOC_DAPM_ENUM("ADC4 MUX Mux", adc4_enum); 1858d5add08fSSrinivas Kandagatla 1859d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new tx_hdr12_mux = 1860d5add08fSSrinivas Kandagatla SOC_DAPM_ENUM("HDR12 MUX Mux", hdr12_enum); 1861d5add08fSSrinivas Kandagatla 1862d5add08fSSrinivas Kandagatla static const struct snd_kcontrol_new tx_hdr34_mux = 1863d5add08fSSrinivas Kandagatla SOC_DAPM_ENUM("HDR34 MUX Mux", hdr34_enum); 1864d5add08fSSrinivas Kandagatla 18658da9db0cSSrinivas Kandagatla static const struct snd_kcontrol_new rx_rdac3_mux = 18668da9db0cSSrinivas Kandagatla SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum); 18678da9db0cSSrinivas Kandagatla 1868e8ba1e05SSrinivas Kandagatla static const struct snd_kcontrol_new wcd9380_snd_controls[] = { 1869e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum_wcd9380, 1870e8ba1e05SSrinivas Kandagatla wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put), 1871e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9380, 1872e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1873e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9380, 1874e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1875e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9380, 1876e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1877e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9380, 1878e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1879e8ba1e05SSrinivas Kandagatla }; 1880e8ba1e05SSrinivas Kandagatla 1881e8ba1e05SSrinivas Kandagatla static const struct snd_kcontrol_new wcd9385_snd_controls[] = { 1882e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum, 1883e8ba1e05SSrinivas Kandagatla wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put), 1884e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX0 MODE", tx0_mode_enum_wcd9385, 1885e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1886e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX1 MODE", tx1_mode_enum_wcd9385, 1887e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1888e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX2 MODE", tx2_mode_enum_wcd9385, 1889e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1890e8ba1e05SSrinivas Kandagatla SOC_ENUM_EXT("TX3 MODE", tx3_mode_enum_wcd9385, 1891e8ba1e05SSrinivas Kandagatla wcd938x_tx_mode_get, wcd938x_tx_mode_put), 1892e8ba1e05SSrinivas Kandagatla }; 1893e8ba1e05SSrinivas Kandagatla 1894e8ba1e05SSrinivas Kandagatla static int wcd938x_get_swr_port(struct snd_kcontrol *kcontrol, 1895e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1896e8ba1e05SSrinivas Kandagatla { 1897e8ba1e05SSrinivas Kandagatla struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 1898e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp); 1899e8ba1e05SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd; 1900e8ba1e05SSrinivas Kandagatla struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; 1901e8ba1e05SSrinivas Kandagatla int dai_id = mixer->shift; 1902c5c1546aSSrinivas Kandagatla int portidx, ch_idx = mixer->reg; 1903c5c1546aSSrinivas Kandagatla 1904e8ba1e05SSrinivas Kandagatla 1905e8ba1e05SSrinivas Kandagatla wcd = wcd938x->sdw_priv[dai_id]; 1906c5c1546aSSrinivas Kandagatla portidx = wcd->ch_info[ch_idx].port_num; 1907e8ba1e05SSrinivas Kandagatla 1908e8ba1e05SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd->port_enable[portidx]; 1909e8ba1e05SSrinivas Kandagatla 1910e8ba1e05SSrinivas Kandagatla return 0; 1911e8ba1e05SSrinivas Kandagatla } 1912e8ba1e05SSrinivas Kandagatla 1913e8ba1e05SSrinivas Kandagatla static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, 1914e8ba1e05SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 1915e8ba1e05SSrinivas Kandagatla { 1916e8ba1e05SSrinivas Kandagatla struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 1917e8ba1e05SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(comp); 1918e8ba1e05SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd; 1919e8ba1e05SSrinivas Kandagatla struct soc_mixer_control *mixer = 1920e8ba1e05SSrinivas Kandagatla (struct soc_mixer_control *)kcontrol->private_value; 1921c5c1546aSSrinivas Kandagatla int ch_idx = mixer->reg; 1922c5c1546aSSrinivas Kandagatla int portidx; 1923e8ba1e05SSrinivas Kandagatla int dai_id = mixer->shift; 1924e8ba1e05SSrinivas Kandagatla bool enable; 1925e8ba1e05SSrinivas Kandagatla 1926e8ba1e05SSrinivas Kandagatla wcd = wcd938x->sdw_priv[dai_id]; 1927e8ba1e05SSrinivas Kandagatla 1928c5c1546aSSrinivas Kandagatla portidx = wcd->ch_info[ch_idx].port_num; 1929e8ba1e05SSrinivas Kandagatla if (ucontrol->value.integer.value[0]) 1930e8ba1e05SSrinivas Kandagatla enable = true; 1931e8ba1e05SSrinivas Kandagatla else 1932e8ba1e05SSrinivas Kandagatla enable = false; 1933e8ba1e05SSrinivas Kandagatla 1934e8ba1e05SSrinivas Kandagatla wcd->port_enable[portidx] = enable; 1935e8ba1e05SSrinivas Kandagatla 1936c5c1546aSSrinivas Kandagatla wcd938x_connect_port(wcd, portidx, ch_idx, enable); 1937e8ba1e05SSrinivas Kandagatla 1938bd2347fdSSrinivas Kandagatla return 1; 1939e8ba1e05SSrinivas Kandagatla 1940e8ba1e05SSrinivas Kandagatla } 1941e8ba1e05SSrinivas Kandagatla 1942bcee7ed0SSrinivas Kandagatla /* MBHC related */ 1943bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component, 1944bcee7ed0SSrinivas Kandagatla bool enable) 1945bcee7ed0SSrinivas Kandagatla { 1946bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1, 1947bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_CTL_RCO_EN_MASK, enable); 1948bcee7ed0SSrinivas Kandagatla } 1949bcee7ed0SSrinivas Kandagatla 1950bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component, 1951bcee7ed0SSrinivas Kandagatla bool enable) 1952bcee7ed0SSrinivas Kandagatla { 1953bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT, 1954bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_BIAS_EN, enable); 1955bcee7ed0SSrinivas Kandagatla } 1956bcee7ed0SSrinivas Kandagatla 1957bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component, 1958bcee7ed0SSrinivas Kandagatla int *btn_low, int *btn_high, 1959bcee7ed0SSrinivas Kandagatla int num_btn, bool is_micbias) 1960bcee7ed0SSrinivas Kandagatla { 1961bcee7ed0SSrinivas Kandagatla int i, vth; 1962bcee7ed0SSrinivas Kandagatla 1963bcee7ed0SSrinivas Kandagatla if (num_btn > WCD_MBHC_DEF_BUTTONS) { 1964bcee7ed0SSrinivas Kandagatla dev_err(component->dev, "%s: invalid number of buttons: %d\n", 1965bcee7ed0SSrinivas Kandagatla __func__, num_btn); 1966bcee7ed0SSrinivas Kandagatla return; 1967bcee7ed0SSrinivas Kandagatla } 1968bcee7ed0SSrinivas Kandagatla 1969bcee7ed0SSrinivas Kandagatla for (i = 0; i < num_btn; i++) { 1970bcee7ed0SSrinivas Kandagatla vth = ((btn_high[i] * 2) / 25) & 0x3F; 1971bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i, 1972bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_BTN_VTH_MASK, vth); 1973bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n", 1974bcee7ed0SSrinivas Kandagatla __func__, i, btn_high[i], vth); 1975bcee7ed0SSrinivas Kandagatla } 1976bcee7ed0SSrinivas Kandagatla } 1977bcee7ed0SSrinivas Kandagatla 1978bcee7ed0SSrinivas Kandagatla static bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num) 1979bcee7ed0SSrinivas Kandagatla { 1980bcee7ed0SSrinivas Kandagatla u8 val; 1981bcee7ed0SSrinivas Kandagatla 1982bcee7ed0SSrinivas Kandagatla if (micb_num == MIC_BIAS_2) { 1983bcee7ed0SSrinivas Kandagatla val = snd_soc_component_read_field(component, 1984bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MICB2, 1985bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MICB2_ENABLE_MASK); 1986bcee7ed0SSrinivas Kandagatla if (val == WCD938X_MICB_ENABLE) 1987bcee7ed0SSrinivas Kandagatla return true; 1988bcee7ed0SSrinivas Kandagatla } 1989bcee7ed0SSrinivas Kandagatla return false; 1990bcee7ed0SSrinivas Kandagatla } 1991bcee7ed0SSrinivas Kandagatla 1992bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component, 1993bcee7ed0SSrinivas Kandagatla int pull_up_cur) 1994bcee7ed0SSrinivas Kandagatla { 1995bcee7ed0SSrinivas Kandagatla /* Default pull up current to 2uA */ 1996bcee7ed0SSrinivas Kandagatla if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA) 1997bcee7ed0SSrinivas Kandagatla pull_up_cur = HS_PULLUP_I_2P0_UA; 1998bcee7ed0SSrinivas Kandagatla 1999bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, 2000bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 2001bcee7ed0SSrinivas Kandagatla WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur); 2002bcee7ed0SSrinivas Kandagatla } 2003bcee7ed0SSrinivas Kandagatla 2004bcee7ed0SSrinivas Kandagatla static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component, 2005bcee7ed0SSrinivas Kandagatla int micb_num, int req) 2006bcee7ed0SSrinivas Kandagatla { 2007bcee7ed0SSrinivas Kandagatla return wcd938x_micbias_control(component, micb_num, req, false); 2008bcee7ed0SSrinivas Kandagatla } 2009bcee7ed0SSrinivas Kandagatla 2010bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component, 2011bcee7ed0SSrinivas Kandagatla bool enable) 2012bcee7ed0SSrinivas Kandagatla { 2013bcee7ed0SSrinivas Kandagatla if (enable) { 2014bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, 2015bcee7ed0SSrinivas Kandagatla WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C); 2016bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, 2017bcee7ed0SSrinivas Kandagatla WCD938X_RAMP_EN_MASK, 1); 2018bcee7ed0SSrinivas Kandagatla } else { 2019bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, 2020bcee7ed0SSrinivas Kandagatla WCD938X_RAMP_EN_MASK, 0); 2021bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, 2022bcee7ed0SSrinivas Kandagatla WCD938X_RAMP_SHIFT_CTRL_MASK, 0); 2023bcee7ed0SSrinivas Kandagatla } 2024bcee7ed0SSrinivas Kandagatla } 2025bcee7ed0SSrinivas Kandagatla 2026bcee7ed0SSrinivas Kandagatla static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv) 2027bcee7ed0SSrinivas Kandagatla { 2028bcee7ed0SSrinivas Kandagatla /* min micbias voltage is 1V and maximum is 2.85V */ 2029bcee7ed0SSrinivas Kandagatla if (micb_mv < 1000 || micb_mv > 2850) 2030bcee7ed0SSrinivas Kandagatla return -EINVAL; 2031bcee7ed0SSrinivas Kandagatla 2032bcee7ed0SSrinivas Kandagatla return (micb_mv - 1000) / 50; 2033bcee7ed0SSrinivas Kandagatla } 2034bcee7ed0SSrinivas Kandagatla 2035bcee7ed0SSrinivas Kandagatla static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, 2036bcee7ed0SSrinivas Kandagatla int req_volt, int micb_num) 2037bcee7ed0SSrinivas Kandagatla { 2038bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2039bcee7ed0SSrinivas Kandagatla int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0; 2040bcee7ed0SSrinivas Kandagatla 2041bcee7ed0SSrinivas Kandagatla switch (micb_num) { 2042bcee7ed0SSrinivas Kandagatla case MIC_BIAS_1: 2043bcee7ed0SSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB1; 2044bcee7ed0SSrinivas Kandagatla break; 2045bcee7ed0SSrinivas Kandagatla case MIC_BIAS_2: 2046bcee7ed0SSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB2; 2047bcee7ed0SSrinivas Kandagatla break; 2048bcee7ed0SSrinivas Kandagatla case MIC_BIAS_3: 2049bcee7ed0SSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB3; 2050bcee7ed0SSrinivas Kandagatla break; 2051bcee7ed0SSrinivas Kandagatla case MIC_BIAS_4: 2052bcee7ed0SSrinivas Kandagatla micb_reg = WCD938X_ANA_MICB4; 2053bcee7ed0SSrinivas Kandagatla break; 2054bcee7ed0SSrinivas Kandagatla default: 2055bcee7ed0SSrinivas Kandagatla return -EINVAL; 2056bcee7ed0SSrinivas Kandagatla } 2057bcee7ed0SSrinivas Kandagatla mutex_lock(&wcd938x->micb_lock); 2058bcee7ed0SSrinivas Kandagatla /* 2059bcee7ed0SSrinivas Kandagatla * If requested micbias voltage is same as current micbias 2060bcee7ed0SSrinivas Kandagatla * voltage, then just return. Otherwise, adjust voltage as 2061bcee7ed0SSrinivas Kandagatla * per requested value. If micbias is already enabled, then 2062bcee7ed0SSrinivas Kandagatla * to avoid slow micbias ramp-up or down enable pull-up 2063bcee7ed0SSrinivas Kandagatla * momentarily, change the micbias value and then re-enable 2064bcee7ed0SSrinivas Kandagatla * micbias. 2065bcee7ed0SSrinivas Kandagatla */ 2066bcee7ed0SSrinivas Kandagatla micb_en = snd_soc_component_read_field(component, micb_reg, 2067bcee7ed0SSrinivas Kandagatla WCD938X_MICB_EN_MASK); 2068bcee7ed0SSrinivas Kandagatla cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, 2069bcee7ed0SSrinivas Kandagatla WCD938X_MICB_VOUT_MASK); 2070bcee7ed0SSrinivas Kandagatla 2071bcee7ed0SSrinivas Kandagatla req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt); 2072bcee7ed0SSrinivas Kandagatla if (req_vout_ctl < 0) { 2073bcee7ed0SSrinivas Kandagatla ret = -EINVAL; 2074bcee7ed0SSrinivas Kandagatla goto exit; 2075bcee7ed0SSrinivas Kandagatla } 2076bcee7ed0SSrinivas Kandagatla 2077bcee7ed0SSrinivas Kandagatla if (cur_vout_ctl == req_vout_ctl) { 2078bcee7ed0SSrinivas Kandagatla ret = 0; 2079bcee7ed0SSrinivas Kandagatla goto exit; 2080bcee7ed0SSrinivas Kandagatla } 2081bcee7ed0SSrinivas Kandagatla 2082bcee7ed0SSrinivas Kandagatla if (micb_en == WCD938X_MICB_ENABLE) 2083bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 2084bcee7ed0SSrinivas Kandagatla WCD938X_MICB_EN_MASK, 2085bcee7ed0SSrinivas Kandagatla WCD938X_MICB_PULL_UP); 2086bcee7ed0SSrinivas Kandagatla 2087bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 2088bcee7ed0SSrinivas Kandagatla WCD938X_MICB_VOUT_MASK, 2089bcee7ed0SSrinivas Kandagatla req_vout_ctl); 2090bcee7ed0SSrinivas Kandagatla 2091bcee7ed0SSrinivas Kandagatla if (micb_en == WCD938X_MICB_ENABLE) { 2092bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, micb_reg, 2093bcee7ed0SSrinivas Kandagatla WCD938X_MICB_EN_MASK, 2094bcee7ed0SSrinivas Kandagatla WCD938X_MICB_ENABLE); 2095bcee7ed0SSrinivas Kandagatla /* 2096bcee7ed0SSrinivas Kandagatla * Add 2ms delay as per HW requirement after enabling 2097bcee7ed0SSrinivas Kandagatla * micbias 2098bcee7ed0SSrinivas Kandagatla */ 2099bcee7ed0SSrinivas Kandagatla usleep_range(2000, 2100); 2100bcee7ed0SSrinivas Kandagatla } 2101bcee7ed0SSrinivas Kandagatla exit: 2102bcee7ed0SSrinivas Kandagatla mutex_unlock(&wcd938x->micb_lock); 2103bcee7ed0SSrinivas Kandagatla return ret; 2104bcee7ed0SSrinivas Kandagatla } 2105bcee7ed0SSrinivas Kandagatla 2106bcee7ed0SSrinivas Kandagatla static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component, 2107bcee7ed0SSrinivas Kandagatla int micb_num, bool req_en) 2108bcee7ed0SSrinivas Kandagatla { 2109bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2110b2fde4deSchiminghao int micb_mv; 2111bcee7ed0SSrinivas Kandagatla 2112bcee7ed0SSrinivas Kandagatla if (micb_num != MIC_BIAS_2) 2113bcee7ed0SSrinivas Kandagatla return -EINVAL; 2114bcee7ed0SSrinivas Kandagatla /* 2115bcee7ed0SSrinivas Kandagatla * If device tree micbias level is already above the minimum 2116bcee7ed0SSrinivas Kandagatla * voltage needed to detect threshold microphone, then do 2117bcee7ed0SSrinivas Kandagatla * not change the micbias, just return. 2118bcee7ed0SSrinivas Kandagatla */ 2119bcee7ed0SSrinivas Kandagatla if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) 2120bcee7ed0SSrinivas Kandagatla return 0; 2121bcee7ed0SSrinivas Kandagatla 2122bcee7ed0SSrinivas Kandagatla micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv; 2123bcee7ed0SSrinivas Kandagatla 2124b2fde4deSchiminghao return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); 2125bcee7ed0SSrinivas Kandagatla } 2126bcee7ed0SSrinivas Kandagatla 212717d59d9eSJohan Hovold static void wcd938x_mbhc_get_result_params(struct snd_soc_component *component, 2128bcee7ed0SSrinivas Kandagatla s16 *d1_a, u16 noff, 2129bcee7ed0SSrinivas Kandagatla int32_t *zdet) 2130bcee7ed0SSrinivas Kandagatla { 213117d59d9eSJohan Hovold struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2132bcee7ed0SSrinivas Kandagatla int i; 2133bcee7ed0SSrinivas Kandagatla int val, val1; 2134bcee7ed0SSrinivas Kandagatla s16 c1; 2135bcee7ed0SSrinivas Kandagatla s32 x1, d1; 2136bcee7ed0SSrinivas Kandagatla int32_t denom; 2137e110ede8SColin Ian King static const int minCode_param[] = { 2138bcee7ed0SSrinivas Kandagatla 3277, 1639, 820, 410, 205, 103, 52, 26 2139bcee7ed0SSrinivas Kandagatla }; 2140bcee7ed0SSrinivas Kandagatla 2141bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20); 2142bcee7ed0SSrinivas Kandagatla for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) { 2143bcee7ed0SSrinivas Kandagatla regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val); 2144bcee7ed0SSrinivas Kandagatla if (val & 0x80) 2145bcee7ed0SSrinivas Kandagatla break; 2146bcee7ed0SSrinivas Kandagatla } 2147bcee7ed0SSrinivas Kandagatla val = val << 0x8; 2148bcee7ed0SSrinivas Kandagatla regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1); 2149bcee7ed0SSrinivas Kandagatla val |= val1; 2150bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00); 2151bcee7ed0SSrinivas Kandagatla x1 = WCD938X_MBHC_GET_X1(val); 2152bcee7ed0SSrinivas Kandagatla c1 = WCD938X_MBHC_GET_C1(val); 2153bcee7ed0SSrinivas Kandagatla /* If ramp is not complete, give additional 5ms */ 2154bcee7ed0SSrinivas Kandagatla if ((c1 < 2) && x1) 2155bcee7ed0SSrinivas Kandagatla usleep_range(5000, 5050); 2156bcee7ed0SSrinivas Kandagatla 2157bcee7ed0SSrinivas Kandagatla if (!c1 || !x1) { 215817d59d9eSJohan Hovold dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n", 215917d59d9eSJohan Hovold c1, x1); 2160bcee7ed0SSrinivas Kandagatla goto ramp_down; 2161bcee7ed0SSrinivas Kandagatla } 2162bcee7ed0SSrinivas Kandagatla d1 = d1_a[c1]; 2163bcee7ed0SSrinivas Kandagatla denom = (x1 * d1) - (1 << (14 - noff)); 2164bcee7ed0SSrinivas Kandagatla if (denom > 0) 2165bcee7ed0SSrinivas Kandagatla *zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom; 2166bcee7ed0SSrinivas Kandagatla else if (x1 < minCode_param[noff]) 2167bcee7ed0SSrinivas Kandagatla *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE; 2168bcee7ed0SSrinivas Kandagatla 216917d59d9eSJohan Hovold dev_dbg(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n", 2170bcee7ed0SSrinivas Kandagatla __func__, d1, c1, x1, *zdet); 2171bcee7ed0SSrinivas Kandagatla ramp_down: 2172bcee7ed0SSrinivas Kandagatla i = 0; 2173bcee7ed0SSrinivas Kandagatla while (x1) { 2174bcee7ed0SSrinivas Kandagatla regmap_read(wcd938x->regmap, 2175bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_RESULT_1, &val); 2176bcee7ed0SSrinivas Kandagatla regmap_read(wcd938x->regmap, 2177bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_RESULT_2, &val1); 2178bcee7ed0SSrinivas Kandagatla val = val << 0x08; 2179bcee7ed0SSrinivas Kandagatla val |= val1; 2180bcee7ed0SSrinivas Kandagatla x1 = WCD938X_MBHC_GET_X1(val); 2181bcee7ed0SSrinivas Kandagatla i++; 2182bcee7ed0SSrinivas Kandagatla if (i == WCD938X_ZDET_NUM_MEASUREMENTS) 2183bcee7ed0SSrinivas Kandagatla break; 2184bcee7ed0SSrinivas Kandagatla } 2185bcee7ed0SSrinivas Kandagatla } 2186bcee7ed0SSrinivas Kandagatla 2187bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component, 2188bcee7ed0SSrinivas Kandagatla struct wcd938x_mbhc_zdet_param *zdet_param, 2189bcee7ed0SSrinivas Kandagatla int32_t *zl, int32_t *zr, s16 *d1_a) 2190bcee7ed0SSrinivas Kandagatla { 2191bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2192bcee7ed0SSrinivas Kandagatla int32_t zdet = 0; 2193bcee7ed0SSrinivas Kandagatla 2194bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, 2195bcee7ed0SSrinivas Kandagatla WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl); 2196bcee7ed0SSrinivas Kandagatla snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5, 2197bcee7ed0SSrinivas Kandagatla WCD938X_VTH_MASK, zdet_param->btn5); 2198bcee7ed0SSrinivas Kandagatla snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6, 2199bcee7ed0SSrinivas Kandagatla WCD938X_VTH_MASK, zdet_param->btn6); 2200bcee7ed0SSrinivas Kandagatla snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7, 2201bcee7ed0SSrinivas Kandagatla WCD938X_VTH_MASK, zdet_param->btn7); 2202bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, 2203bcee7ed0SSrinivas Kandagatla WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff); 2204bcee7ed0SSrinivas Kandagatla snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL, 2205bcee7ed0SSrinivas Kandagatla 0x0F, zdet_param->nshift); 2206bcee7ed0SSrinivas Kandagatla 2207bcee7ed0SSrinivas Kandagatla if (!zl) 2208bcee7ed0SSrinivas Kandagatla goto z_right; 2209bcee7ed0SSrinivas Kandagatla /* Start impedance measurement for HPH_L */ 2210bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2211bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ZDET, 0x80, 0x80); 2212bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n", 2213bcee7ed0SSrinivas Kandagatla __func__, zdet_param->noff); 221417d59d9eSJohan Hovold wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet); 2215bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2216bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ZDET, 0x80, 0x00); 2217bcee7ed0SSrinivas Kandagatla 2218bcee7ed0SSrinivas Kandagatla *zl = zdet; 2219bcee7ed0SSrinivas Kandagatla 2220bcee7ed0SSrinivas Kandagatla z_right: 2221bcee7ed0SSrinivas Kandagatla if (!zr) 2222bcee7ed0SSrinivas Kandagatla return; 2223bcee7ed0SSrinivas Kandagatla /* Start impedance measurement for HPH_R */ 2224bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2225bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ZDET, 0x40, 0x40); 2226bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n", 2227bcee7ed0SSrinivas Kandagatla __func__, zdet_param->noff); 222817d59d9eSJohan Hovold wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet); 2229bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2230bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ZDET, 0x40, 0x00); 2231bcee7ed0SSrinivas Kandagatla 2232bcee7ed0SSrinivas Kandagatla *zr = zdet; 2233bcee7ed0SSrinivas Kandagatla } 2234bcee7ed0SSrinivas Kandagatla 22355db9fe95SJohan Hovold static void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component, 2236bcee7ed0SSrinivas Kandagatla int32_t *z_val, int flag_l_r) 2237bcee7ed0SSrinivas Kandagatla { 2238bcee7ed0SSrinivas Kandagatla s16 q1; 2239bcee7ed0SSrinivas Kandagatla int q1_cal; 2240bcee7ed0SSrinivas Kandagatla 2241bcee7ed0SSrinivas Kandagatla if (*z_val < (WCD938X_ZDET_VAL_400/1000)) 2242bcee7ed0SSrinivas Kandagatla q1 = snd_soc_component_read(component, 2243bcee7ed0SSrinivas Kandagatla WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r)); 2244bcee7ed0SSrinivas Kandagatla else 2245bcee7ed0SSrinivas Kandagatla q1 = snd_soc_component_read(component, 2246bcee7ed0SSrinivas Kandagatla WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r)); 2247bcee7ed0SSrinivas Kandagatla if (q1 & 0x80) 2248bcee7ed0SSrinivas Kandagatla q1_cal = (10000 - ((q1 & 0x7F) * 25)); 2249bcee7ed0SSrinivas Kandagatla else 2250bcee7ed0SSrinivas Kandagatla q1_cal = (10000 + (q1 * 25)); 2251bcee7ed0SSrinivas Kandagatla if (q1_cal > 0) 2252bcee7ed0SSrinivas Kandagatla *z_val = ((*z_val) * 10000) / q1_cal; 2253bcee7ed0SSrinivas Kandagatla } 2254bcee7ed0SSrinivas Kandagatla 2255bcee7ed0SSrinivas Kandagatla static void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component, 2256bcee7ed0SSrinivas Kandagatla uint32_t *zl, uint32_t *zr) 2257bcee7ed0SSrinivas Kandagatla { 2258bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2259bcee7ed0SSrinivas Kandagatla s16 reg0, reg1, reg2, reg3, reg4; 2260bcee7ed0SSrinivas Kandagatla int32_t z1L, z1R, z1Ls; 2261bcee7ed0SSrinivas Kandagatla int zMono, z_diff1, z_diff2; 2262bcee7ed0SSrinivas Kandagatla bool is_fsm_disable = false; 2263bcee7ed0SSrinivas Kandagatla struct wcd938x_mbhc_zdet_param zdet_param[] = { 2264bcee7ed0SSrinivas Kandagatla {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */ 2265bcee7ed0SSrinivas Kandagatla {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */ 2266bcee7ed0SSrinivas Kandagatla {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */ 2267bcee7ed0SSrinivas Kandagatla {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */ 2268bcee7ed0SSrinivas Kandagatla }; 2269bcee7ed0SSrinivas Kandagatla struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL; 2270bcee7ed0SSrinivas Kandagatla s16 d1_a[][4] = { 2271bcee7ed0SSrinivas Kandagatla {0, 30, 90, 30}, 2272bcee7ed0SSrinivas Kandagatla {0, 30, 30, 5}, 2273bcee7ed0SSrinivas Kandagatla {0, 30, 30, 5}, 2274bcee7ed0SSrinivas Kandagatla {0, 30, 30, 5}, 2275bcee7ed0SSrinivas Kandagatla }; 2276bcee7ed0SSrinivas Kandagatla s16 *d1 = NULL; 2277bcee7ed0SSrinivas Kandagatla 2278bcee7ed0SSrinivas Kandagatla reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5); 2279bcee7ed0SSrinivas Kandagatla reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6); 2280bcee7ed0SSrinivas Kandagatla reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7); 2281bcee7ed0SSrinivas Kandagatla reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK); 2282bcee7ed0SSrinivas Kandagatla reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL); 2283bcee7ed0SSrinivas Kandagatla 2284bcee7ed0SSrinivas Kandagatla if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) { 2285bcee7ed0SSrinivas Kandagatla is_fsm_disable = true; 2286bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2287bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ELECT, 0x80, 0x00); 2288bcee7ed0SSrinivas Kandagatla } 2289bcee7ed0SSrinivas Kandagatla 2290bcee7ed0SSrinivas Kandagatla /* For NO-jack, disable L_DET_EN before Z-det measurements */ 2291bcee7ed0SSrinivas Kandagatla if (wcd938x->mbhc_cfg.hphl_swh) 2292bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2293bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_MECH, 0x80, 0x00); 2294bcee7ed0SSrinivas Kandagatla 2295bcee7ed0SSrinivas Kandagatla /* Turn off 100k pull down on HPHL */ 2296bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2297bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_MECH, 0x01, 0x00); 2298bcee7ed0SSrinivas Kandagatla 2299bcee7ed0SSrinivas Kandagatla /* Disable surge protection before impedance detection. 2300bcee7ed0SSrinivas Kandagatla * This is done to give correct value for high impedance. 2301bcee7ed0SSrinivas Kandagatla */ 2302bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2303bcee7ed0SSrinivas Kandagatla WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); 2304bcee7ed0SSrinivas Kandagatla /* 1ms delay needed after disable surge protection */ 2305bcee7ed0SSrinivas Kandagatla usleep_range(1000, 1010); 2306bcee7ed0SSrinivas Kandagatla 2307bcee7ed0SSrinivas Kandagatla /* First get impedance on Left */ 2308bcee7ed0SSrinivas Kandagatla d1 = d1_a[1]; 2309bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[1]; 2310bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); 2311bcee7ed0SSrinivas Kandagatla 2312bcee7ed0SSrinivas Kandagatla if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L)) 2313bcee7ed0SSrinivas Kandagatla goto left_ch_impedance; 2314bcee7ed0SSrinivas Kandagatla 2315bcee7ed0SSrinivas Kandagatla /* Second ramp for left ch */ 2316bcee7ed0SSrinivas Kandagatla if (z1L < WCD938X_ZDET_VAL_32) { 2317bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[0]; 2318bcee7ed0SSrinivas Kandagatla d1 = d1_a[0]; 2319bcee7ed0SSrinivas Kandagatla } else if ((z1L > WCD938X_ZDET_VAL_400) && 2320bcee7ed0SSrinivas Kandagatla (z1L <= WCD938X_ZDET_VAL_1200)) { 2321bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[2]; 2322bcee7ed0SSrinivas Kandagatla d1 = d1_a[2]; 2323bcee7ed0SSrinivas Kandagatla } else if (z1L > WCD938X_ZDET_VAL_1200) { 2324bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[3]; 2325bcee7ed0SSrinivas Kandagatla d1 = d1_a[3]; 2326bcee7ed0SSrinivas Kandagatla } 2327bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); 2328bcee7ed0SSrinivas Kandagatla 2329bcee7ed0SSrinivas Kandagatla left_ch_impedance: 2330bcee7ed0SSrinivas Kandagatla if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) || 2331bcee7ed0SSrinivas Kandagatla (z1L > WCD938X_ZDET_VAL_100K)) { 2332bcee7ed0SSrinivas Kandagatla *zl = WCD938X_ZDET_FLOATING_IMPEDANCE; 2333bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[1]; 2334bcee7ed0SSrinivas Kandagatla d1 = d1_a[1]; 2335bcee7ed0SSrinivas Kandagatla } else { 2336bcee7ed0SSrinivas Kandagatla *zl = z1L/1000; 2337bcee7ed0SSrinivas Kandagatla wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0); 2338bcee7ed0SSrinivas Kandagatla } 2339bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n", 2340bcee7ed0SSrinivas Kandagatla __func__, *zl); 2341bcee7ed0SSrinivas Kandagatla 2342bcee7ed0SSrinivas Kandagatla /* Start of right impedance ramp and calculation */ 2343bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); 2344bcee7ed0SSrinivas Kandagatla if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) { 2345bcee7ed0SSrinivas Kandagatla if (((z1R > WCD938X_ZDET_VAL_1200) && 2346bcee7ed0SSrinivas Kandagatla (zdet_param_ptr->noff == 0x6)) || 2347bcee7ed0SSrinivas Kandagatla ((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE)) 2348bcee7ed0SSrinivas Kandagatla goto right_ch_impedance; 2349bcee7ed0SSrinivas Kandagatla /* Second ramp for right ch */ 2350bcee7ed0SSrinivas Kandagatla if (z1R < WCD938X_ZDET_VAL_32) { 2351bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[0]; 2352bcee7ed0SSrinivas Kandagatla d1 = d1_a[0]; 2353bcee7ed0SSrinivas Kandagatla } else if ((z1R > WCD938X_ZDET_VAL_400) && 2354bcee7ed0SSrinivas Kandagatla (z1R <= WCD938X_ZDET_VAL_1200)) { 2355bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[2]; 2356bcee7ed0SSrinivas Kandagatla d1 = d1_a[2]; 2357bcee7ed0SSrinivas Kandagatla } else if (z1R > WCD938X_ZDET_VAL_1200) { 2358bcee7ed0SSrinivas Kandagatla zdet_param_ptr = &zdet_param[3]; 2359bcee7ed0SSrinivas Kandagatla d1 = d1_a[3]; 2360bcee7ed0SSrinivas Kandagatla } 2361bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); 2362bcee7ed0SSrinivas Kandagatla } 2363bcee7ed0SSrinivas Kandagatla right_ch_impedance: 2364bcee7ed0SSrinivas Kandagatla if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) || 2365bcee7ed0SSrinivas Kandagatla (z1R > WCD938X_ZDET_VAL_100K)) { 2366bcee7ed0SSrinivas Kandagatla *zr = WCD938X_ZDET_FLOATING_IMPEDANCE; 2367bcee7ed0SSrinivas Kandagatla } else { 2368bcee7ed0SSrinivas Kandagatla *zr = z1R/1000; 2369bcee7ed0SSrinivas Kandagatla wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1); 2370bcee7ed0SSrinivas Kandagatla } 2371bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n", 2372bcee7ed0SSrinivas Kandagatla __func__, *zr); 2373bcee7ed0SSrinivas Kandagatla 2374bcee7ed0SSrinivas Kandagatla /* Mono/stereo detection */ 2375bcee7ed0SSrinivas Kandagatla if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) && 2376bcee7ed0SSrinivas Kandagatla (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) { 2377bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, 2378bcee7ed0SSrinivas Kandagatla "%s: plug type is invalid or extension cable\n", 2379bcee7ed0SSrinivas Kandagatla __func__); 2380bcee7ed0SSrinivas Kandagatla goto zdet_complete; 2381bcee7ed0SSrinivas Kandagatla } 2382bcee7ed0SSrinivas Kandagatla if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) || 2383bcee7ed0SSrinivas Kandagatla (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) || 2384bcee7ed0SSrinivas Kandagatla ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) || 2385bcee7ed0SSrinivas Kandagatla ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) { 2386bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, 2387bcee7ed0SSrinivas Kandagatla "%s: Mono plug type with one ch floating or shorted to GND\n", 2388bcee7ed0SSrinivas Kandagatla __func__); 2389bcee7ed0SSrinivas Kandagatla wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO); 2390bcee7ed0SSrinivas Kandagatla goto zdet_complete; 2391bcee7ed0SSrinivas Kandagatla } 2392bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST, 2393bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_OVR_MASK, 1); 2394bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, 2395bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_R_MASK, 1); 2396bcee7ed0SSrinivas Kandagatla if (*zl < (WCD938X_ZDET_VAL_32/1000)) 2397bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1); 2398bcee7ed0SSrinivas Kandagatla else 2399bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1); 2400bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, 2401bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_R_MASK, 0); 2402bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST, 2403bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_OVR_MASK, 0); 2404bcee7ed0SSrinivas Kandagatla z1Ls /= 1000; 2405bcee7ed0SSrinivas Kandagatla wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0); 2406bcee7ed0SSrinivas Kandagatla /* Parallel of left Z and 9 ohm pull down resistor */ 2407bcee7ed0SSrinivas Kandagatla zMono = ((*zl) * 9) / ((*zl) + 9); 2408bcee7ed0SSrinivas Kandagatla z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls); 2409bcee7ed0SSrinivas Kandagatla z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl)); 2410bcee7ed0SSrinivas Kandagatla if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) { 2411bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: stereo plug type detected\n", 2412bcee7ed0SSrinivas Kandagatla __func__); 2413bcee7ed0SSrinivas Kandagatla wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO); 2414bcee7ed0SSrinivas Kandagatla } else { 2415bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: MONO plug type detected\n", 2416bcee7ed0SSrinivas Kandagatla __func__); 2417bcee7ed0SSrinivas Kandagatla wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO); 2418bcee7ed0SSrinivas Kandagatla } 2419bcee7ed0SSrinivas Kandagatla 2420bcee7ed0SSrinivas Kandagatla /* Enable surge protection again after impedance detection */ 2421bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2422bcee7ed0SSrinivas Kandagatla WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); 2423bcee7ed0SSrinivas Kandagatla zdet_complete: 2424bcee7ed0SSrinivas Kandagatla snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0); 2425bcee7ed0SSrinivas Kandagatla snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1); 2426bcee7ed0SSrinivas Kandagatla snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2); 2427bcee7ed0SSrinivas Kandagatla /* Turn on 100k pull down on HPHL */ 2428bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2429bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_MECH, 0x01, 0x01); 2430bcee7ed0SSrinivas Kandagatla 2431bcee7ed0SSrinivas Kandagatla /* For NO-jack, re-enable L_DET_EN after Z-det measurements */ 2432bcee7ed0SSrinivas Kandagatla if (wcd938x->mbhc_cfg.hphl_swh) 2433bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2434bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_MECH, 0x80, 0x80); 2435bcee7ed0SSrinivas Kandagatla 2436bcee7ed0SSrinivas Kandagatla snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4); 2437bcee7ed0SSrinivas Kandagatla snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3); 2438bcee7ed0SSrinivas Kandagatla if (is_fsm_disable) 2439bcee7ed0SSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, 2440bcee7ed0SSrinivas Kandagatla WCD938X_ANA_MBHC_ELECT, 0x80, 0x80); 2441bcee7ed0SSrinivas Kandagatla } 2442bcee7ed0SSrinivas Kandagatla 2443bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component, 2444bcee7ed0SSrinivas Kandagatla bool enable) 2445bcee7ed0SSrinivas Kandagatla { 2446bcee7ed0SSrinivas Kandagatla if (enable) { 2447bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, 2448bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1); 2449bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, 2450bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_GND_DET_EN_MASK, 1); 2451bcee7ed0SSrinivas Kandagatla } else { 2452bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, 2453bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_GND_DET_EN_MASK, 0); 2454bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, 2455bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0); 2456bcee7ed0SSrinivas Kandagatla } 2457bcee7ed0SSrinivas Kandagatla } 2458bcee7ed0SSrinivas Kandagatla 2459bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, 2460bcee7ed0SSrinivas Kandagatla bool enable) 2461bcee7ed0SSrinivas Kandagatla { 2462bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, 2463bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_R_MASK, enable); 2464bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, 2465bcee7ed0SSrinivas Kandagatla WCD938X_HPHPA_GND_L_MASK, enable); 2466bcee7ed0SSrinivas Kandagatla } 2467bcee7ed0SSrinivas Kandagatla 2468bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_moisture_config(struct snd_soc_component *component) 2469bcee7ed0SSrinivas Kandagatla { 2470bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2471bcee7ed0SSrinivas Kandagatla 2472bcee7ed0SSrinivas Kandagatla if (wcd938x->mbhc_cfg.moist_rref == R_OFF) { 2473bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2474bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, R_OFF); 2475bcee7ed0SSrinivas Kandagatla return; 2476bcee7ed0SSrinivas Kandagatla } 2477bcee7ed0SSrinivas Kandagatla 2478bcee7ed0SSrinivas Kandagatla /* Do not enable moisture detection if jack type is NC */ 2479bcee7ed0SSrinivas Kandagatla if (!wcd938x->mbhc_cfg.hphl_swh) { 2480bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: disable moisture detection for NC\n", 2481bcee7ed0SSrinivas Kandagatla __func__); 2482bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2483bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, R_OFF); 2484bcee7ed0SSrinivas Kandagatla return; 2485bcee7ed0SSrinivas Kandagatla } 2486bcee7ed0SSrinivas Kandagatla 2487bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2488bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref); 2489bcee7ed0SSrinivas Kandagatla } 2490bcee7ed0SSrinivas Kandagatla 2491bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable) 2492bcee7ed0SSrinivas Kandagatla { 2493bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2494bcee7ed0SSrinivas Kandagatla 2495bcee7ed0SSrinivas Kandagatla if (enable) 2496bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2497bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref); 2498bcee7ed0SSrinivas Kandagatla else 2499bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2500bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, R_OFF); 2501bcee7ed0SSrinivas Kandagatla } 2502bcee7ed0SSrinivas Kandagatla 2503bcee7ed0SSrinivas Kandagatla static bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component) 2504bcee7ed0SSrinivas Kandagatla { 2505bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2506bcee7ed0SSrinivas Kandagatla bool ret = false; 2507bcee7ed0SSrinivas Kandagatla 2508bcee7ed0SSrinivas Kandagatla if (wcd938x->mbhc_cfg.moist_rref == R_OFF) { 2509bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2510bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, R_OFF); 2511bcee7ed0SSrinivas Kandagatla goto done; 2512bcee7ed0SSrinivas Kandagatla } 2513bcee7ed0SSrinivas Kandagatla 2514bcee7ed0SSrinivas Kandagatla /* Do not enable moisture detection if jack type is NC */ 2515bcee7ed0SSrinivas Kandagatla if (!wcd938x->mbhc_cfg.hphl_swh) { 2516bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: disable moisture detection for NC\n", 2517bcee7ed0SSrinivas Kandagatla __func__); 2518bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, 2519bcee7ed0SSrinivas Kandagatla WCD938X_M_RTH_CTL_MASK, R_OFF); 2520bcee7ed0SSrinivas Kandagatla goto done; 2521bcee7ed0SSrinivas Kandagatla } 2522bcee7ed0SSrinivas Kandagatla 2523bcee7ed0SSrinivas Kandagatla /* 2524bcee7ed0SSrinivas Kandagatla * If moisture_en is already enabled, then skip to plug type 2525bcee7ed0SSrinivas Kandagatla * detection. 2526bcee7ed0SSrinivas Kandagatla */ 2527bcee7ed0SSrinivas Kandagatla if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK)) 2528bcee7ed0SSrinivas Kandagatla goto done; 2529bcee7ed0SSrinivas Kandagatla 2530bcee7ed0SSrinivas Kandagatla wcd938x_mbhc_moisture_detect_en(component, true); 2531bcee7ed0SSrinivas Kandagatla /* Read moisture comparator status */ 2532bcee7ed0SSrinivas Kandagatla ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS) 2533bcee7ed0SSrinivas Kandagatla & 0x20) ? 0 : 1); 2534bcee7ed0SSrinivas Kandagatla 2535bcee7ed0SSrinivas Kandagatla done: 2536bcee7ed0SSrinivas Kandagatla return ret; 2537bcee7ed0SSrinivas Kandagatla 2538bcee7ed0SSrinivas Kandagatla } 2539bcee7ed0SSrinivas Kandagatla 2540bcee7ed0SSrinivas Kandagatla static void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component, 2541bcee7ed0SSrinivas Kandagatla bool enable) 2542bcee7ed0SSrinivas Kandagatla { 2543bcee7ed0SSrinivas Kandagatla snd_soc_component_write_field(component, 2544bcee7ed0SSrinivas Kandagatla WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 2545bcee7ed0SSrinivas Kandagatla WCD938X_MOISTURE_EN_POLLING_MASK, enable); 2546bcee7ed0SSrinivas Kandagatla } 2547bcee7ed0SSrinivas Kandagatla 2548bcee7ed0SSrinivas Kandagatla static const struct wcd_mbhc_cb mbhc_cb = { 2549bcee7ed0SSrinivas Kandagatla .clk_setup = wcd938x_mbhc_clk_setup, 2550bcee7ed0SSrinivas Kandagatla .mbhc_bias = wcd938x_mbhc_mbhc_bias_control, 2551bcee7ed0SSrinivas Kandagatla .set_btn_thr = wcd938x_mbhc_program_btn_thr, 2552bcee7ed0SSrinivas Kandagatla .micbias_enable_status = wcd938x_mbhc_micb_en_status, 2553bcee7ed0SSrinivas Kandagatla .hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control, 2554bcee7ed0SSrinivas Kandagatla .mbhc_micbias_control = wcd938x_mbhc_request_micbias, 2555bcee7ed0SSrinivas Kandagatla .mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control, 2556bcee7ed0SSrinivas Kandagatla .mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic, 2557bcee7ed0SSrinivas Kandagatla .compute_impedance = wcd938x_wcd_mbhc_calc_impedance, 2558bcee7ed0SSrinivas Kandagatla .mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl, 2559bcee7ed0SSrinivas Kandagatla .hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl, 2560bcee7ed0SSrinivas Kandagatla .mbhc_moisture_config = wcd938x_mbhc_moisture_config, 2561bcee7ed0SSrinivas Kandagatla .mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status, 2562bcee7ed0SSrinivas Kandagatla .mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl, 2563bcee7ed0SSrinivas Kandagatla .mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en, 2564bcee7ed0SSrinivas Kandagatla }; 2565bcee7ed0SSrinivas Kandagatla 2566bcee7ed0SSrinivas Kandagatla static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol, 2567bcee7ed0SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 2568bcee7ed0SSrinivas Kandagatla { 2569bcee7ed0SSrinivas Kandagatla struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2570bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2571bcee7ed0SSrinivas Kandagatla 2572bcee7ed0SSrinivas Kandagatla ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc); 2573bcee7ed0SSrinivas Kandagatla 2574bcee7ed0SSrinivas Kandagatla return 0; 2575bcee7ed0SSrinivas Kandagatla } 2576bcee7ed0SSrinivas Kandagatla 2577bcee7ed0SSrinivas Kandagatla static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol, 2578bcee7ed0SSrinivas Kandagatla struct snd_ctl_elem_value *ucontrol) 2579bcee7ed0SSrinivas Kandagatla { 2580bcee7ed0SSrinivas Kandagatla uint32_t zl, zr; 2581bcee7ed0SSrinivas Kandagatla bool hphr; 2582bcee7ed0SSrinivas Kandagatla struct soc_mixer_control *mc; 2583bcee7ed0SSrinivas Kandagatla struct snd_soc_component *component = 2584bcee7ed0SSrinivas Kandagatla snd_soc_kcontrol_component(kcontrol); 2585bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2586bcee7ed0SSrinivas Kandagatla 2587bcee7ed0SSrinivas Kandagatla mc = (struct soc_mixer_control *)(kcontrol->private_value); 2588bcee7ed0SSrinivas Kandagatla hphr = mc->shift; 2589bcee7ed0SSrinivas Kandagatla wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr); 2590bcee7ed0SSrinivas Kandagatla dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr); 2591bcee7ed0SSrinivas Kandagatla ucontrol->value.integer.value[0] = hphr ? zr : zl; 2592bcee7ed0SSrinivas Kandagatla 2593bcee7ed0SSrinivas Kandagatla return 0; 2594bcee7ed0SSrinivas Kandagatla } 2595bcee7ed0SSrinivas Kandagatla 2596bcee7ed0SSrinivas Kandagatla static const struct snd_kcontrol_new hph_type_detect_controls[] = { 2597b0217519SSrinivas Kandagatla SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0, 2598bcee7ed0SSrinivas Kandagatla wcd938x_get_hph_type, NULL), 2599bcee7ed0SSrinivas Kandagatla }; 2600bcee7ed0SSrinivas Kandagatla 2601bcee7ed0SSrinivas Kandagatla static const struct snd_kcontrol_new impedance_detect_controls[] = { 2602b0217519SSrinivas Kandagatla SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0, 2603bcee7ed0SSrinivas Kandagatla wcd938x_hph_impedance_get, NULL), 2604b0217519SSrinivas Kandagatla SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0, 2605bcee7ed0SSrinivas Kandagatla wcd938x_hph_impedance_get, NULL), 2606bcee7ed0SSrinivas Kandagatla }; 2607bcee7ed0SSrinivas Kandagatla 2608bcee7ed0SSrinivas Kandagatla static int wcd938x_mbhc_init(struct snd_soc_component *component) 2609bcee7ed0SSrinivas Kandagatla { 2610bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 2611bcee7ed0SSrinivas Kandagatla struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids; 2612bcee7ed0SSrinivas Kandagatla 2613bcee7ed0SSrinivas Kandagatla intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip, 2614bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_MBHC_SW_DET); 2615bcee7ed0SSrinivas Kandagatla intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip, 2616bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_MBHC_BUTTON_PRESS_DET); 2617bcee7ed0SSrinivas Kandagatla intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip, 2618bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET); 2619bcee7ed0SSrinivas Kandagatla intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip, 2620bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET); 2621bcee7ed0SSrinivas Kandagatla intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip, 2622bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_MBHC_ELECT_INS_REM_DET); 2623bcee7ed0SSrinivas Kandagatla intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip, 2624bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_HPHL_OCP_INT); 2625bcee7ed0SSrinivas Kandagatla intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip, 2626bcee7ed0SSrinivas Kandagatla WCD938X_IRQ_HPHR_OCP_INT); 2627bcee7ed0SSrinivas Kandagatla 2628bcee7ed0SSrinivas Kandagatla wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true); 2629bcee7ed0SSrinivas Kandagatla 2630bcee7ed0SSrinivas Kandagatla snd_soc_add_component_controls(component, impedance_detect_controls, 2631bcee7ed0SSrinivas Kandagatla ARRAY_SIZE(impedance_detect_controls)); 2632bcee7ed0SSrinivas Kandagatla snd_soc_add_component_controls(component, hph_type_detect_controls, 2633bcee7ed0SSrinivas Kandagatla ARRAY_SIZE(hph_type_detect_controls)); 2634bcee7ed0SSrinivas Kandagatla 2635bcee7ed0SSrinivas Kandagatla return 0; 2636bcee7ed0SSrinivas Kandagatla } 2637bcee7ed0SSrinivas Kandagatla /* END MBHC */ 2638bcee7ed0SSrinivas Kandagatla 2639e8ba1e05SSrinivas Kandagatla static const struct snd_kcontrol_new wcd938x_snd_controls[] = { 2640e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0, 2641e8ba1e05SSrinivas Kandagatla wcd938x_get_compander, wcd938x_set_compander), 2642e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("HPHR_COMP Switch", WCD938X_COMP_R, 1, 1, 0, 2643e8ba1e05SSrinivas Kandagatla wcd938x_get_compander, wcd938x_set_compander), 2644e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("HPHL Switch", WCD938X_HPH_L, 0, 1, 0, 2645e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2646e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("HPHR Switch", WCD938X_HPH_R, 0, 1, 0, 2647e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2648e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("CLSH Switch", WCD938X_CLSH, 0, 1, 0, 2649e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2650e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("LO Switch", WCD938X_LO, 0, 1, 0, 2651e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2652e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DSD_L Switch", WCD938X_DSD_L, 0, 1, 0, 2653e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2654e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DSD_R Switch", WCD938X_DSD_R, 0, 1, 0, 2655e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2656e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 0, line_gain), 2657e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 0, line_gain), 2658e8ba1e05SSrinivas Kandagatla WCD938X_EAR_PA_GAIN_TLV("EAR_PA Volume", WCD938X_ANA_EAR_COMPANDER_CTL, 2659e8ba1e05SSrinivas Kandagatla 2, 0x10, 0, ear_pa_gain), 2660e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("ADC1 Switch", WCD938X_ADC1, 1, 1, 0, 2661e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2662e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("ADC2 Switch", WCD938X_ADC2, 1, 1, 0, 2663e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2664e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("ADC3 Switch", WCD938X_ADC3, 1, 1, 0, 2665e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2666e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("ADC4 Switch", WCD938X_ADC4, 1, 1, 0, 2667e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2668e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC0 Switch", WCD938X_DMIC0, 1, 1, 0, 2669e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2670e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC1 Switch", WCD938X_DMIC1, 1, 1, 0, 2671e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2672e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("MBHC Switch", WCD938X_MBHC, 1, 1, 0, 2673e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2674e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC2 Switch", WCD938X_DMIC2, 1, 1, 0, 2675e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2676e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC3 Switch", WCD938X_DMIC3, 1, 1, 0, 2677e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2678e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC4 Switch", WCD938X_DMIC4, 1, 1, 0, 2679e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2680e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC5 Switch", WCD938X_DMIC5, 1, 1, 0, 2681e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2682e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC6 Switch", WCD938X_DMIC6, 1, 1, 0, 2683e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2684e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("DMIC7 Switch", WCD938X_DMIC7, 1, 1, 0, 2685e8ba1e05SSrinivas Kandagatla wcd938x_get_swr_port, wcd938x_set_swr_port), 2686e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("LDOH Enable Switch", SND_SOC_NOPM, 0, 1, 0, 2687e8ba1e05SSrinivas Kandagatla wcd938x_ldoh_get, wcd938x_ldoh_put), 2688e8ba1e05SSrinivas Kandagatla SOC_SINGLE_EXT("ADC2_BCS Disable Switch", SND_SOC_NOPM, 0, 1, 0, 2689e8ba1e05SSrinivas Kandagatla wcd938x_bcs_get, wcd938x_bcs_put), 2690e8ba1e05SSrinivas Kandagatla 2691e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0, analog_gain), 2692e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("ADC2 Volume", WCD938X_ANA_TX_CH2, 0, 20, 0, analog_gain), 2693e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("ADC3 Volume", WCD938X_ANA_TX_CH3, 0, 20, 0, analog_gain), 2694e8ba1e05SSrinivas Kandagatla SOC_SINGLE_TLV("ADC4 Volume", WCD938X_ANA_TX_CH4, 0, 20, 0, analog_gain), 2695e8ba1e05SSrinivas Kandagatla }; 2696e8ba1e05SSrinivas Kandagatla 26978da9db0cSSrinivas Kandagatla static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = { 2698d5add08fSSrinivas Kandagatla 2699d5add08fSSrinivas Kandagatla /*input widgets*/ 2700d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC1"), 2701d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC2"), 2702d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC3"), 2703d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC4"), 2704d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC5"), 2705d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC6"), 2706d5add08fSSrinivas Kandagatla SND_SOC_DAPM_INPUT("AMIC7"), 2707d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIC("Analog Mic1", NULL), 2708d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIC("Analog Mic2", NULL), 2709d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIC("Analog Mic3", NULL), 2710d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIC("Analog Mic4", NULL), 2711d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIC("Analog Mic5", NULL), 2712d5add08fSSrinivas Kandagatla 2713d5add08fSSrinivas Kandagatla /*tx widgets*/ 2714d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, 2715d5add08fSSrinivas Kandagatla wcd938x_codec_enable_adc, 2716d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2717d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0, 2718d5add08fSSrinivas Kandagatla wcd938x_codec_enable_adc, 2719d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2720d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 2, 0, 2721d5add08fSSrinivas Kandagatla wcd938x_codec_enable_adc, 2722d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2723d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("ADC4", NULL, SND_SOC_NOPM, 3, 0, 2724d5add08fSSrinivas Kandagatla wcd938x_codec_enable_adc, 2725d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2726d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0, 2727d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2728d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2729d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0, 2730d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2731d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2732d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 2, 0, 2733d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2734d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2735d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 3, 0, 2736d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2737d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2738d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 4, 0, 2739d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2740d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2741d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 5, 0, 2742d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2743d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2744d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC7", NULL, SND_SOC_NOPM, 6, 0, 2745d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2746d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2747d5add08fSSrinivas Kandagatla SND_SOC_DAPM_ADC_E("DMIC8", NULL, SND_SOC_NOPM, 7, 0, 2748d5add08fSSrinivas Kandagatla wcd938x_codec_enable_dmic, 2749d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2750d5add08fSSrinivas Kandagatla 2751d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0, 2752d5add08fSSrinivas Kandagatla NULL, 0, wcd938x_adc_enable_req, 2753d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2754d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 1, 0, 2755d5add08fSSrinivas Kandagatla NULL, 0, wcd938x_adc_enable_req, 2756d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2757d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 2, 0, 2758d5add08fSSrinivas Kandagatla NULL, 0, wcd938x_adc_enable_req, 2759d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2760d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC4 REQ", SND_SOC_NOPM, 3, 0, NULL, 0, 2761d5add08fSSrinivas Kandagatla wcd938x_adc_enable_req, 2762d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2763d5add08fSSrinivas Kandagatla 2764d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux), 2765d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MUX("ADC3 MUX", SND_SOC_NOPM, 0, 0, &tx_adc3_mux), 2766d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0, &tx_adc4_mux), 2767d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MUX("HDR12 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr12_mux), 2768d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MUX("HDR34 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr34_mux), 2769d5add08fSSrinivas Kandagatla 2770d5add08fSSrinivas Kandagatla /*tx mixers*/ 2771d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch, 2772d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc1_switch), wcd938x_tx_swr_ctrl, 2773d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2774d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0, adc2_switch, 2775d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc2_switch), wcd938x_tx_swr_ctrl, 2776d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2777d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch, 2778d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc3_switch), wcd938x_tx_swr_ctrl, 2779d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2780d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("ADC4_MIXER", SND_SOC_NOPM, 0, 0, adc4_switch, 2781d5add08fSSrinivas Kandagatla ARRAY_SIZE(adc4_switch), wcd938x_tx_swr_ctrl, 2782d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2783d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch, 2784d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic1_switch), wcd938x_tx_swr_ctrl, 2785d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2786d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0, 0, dmic2_switch, 2787d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic2_switch), wcd938x_tx_swr_ctrl, 2788d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2789d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0, 0, dmic3_switch, 2790d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic3_switch), wcd938x_tx_swr_ctrl, 2791d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2792d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0, 0, dmic4_switch, 2793d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic4_switch), wcd938x_tx_swr_ctrl, 2794d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2795d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0, 0, dmic5_switch, 2796d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic5_switch), wcd938x_tx_swr_ctrl, 2797d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2798d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0, 0, dmic6_switch, 2799d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic6_switch), wcd938x_tx_swr_ctrl, 2800d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2801d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC7_MIXER", SND_SOC_NOPM, 0, 0, dmic7_switch, 2802d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic7_switch), wcd938x_tx_swr_ctrl, 2803d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2804d5add08fSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("DMIC8_MIXER", SND_SOC_NOPM, 0, 0, dmic8_switch, 2805d5add08fSSrinivas Kandagatla ARRAY_SIZE(dmic8_switch), wcd938x_tx_swr_ctrl, 2806d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2807d5add08fSSrinivas Kandagatla /* micbias widgets*/ 2808d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, 2809d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias, 2810d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2811d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2812d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, 2813d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias, 2814d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2815d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2816d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, 2817d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias, 2818d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2819d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2820d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0, 2821d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias, 2822d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2823d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2824d5add08fSSrinivas Kandagatla 2825d5add08fSSrinivas Kandagatla /* micbias pull up widgets*/ 2826d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, 2827d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias_pullup, 2828d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2829d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2830d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, 2831d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias_pullup, 2832d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2833d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2834d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, 2835d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias_pullup, 2836d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2837d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2838d5add08fSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("VA MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0, 2839d5add08fSSrinivas Kandagatla wcd938x_codec_enable_micbias_pullup, 2840d5add08fSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2841d5add08fSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 2842d5add08fSSrinivas Kandagatla 2843d5add08fSSrinivas Kandagatla /*output widgets tx*/ 2844d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"), 2845d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"), 2846d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"), 2847d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("ADC4_OUTPUT"), 2848d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"), 2849d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"), 2850d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"), 2851d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"), 2852d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"), 2853d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"), 2854d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC7_OUTPUT"), 2855d5add08fSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("DMIC8_OUTPUT"), 2856d5add08fSSrinivas Kandagatla 28578da9db0cSSrinivas Kandagatla SND_SOC_DAPM_INPUT("IN1_HPHL"), 28588da9db0cSSrinivas Kandagatla SND_SOC_DAPM_INPUT("IN2_HPHR"), 28598da9db0cSSrinivas Kandagatla SND_SOC_DAPM_INPUT("IN3_AUX"), 28608da9db0cSSrinivas Kandagatla 28618da9db0cSSrinivas Kandagatla /*rx widgets*/ 28628da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PGA_E("EAR PGA", WCD938X_ANA_EAR, 7, 0, NULL, 0, 28638da9db0cSSrinivas Kandagatla wcd938x_codec_enable_ear_pa, 28648da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28658da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28668da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PGA_E("AUX PGA", WCD938X_AUX_AUXPA, 7, 0, NULL, 0, 28678da9db0cSSrinivas Kandagatla wcd938x_codec_enable_aux_pa, 28688da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28698da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28708da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PGA_E("HPHL PGA", WCD938X_ANA_HPH, 7, 0, NULL, 0, 28718da9db0cSSrinivas Kandagatla wcd938x_codec_enable_hphl_pa, 28728da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28738da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28748da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PGA_E("HPHR PGA", WCD938X_ANA_HPH, 6, 0, NULL, 0, 28758da9db0cSSrinivas Kandagatla wcd938x_codec_enable_hphr_pa, 28768da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28778da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28788da9db0cSSrinivas Kandagatla 28798da9db0cSSrinivas Kandagatla SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0, 28808da9db0cSSrinivas Kandagatla wcd938x_codec_hphl_dac_event, 28818da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28828da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28838da9db0cSSrinivas Kandagatla SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0, 28848da9db0cSSrinivas Kandagatla wcd938x_codec_hphr_dac_event, 28858da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28868da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28878da9db0cSSrinivas Kandagatla SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0, 28888da9db0cSSrinivas Kandagatla wcd938x_codec_ear_dac_event, 28898da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28908da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28918da9db0cSSrinivas Kandagatla SND_SOC_DAPM_DAC_E("RDAC4", NULL, SND_SOC_NOPM, 0, 0, 28928da9db0cSSrinivas Kandagatla wcd938x_codec_aux_dac_event, 28938da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 28948da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 28958da9db0cSSrinivas Kandagatla 28968da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux), 28978da9db0cSSrinivas Kandagatla 28988da9db0cSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0, NULL, 0), 28998da9db0cSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY("RXCLK", SND_SOC_NOPM, 0, 0, 29008da9db0cSSrinivas Kandagatla wcd938x_codec_enable_rxclk, 29018da9db0cSSrinivas Kandagatla SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 29028da9db0cSSrinivas Kandagatla SND_SOC_DAPM_POST_PMD), 29038da9db0cSSrinivas Kandagatla 29048da9db0cSSrinivas Kandagatla SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0, NULL, 0), 29058da9db0cSSrinivas Kandagatla 29068da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), 29078da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), 29088da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), 29098da9db0cSSrinivas Kandagatla 29108da9db0cSSrinivas Kandagatla /* rx mixer widgets*/ 29118da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0, 29128da9db0cSSrinivas Kandagatla ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)), 29138da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER("AUX_RDAC", SND_SOC_NOPM, 0, 0, 29148da9db0cSSrinivas Kandagatla aux_rdac_switch, ARRAY_SIZE(aux_rdac_switch)), 29158da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0, 29168da9db0cSSrinivas Kandagatla hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)), 29178da9db0cSSrinivas Kandagatla SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0, 29188da9db0cSSrinivas Kandagatla hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)), 29198da9db0cSSrinivas Kandagatla 29208da9db0cSSrinivas Kandagatla /*output widgets rx*/ 29218da9db0cSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("EAR"), 29228da9db0cSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("AUX"), 29238da9db0cSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("HPHL"), 29248da9db0cSSrinivas Kandagatla SND_SOC_DAPM_OUTPUT("HPHR"), 292504544222SSrinivas Kandagatla 292604544222SSrinivas Kandagatla }; 292704544222SSrinivas Kandagatla 292804544222SSrinivas Kandagatla static const struct snd_soc_dapm_route wcd938x_audio_map[] = { 292904544222SSrinivas Kandagatla {"ADC1_OUTPUT", NULL, "ADC1_MIXER"}, 293004544222SSrinivas Kandagatla {"ADC1_MIXER", "Switch", "ADC1 REQ"}, 293104544222SSrinivas Kandagatla {"ADC1 REQ", NULL, "ADC1"}, 293204544222SSrinivas Kandagatla {"ADC1", NULL, "AMIC1"}, 293304544222SSrinivas Kandagatla 293404544222SSrinivas Kandagatla {"ADC2_OUTPUT", NULL, "ADC2_MIXER"}, 293504544222SSrinivas Kandagatla {"ADC2_MIXER", "Switch", "ADC2 REQ"}, 293604544222SSrinivas Kandagatla {"ADC2 REQ", NULL, "ADC2"}, 293704544222SSrinivas Kandagatla {"ADC2", NULL, "HDR12 MUX"}, 293804544222SSrinivas Kandagatla {"HDR12 MUX", "NO_HDR12", "ADC2 MUX"}, 293904544222SSrinivas Kandagatla {"HDR12 MUX", "HDR12", "AMIC1"}, 294004544222SSrinivas Kandagatla {"ADC2 MUX", "INP3", "AMIC3"}, 294104544222SSrinivas Kandagatla {"ADC2 MUX", "INP2", "AMIC2"}, 294204544222SSrinivas Kandagatla 294304544222SSrinivas Kandagatla {"ADC3_OUTPUT", NULL, "ADC3_MIXER"}, 294404544222SSrinivas Kandagatla {"ADC3_MIXER", "Switch", "ADC3 REQ"}, 294504544222SSrinivas Kandagatla {"ADC3 REQ", NULL, "ADC3"}, 294604544222SSrinivas Kandagatla {"ADC3", NULL, "HDR34 MUX"}, 294704544222SSrinivas Kandagatla {"HDR34 MUX", "NO_HDR34", "ADC3 MUX"}, 294804544222SSrinivas Kandagatla {"HDR34 MUX", "HDR34", "AMIC5"}, 294904544222SSrinivas Kandagatla {"ADC3 MUX", "INP4", "AMIC4"}, 295004544222SSrinivas Kandagatla {"ADC3 MUX", "INP6", "AMIC6"}, 295104544222SSrinivas Kandagatla 295204544222SSrinivas Kandagatla {"ADC4_OUTPUT", NULL, "ADC4_MIXER"}, 295304544222SSrinivas Kandagatla {"ADC4_MIXER", "Switch", "ADC4 REQ"}, 295404544222SSrinivas Kandagatla {"ADC4 REQ", NULL, "ADC4"}, 295504544222SSrinivas Kandagatla {"ADC4", NULL, "ADC4 MUX"}, 295604544222SSrinivas Kandagatla {"ADC4 MUX", "INP5", "AMIC5"}, 295704544222SSrinivas Kandagatla {"ADC4 MUX", "INP7", "AMIC7"}, 295804544222SSrinivas Kandagatla 295904544222SSrinivas Kandagatla {"DMIC1_OUTPUT", NULL, "DMIC1_MIXER"}, 296004544222SSrinivas Kandagatla {"DMIC1_MIXER", "Switch", "DMIC1"}, 296104544222SSrinivas Kandagatla 296204544222SSrinivas Kandagatla {"DMIC2_OUTPUT", NULL, "DMIC2_MIXER"}, 296304544222SSrinivas Kandagatla {"DMIC2_MIXER", "Switch", "DMIC2"}, 296404544222SSrinivas Kandagatla 296504544222SSrinivas Kandagatla {"DMIC3_OUTPUT", NULL, "DMIC3_MIXER"}, 296604544222SSrinivas Kandagatla {"DMIC3_MIXER", "Switch", "DMIC3"}, 296704544222SSrinivas Kandagatla 296804544222SSrinivas Kandagatla {"DMIC4_OUTPUT", NULL, "DMIC4_MIXER"}, 296904544222SSrinivas Kandagatla {"DMIC4_MIXER", "Switch", "DMIC4"}, 297004544222SSrinivas Kandagatla 297104544222SSrinivas Kandagatla {"DMIC5_OUTPUT", NULL, "DMIC5_MIXER"}, 297204544222SSrinivas Kandagatla {"DMIC5_MIXER", "Switch", "DMIC5"}, 297304544222SSrinivas Kandagatla 297404544222SSrinivas Kandagatla {"DMIC6_OUTPUT", NULL, "DMIC6_MIXER"}, 297504544222SSrinivas Kandagatla {"DMIC6_MIXER", "Switch", "DMIC6"}, 297604544222SSrinivas Kandagatla 297704544222SSrinivas Kandagatla {"DMIC7_OUTPUT", NULL, "DMIC7_MIXER"}, 297804544222SSrinivas Kandagatla {"DMIC7_MIXER", "Switch", "DMIC7"}, 297904544222SSrinivas Kandagatla 298004544222SSrinivas Kandagatla {"DMIC8_OUTPUT", NULL, "DMIC8_MIXER"}, 298104544222SSrinivas Kandagatla {"DMIC8_MIXER", "Switch", "DMIC8"}, 298204544222SSrinivas Kandagatla 298304544222SSrinivas Kandagatla {"IN1_HPHL", NULL, "VDD_BUCK"}, 298404544222SSrinivas Kandagatla {"IN1_HPHL", NULL, "CLS_H_PORT"}, 298504544222SSrinivas Kandagatla 298604544222SSrinivas Kandagatla {"RX1", NULL, "IN1_HPHL"}, 298704544222SSrinivas Kandagatla {"RX1", NULL, "RXCLK"}, 298804544222SSrinivas Kandagatla {"RDAC1", NULL, "RX1"}, 298904544222SSrinivas Kandagatla {"HPHL_RDAC", "Switch", "RDAC1"}, 299004544222SSrinivas Kandagatla {"HPHL PGA", NULL, "HPHL_RDAC"}, 299104544222SSrinivas Kandagatla {"HPHL", NULL, "HPHL PGA"}, 299204544222SSrinivas Kandagatla 299304544222SSrinivas Kandagatla {"IN2_HPHR", NULL, "VDD_BUCK"}, 299404544222SSrinivas Kandagatla {"IN2_HPHR", NULL, "CLS_H_PORT"}, 299504544222SSrinivas Kandagatla {"RX2", NULL, "IN2_HPHR"}, 299604544222SSrinivas Kandagatla {"RDAC2", NULL, "RX2"}, 299704544222SSrinivas Kandagatla {"RX2", NULL, "RXCLK"}, 299804544222SSrinivas Kandagatla {"HPHR_RDAC", "Switch", "RDAC2"}, 299904544222SSrinivas Kandagatla {"HPHR PGA", NULL, "HPHR_RDAC"}, 300004544222SSrinivas Kandagatla {"HPHR", NULL, "HPHR PGA"}, 300104544222SSrinivas Kandagatla 300204544222SSrinivas Kandagatla {"IN3_AUX", NULL, "VDD_BUCK"}, 300304544222SSrinivas Kandagatla {"IN3_AUX", NULL, "CLS_H_PORT"}, 300404544222SSrinivas Kandagatla {"RX3", NULL, "IN3_AUX"}, 300504544222SSrinivas Kandagatla {"RDAC4", NULL, "RX3"}, 300604544222SSrinivas Kandagatla {"RX3", NULL, "RXCLK"}, 300704544222SSrinivas Kandagatla {"AUX_RDAC", "Switch", "RDAC4"}, 300804544222SSrinivas Kandagatla {"AUX PGA", NULL, "AUX_RDAC"}, 300904544222SSrinivas Kandagatla {"AUX", NULL, "AUX PGA"}, 301004544222SSrinivas Kandagatla 301104544222SSrinivas Kandagatla {"RDAC3_MUX", "RX3", "RX3"}, 301204544222SSrinivas Kandagatla {"RDAC3_MUX", "RX1", "RX1"}, 301304544222SSrinivas Kandagatla {"RDAC3", NULL, "RDAC3_MUX"}, 301404544222SSrinivas Kandagatla {"EAR_RDAC", "Switch", "RDAC3"}, 301504544222SSrinivas Kandagatla {"EAR PGA", NULL, "EAR_RDAC"}, 301604544222SSrinivas Kandagatla {"EAR", NULL, "EAR PGA"}, 30178da9db0cSSrinivas Kandagatla }; 30188da9db0cSSrinivas Kandagatla 30198d78602aSSrinivas Kandagatla static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x) 30208d78602aSSrinivas Kandagatla { 30218d78602aSSrinivas Kandagatla int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4; 30228d78602aSSrinivas Kandagatla 30238d78602aSSrinivas Kandagatla /* set micbias voltage */ 30248d78602aSSrinivas Kandagatla vout_ctl_1 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb1_mv); 30258d78602aSSrinivas Kandagatla vout_ctl_2 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb2_mv); 30268d78602aSSrinivas Kandagatla vout_ctl_3 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb3_mv); 30278d78602aSSrinivas Kandagatla vout_ctl_4 = wcd938x_get_micb_vout_ctl_val(wcd938x->micb4_mv); 30288d78602aSSrinivas Kandagatla if (vout_ctl_1 < 0 || vout_ctl_2 < 0 || vout_ctl_3 < 0 || vout_ctl_4 < 0) 30298d78602aSSrinivas Kandagatla return -EINVAL; 30308d78602aSSrinivas Kandagatla 30318d78602aSSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB1, 30328d78602aSSrinivas Kandagatla WCD938X_MICB_VOUT_MASK, vout_ctl_1); 30338d78602aSSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB2, 30348d78602aSSrinivas Kandagatla WCD938X_MICB_VOUT_MASK, vout_ctl_2); 30358d78602aSSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB3, 30368d78602aSSrinivas Kandagatla WCD938X_MICB_VOUT_MASK, vout_ctl_3); 30378d78602aSSrinivas Kandagatla regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MICB4, 30388d78602aSSrinivas Kandagatla WCD938X_MICB_VOUT_MASK, vout_ctl_4); 30398d78602aSSrinivas Kandagatla 30408d78602aSSrinivas Kandagatla return 0; 30418d78602aSSrinivas Kandagatla } 30428d78602aSSrinivas Kandagatla 30438d78602aSSrinivas Kandagatla static irqreturn_t wcd938x_wd_handle_irq(int irq, void *data) 30448d78602aSSrinivas Kandagatla { 30458d78602aSSrinivas Kandagatla return IRQ_HANDLED; 30468d78602aSSrinivas Kandagatla } 30478d78602aSSrinivas Kandagatla 30488d78602aSSrinivas Kandagatla static struct irq_chip wcd_irq_chip = { 30498d78602aSSrinivas Kandagatla .name = "WCD938x", 30508d78602aSSrinivas Kandagatla }; 30518d78602aSSrinivas Kandagatla 30528d78602aSSrinivas Kandagatla static int wcd_irq_chip_map(struct irq_domain *irqd, unsigned int virq, 30538d78602aSSrinivas Kandagatla irq_hw_number_t hw) 30548d78602aSSrinivas Kandagatla { 30558d78602aSSrinivas Kandagatla irq_set_chip_and_handler(virq, &wcd_irq_chip, handle_simple_irq); 30568d78602aSSrinivas Kandagatla irq_set_nested_thread(virq, 1); 30578d78602aSSrinivas Kandagatla irq_set_noprobe(virq); 30588d78602aSSrinivas Kandagatla 30598d78602aSSrinivas Kandagatla return 0; 30608d78602aSSrinivas Kandagatla } 30618d78602aSSrinivas Kandagatla 30628d78602aSSrinivas Kandagatla static const struct irq_domain_ops wcd_domain_ops = { 30638d78602aSSrinivas Kandagatla .map = wcd_irq_chip_map, 30648d78602aSSrinivas Kandagatla }; 30658d78602aSSrinivas Kandagatla 30668d78602aSSrinivas Kandagatla static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev) 30678d78602aSSrinivas Kandagatla { 30688d78602aSSrinivas Kandagatla 30698d78602aSSrinivas Kandagatla wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); 30708d78602aSSrinivas Kandagatla if (!(wcd->virq)) { 30718d78602aSSrinivas Kandagatla dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); 30728d78602aSSrinivas Kandagatla return -EINVAL; 30738d78602aSSrinivas Kandagatla } 30748d78602aSSrinivas Kandagatla 30758d78602aSSrinivas Kandagatla return devm_regmap_add_irq_chip(dev, wcd->regmap, 30768d78602aSSrinivas Kandagatla irq_create_mapping(wcd->virq, 0), 30778d78602aSSrinivas Kandagatla IRQF_ONESHOT, 0, &wcd938x_regmap_irq_chip, 30788d78602aSSrinivas Kandagatla &wcd->irq_chip); 30798d78602aSSrinivas Kandagatla } 30808d78602aSSrinivas Kandagatla 30818d78602aSSrinivas Kandagatla static int wcd938x_soc_codec_probe(struct snd_soc_component *component) 30828d78602aSSrinivas Kandagatla { 30838d78602aSSrinivas Kandagatla struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 3084*6f492568SJohan Hovold struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev; 30858d78602aSSrinivas Kandagatla struct device *dev = component->dev; 3086*6f492568SJohan Hovold unsigned long time_left; 30878d78602aSSrinivas Kandagatla int ret, i; 30888d78602aSSrinivas Kandagatla 3089*6f492568SJohan Hovold time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, 3090*6f492568SJohan Hovold msecs_to_jiffies(2000)); 3091*6f492568SJohan Hovold if (!time_left) { 3092*6f492568SJohan Hovold dev_err(dev, "soundwire device init timeout\n"); 3093*6f492568SJohan Hovold return -ETIMEDOUT; 3094*6f492568SJohan Hovold } 3095*6f492568SJohan Hovold 30968d78602aSSrinivas Kandagatla snd_soc_component_init_regmap(component, wcd938x->regmap); 30978d78602aSSrinivas Kandagatla 309885a61b1cSJohan Hovold ret = pm_runtime_resume_and_get(dev); 309985a61b1cSJohan Hovold if (ret < 0) 310085a61b1cSJohan Hovold return ret; 310185a61b1cSJohan Hovold 31028d78602aSSrinivas Kandagatla wcd938x->variant = snd_soc_component_read_field(component, 31038d78602aSSrinivas Kandagatla WCD938X_DIGITAL_EFUSE_REG_0, 31048d78602aSSrinivas Kandagatla WCD938X_ID_MASK); 31058d78602aSSrinivas Kandagatla 31068d78602aSSrinivas Kandagatla wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X); 31078d78602aSSrinivas Kandagatla 31088d78602aSSrinivas Kandagatla wcd938x_io_init(wcd938x); 31098d78602aSSrinivas Kandagatla /* Set all interrupts as edge triggered */ 31108d78602aSSrinivas Kandagatla for (i = 0; i < wcd938x_regmap_irq_chip.num_regs; i++) { 31118d78602aSSrinivas Kandagatla regmap_write(wcd938x->regmap, 31128d78602aSSrinivas Kandagatla (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0); 31138d78602aSSrinivas Kandagatla } 31148d78602aSSrinivas Kandagatla 311585a61b1cSJohan Hovold pm_runtime_put(dev); 311685a61b1cSJohan Hovold 31178d78602aSSrinivas Kandagatla wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, 31188d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHR_PDM_WD_INT); 31198d78602aSSrinivas Kandagatla wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, 31208d78602aSSrinivas Kandagatla WCD938X_IRQ_HPHL_PDM_WD_INT); 31218d78602aSSrinivas Kandagatla wcd938x->aux_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, 31228d78602aSSrinivas Kandagatla WCD938X_IRQ_AUX_PDM_WD_INT); 31238d78602aSSrinivas Kandagatla 31248d78602aSSrinivas Kandagatla /* Request for watchdog interrupt */ 31258d78602aSSrinivas Kandagatla ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq, 31268d78602aSSrinivas Kandagatla IRQF_ONESHOT | IRQF_TRIGGER_RISING, 31278d78602aSSrinivas Kandagatla "HPHR PDM WD INT", wcd938x); 31288d78602aSSrinivas Kandagatla if (ret) 31298d78602aSSrinivas Kandagatla dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret); 31308d78602aSSrinivas Kandagatla 31318d78602aSSrinivas Kandagatla ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq, 31328d78602aSSrinivas Kandagatla IRQF_ONESHOT | IRQF_TRIGGER_RISING, 31338d78602aSSrinivas Kandagatla "HPHL PDM WD INT", wcd938x); 31348d78602aSSrinivas Kandagatla if (ret) 31358d78602aSSrinivas Kandagatla dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret); 31368d78602aSSrinivas Kandagatla 31378d78602aSSrinivas Kandagatla ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq, 31388d78602aSSrinivas Kandagatla IRQF_ONESHOT | IRQF_TRIGGER_RISING, 31398d78602aSSrinivas Kandagatla "AUX PDM WD INT", wcd938x); 31408d78602aSSrinivas Kandagatla if (ret) 31418d78602aSSrinivas Kandagatla dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret); 31428d78602aSSrinivas Kandagatla 31438d78602aSSrinivas Kandagatla /* Disable watchdog interrupt for HPH and AUX */ 31448d78602aSSrinivas Kandagatla disable_irq_nosync(wcd938x->hphr_pdm_wd_int); 31458d78602aSSrinivas Kandagatla disable_irq_nosync(wcd938x->hphl_pdm_wd_int); 31468d78602aSSrinivas Kandagatla disable_irq_nosync(wcd938x->aux_pdm_wd_int); 31478d78602aSSrinivas Kandagatla 3148e8ba1e05SSrinivas Kandagatla switch (wcd938x->variant) { 3149e8ba1e05SSrinivas Kandagatla case WCD9380: 3150e8ba1e05SSrinivas Kandagatla ret = snd_soc_add_component_controls(component, wcd9380_snd_controls, 3151e8ba1e05SSrinivas Kandagatla ARRAY_SIZE(wcd9380_snd_controls)); 3152e8ba1e05SSrinivas Kandagatla if (ret < 0) { 3153e8ba1e05SSrinivas Kandagatla dev_err(component->dev, 3154e8ba1e05SSrinivas Kandagatla "%s: Failed to add snd ctrls for variant: %d\n", 3155e8ba1e05SSrinivas Kandagatla __func__, wcd938x->variant); 3156e8ba1e05SSrinivas Kandagatla goto err; 3157e8ba1e05SSrinivas Kandagatla } 3158e8ba1e05SSrinivas Kandagatla break; 3159e8ba1e05SSrinivas Kandagatla case WCD9385: 3160e8ba1e05SSrinivas Kandagatla ret = snd_soc_add_component_controls(component, wcd9385_snd_controls, 3161e8ba1e05SSrinivas Kandagatla ARRAY_SIZE(wcd9385_snd_controls)); 3162e8ba1e05SSrinivas Kandagatla if (ret < 0) { 3163e8ba1e05SSrinivas Kandagatla dev_err(component->dev, 3164e8ba1e05SSrinivas Kandagatla "%s: Failed to add snd ctrls for variant: %d\n", 3165e8ba1e05SSrinivas Kandagatla __func__, wcd938x->variant); 3166e8ba1e05SSrinivas Kandagatla goto err; 3167e8ba1e05SSrinivas Kandagatla } 3168e8ba1e05SSrinivas Kandagatla break; 3169e8ba1e05SSrinivas Kandagatla default: 3170e8ba1e05SSrinivas Kandagatla break; 3171e8ba1e05SSrinivas Kandagatla } 3172bcee7ed0SSrinivas Kandagatla 3173bcee7ed0SSrinivas Kandagatla ret = wcd938x_mbhc_init(component); 3174bcee7ed0SSrinivas Kandagatla if (ret) 3175bcee7ed0SSrinivas Kandagatla dev_err(component->dev, "mbhc initialization failed\n"); 3176e8ba1e05SSrinivas Kandagatla err: 31778d78602aSSrinivas Kandagatla return ret; 31788d78602aSSrinivas Kandagatla } 31798d78602aSSrinivas Kandagatla 3180bcee7ed0SSrinivas Kandagatla static int wcd938x_codec_set_jack(struct snd_soc_component *comp, 3181bcee7ed0SSrinivas Kandagatla struct snd_soc_jack *jack, void *data) 3182bcee7ed0SSrinivas Kandagatla { 3183bcee7ed0SSrinivas Kandagatla struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev); 3184bcee7ed0SSrinivas Kandagatla 3185db0767b8SSrinivasa Rao Mandadapu if (jack) 3186bcee7ed0SSrinivas Kandagatla return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack); 3187db0767b8SSrinivasa Rao Mandadapu else 3188bcee7ed0SSrinivas Kandagatla wcd_mbhc_stop(wcd->wcd_mbhc); 3189bcee7ed0SSrinivas Kandagatla 3190bcee7ed0SSrinivas Kandagatla return 0; 3191bcee7ed0SSrinivas Kandagatla } 3192bcee7ed0SSrinivas Kandagatla 31938d78602aSSrinivas Kandagatla static const struct snd_soc_component_driver soc_codec_dev_wcd938x = { 31948d78602aSSrinivas Kandagatla .name = "wcd938x_codec", 31958d78602aSSrinivas Kandagatla .probe = wcd938x_soc_codec_probe, 3196e8ba1e05SSrinivas Kandagatla .controls = wcd938x_snd_controls, 3197e8ba1e05SSrinivas Kandagatla .num_controls = ARRAY_SIZE(wcd938x_snd_controls), 31988da9db0cSSrinivas Kandagatla .dapm_widgets = wcd938x_dapm_widgets, 31998da9db0cSSrinivas Kandagatla .num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets), 320004544222SSrinivas Kandagatla .dapm_routes = wcd938x_audio_map, 320104544222SSrinivas Kandagatla .num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map), 3202bcee7ed0SSrinivas Kandagatla .set_jack = wcd938x_codec_set_jack, 3203ff7f9aa5SCharles Keepax .endianness = 1, 32048d78602aSSrinivas Kandagatla }; 32058d78602aSSrinivas Kandagatla 32068d78602aSSrinivas Kandagatla static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd) 32078d78602aSSrinivas Kandagatla { 32088d78602aSSrinivas Kandagatla struct device_node *np = dev->of_node; 32098d78602aSSrinivas Kandagatla u32 prop_val = 0; 32108d78602aSSrinivas Kandagatla int rc = 0; 32118d78602aSSrinivas Kandagatla 32128d78602aSSrinivas Kandagatla rc = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); 32138d78602aSSrinivas Kandagatla if (!rc) 32148d78602aSSrinivas Kandagatla wcd->micb1_mv = prop_val/1000; 32158d78602aSSrinivas Kandagatla else 32168d78602aSSrinivas Kandagatla dev_info(dev, "%s: Micbias1 DT property not found\n", __func__); 32178d78602aSSrinivas Kandagatla 32188d78602aSSrinivas Kandagatla rc = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); 32198d78602aSSrinivas Kandagatla if (!rc) 32208d78602aSSrinivas Kandagatla wcd->micb2_mv = prop_val/1000; 32218d78602aSSrinivas Kandagatla else 32228d78602aSSrinivas Kandagatla dev_info(dev, "%s: Micbias2 DT property not found\n", __func__); 32238d78602aSSrinivas Kandagatla 32248d78602aSSrinivas Kandagatla rc = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); 32258d78602aSSrinivas Kandagatla if (!rc) 32268d78602aSSrinivas Kandagatla wcd->micb3_mv = prop_val/1000; 32278d78602aSSrinivas Kandagatla else 32288d78602aSSrinivas Kandagatla dev_info(dev, "%s: Micbias3 DT property not found\n", __func__); 32298d78602aSSrinivas Kandagatla 32308d78602aSSrinivas Kandagatla rc = of_property_read_u32(np, "qcom,micbias4-microvolt", &prop_val); 32318d78602aSSrinivas Kandagatla if (!rc) 32328d78602aSSrinivas Kandagatla wcd->micb4_mv = prop_val/1000; 32338d78602aSSrinivas Kandagatla else 32348d78602aSSrinivas Kandagatla dev_info(dev, "%s: Micbias4 DT property not found\n", __func__); 32358d78602aSSrinivas Kandagatla } 32368d78602aSSrinivas Kandagatla 3237013cc2aeSSrinivasa Rao Mandadapu static bool wcd938x_swap_gnd_mic(struct snd_soc_component *component, bool active) 3238013cc2aeSSrinivasa Rao Mandadapu { 3239013cc2aeSSrinivasa Rao Mandadapu int value; 3240013cc2aeSSrinivasa Rao Mandadapu 3241013cc2aeSSrinivasa Rao Mandadapu struct wcd938x_priv *wcd938x; 3242013cc2aeSSrinivasa Rao Mandadapu 3243013cc2aeSSrinivasa Rao Mandadapu wcd938x = snd_soc_component_get_drvdata(component); 3244013cc2aeSSrinivasa Rao Mandadapu 3245db0b4aedSSrinivasa Rao Mandadapu value = gpiod_get_value(wcd938x->us_euro_gpio); 3246013cc2aeSSrinivasa Rao Mandadapu 3247db0b4aedSSrinivasa Rao Mandadapu gpiod_set_value(wcd938x->us_euro_gpio, !value); 3248013cc2aeSSrinivasa Rao Mandadapu 3249013cc2aeSSrinivasa Rao Mandadapu return true; 3250013cc2aeSSrinivasa Rao Mandadapu } 3251013cc2aeSSrinivasa Rao Mandadapu 3252013cc2aeSSrinivasa Rao Mandadapu 32538d78602aSSrinivas Kandagatla static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev) 32548d78602aSSrinivas Kandagatla { 3255bcee7ed0SSrinivas Kandagatla struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg; 32568d78602aSSrinivas Kandagatla int ret; 32578d78602aSSrinivas Kandagatla 32588d78602aSSrinivas Kandagatla wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); 325960ba2fdaSKrzysztof Kozlowski if (wcd938x->reset_gpio < 0) 326060ba2fdaSKrzysztof Kozlowski return dev_err_probe(dev, wcd938x->reset_gpio, 326160ba2fdaSKrzysztof Kozlowski "Failed to get reset gpio\n"); 32628d78602aSSrinivas Kandagatla 3263db0b4aedSSrinivasa Rao Mandadapu wcd938x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro", 3264db0b4aedSSrinivasa Rao Mandadapu GPIOD_OUT_LOW); 326560ba2fdaSKrzysztof Kozlowski if (IS_ERR(wcd938x->us_euro_gpio)) 326660ba2fdaSKrzysztof Kozlowski return dev_err_probe(dev, PTR_ERR(wcd938x->us_euro_gpio), 326760ba2fdaSKrzysztof Kozlowski "us-euro swap Control GPIO not found\n"); 3268013cc2aeSSrinivasa Rao Mandadapu 3269db0b4aedSSrinivasa Rao Mandadapu cfg->swap_gnd_mic = wcd938x_swap_gnd_mic; 3270db0b4aedSSrinivasa Rao Mandadapu 32718d78602aSSrinivas Kandagatla wcd938x->supplies[0].supply = "vdd-rxtx"; 32728d78602aSSrinivas Kandagatla wcd938x->supplies[1].supply = "vdd-io"; 32738d78602aSSrinivas Kandagatla wcd938x->supplies[2].supply = "vdd-buck"; 32748d78602aSSrinivas Kandagatla wcd938x->supplies[3].supply = "vdd-mic-bias"; 32758d78602aSSrinivas Kandagatla 32768d78602aSSrinivas Kandagatla ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies); 327760ba2fdaSKrzysztof Kozlowski if (ret) 327860ba2fdaSKrzysztof Kozlowski return dev_err_probe(dev, ret, "Failed to get supplies\n"); 32798d78602aSSrinivas Kandagatla 32808d78602aSSrinivas Kandagatla ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); 328160ba2fdaSKrzysztof Kozlowski if (ret) 328260ba2fdaSKrzysztof Kozlowski return dev_err_probe(dev, ret, "Failed to enable supplies\n"); 32838d78602aSSrinivas Kandagatla 32848d78602aSSrinivas Kandagatla wcd938x_dt_parse_micbias_info(dev, wcd938x); 32858d78602aSSrinivas Kandagatla 3286bcee7ed0SSrinivas Kandagatla cfg->mbhc_micbias = MIC_BIAS_2; 3287bcee7ed0SSrinivas Kandagatla cfg->anc_micbias = MIC_BIAS_2; 3288bcee7ed0SSrinivas Kandagatla cfg->v_hs_max = WCD_MBHC_HS_V_MAX; 3289bcee7ed0SSrinivas Kandagatla cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS; 3290bcee7ed0SSrinivas Kandagatla cfg->micb_mv = wcd938x->micb2_mv; 3291bcee7ed0SSrinivas Kandagatla cfg->linein_th = 5000; 3292bcee7ed0SSrinivas Kandagatla cfg->hs_thr = 1700; 3293bcee7ed0SSrinivas Kandagatla cfg->hph_thr = 50; 3294bcee7ed0SSrinivas Kandagatla 3295bcee7ed0SSrinivas Kandagatla wcd_dt_parse_mbhc_data(dev, cfg); 3296bcee7ed0SSrinivas Kandagatla 32978d78602aSSrinivas Kandagatla return 0; 32988d78602aSSrinivas Kandagatla } 32998d78602aSSrinivas Kandagatla 33008d78602aSSrinivas Kandagatla static int wcd938x_reset(struct wcd938x_priv *wcd938x) 33018d78602aSSrinivas Kandagatla { 33028d78602aSSrinivas Kandagatla gpio_direction_output(wcd938x->reset_gpio, 0); 33038d78602aSSrinivas Kandagatla /* 20us sleep required after pulling the reset gpio to LOW */ 33048d78602aSSrinivas Kandagatla usleep_range(20, 30); 33058d78602aSSrinivas Kandagatla gpio_set_value(wcd938x->reset_gpio, 1); 33068d78602aSSrinivas Kandagatla /* 20us sleep required after pulling the reset gpio to HIGH */ 33078d78602aSSrinivas Kandagatla usleep_range(20, 30); 33088d78602aSSrinivas Kandagatla 33098d78602aSSrinivas Kandagatla return 0; 33108d78602aSSrinivas Kandagatla } 33118d78602aSSrinivas Kandagatla 331216572522SSrinivas Kandagatla static int wcd938x_codec_hw_params(struct snd_pcm_substream *substream, 331316572522SSrinivas Kandagatla struct snd_pcm_hw_params *params, 331416572522SSrinivas Kandagatla struct snd_soc_dai *dai) 331516572522SSrinivas Kandagatla { 331616572522SSrinivas Kandagatla struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev); 331716572522SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id]; 331816572522SSrinivas Kandagatla 331916572522SSrinivas Kandagatla return wcd938x_sdw_hw_params(wcd, substream, params, dai); 332016572522SSrinivas Kandagatla } 332116572522SSrinivas Kandagatla 332216572522SSrinivas Kandagatla static int wcd938x_codec_free(struct snd_pcm_substream *substream, 332316572522SSrinivas Kandagatla struct snd_soc_dai *dai) 332416572522SSrinivas Kandagatla { 332516572522SSrinivas Kandagatla struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev); 332616572522SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id]; 332716572522SSrinivas Kandagatla 332816572522SSrinivas Kandagatla return wcd938x_sdw_free(wcd, substream, dai); 332916572522SSrinivas Kandagatla } 333016572522SSrinivas Kandagatla 333116572522SSrinivas Kandagatla static int wcd938x_codec_set_sdw_stream(struct snd_soc_dai *dai, 333216572522SSrinivas Kandagatla void *stream, int direction) 333316572522SSrinivas Kandagatla { 333416572522SSrinivas Kandagatla struct wcd938x_priv *wcd938x = dev_get_drvdata(dai->dev); 333516572522SSrinivas Kandagatla struct wcd938x_sdw_priv *wcd = wcd938x->sdw_priv[dai->id]; 333616572522SSrinivas Kandagatla 333716572522SSrinivas Kandagatla return wcd938x_sdw_set_sdw_stream(wcd, dai, stream, direction); 333816572522SSrinivas Kandagatla 333916572522SSrinivas Kandagatla } 334016572522SSrinivas Kandagatla 3341355af6c0SPu Lehui static const struct snd_soc_dai_ops wcd938x_sdw_dai_ops = { 334216572522SSrinivas Kandagatla .hw_params = wcd938x_codec_hw_params, 334316572522SSrinivas Kandagatla .hw_free = wcd938x_codec_free, 3344e8444560SPierre-Louis Bossart .set_stream = wcd938x_codec_set_sdw_stream, 33458d78602aSSrinivas Kandagatla }; 33468d78602aSSrinivas Kandagatla 33478d78602aSSrinivas Kandagatla static struct snd_soc_dai_driver wcd938x_dais[] = { 33488d78602aSSrinivas Kandagatla [0] = { 33498d78602aSSrinivas Kandagatla .name = "wcd938x-sdw-rx", 33508d78602aSSrinivas Kandagatla .playback = { 33518d78602aSSrinivas Kandagatla .stream_name = "WCD AIF1 Playback", 33528d78602aSSrinivas Kandagatla .rates = WCD938X_RATES_MASK | WCD938X_FRAC_RATES_MASK, 33538d78602aSSrinivas Kandagatla .formats = WCD938X_FORMATS_S16_S24_LE, 33548d78602aSSrinivas Kandagatla .rate_max = 192000, 33558d78602aSSrinivas Kandagatla .rate_min = 8000, 33568d78602aSSrinivas Kandagatla .channels_min = 1, 33578d78602aSSrinivas Kandagatla .channels_max = 2, 33588d78602aSSrinivas Kandagatla }, 33598d78602aSSrinivas Kandagatla .ops = &wcd938x_sdw_dai_ops, 33608d78602aSSrinivas Kandagatla }, 33618d78602aSSrinivas Kandagatla [1] = { 33628d78602aSSrinivas Kandagatla .name = "wcd938x-sdw-tx", 33638d78602aSSrinivas Kandagatla .capture = { 33648d78602aSSrinivas Kandagatla .stream_name = "WCD AIF1 Capture", 33658d78602aSSrinivas Kandagatla .rates = WCD938X_RATES_MASK, 33668d78602aSSrinivas Kandagatla .formats = SNDRV_PCM_FMTBIT_S16_LE, 33678d78602aSSrinivas Kandagatla .rate_min = 8000, 33688d78602aSSrinivas Kandagatla .rate_max = 192000, 33698d78602aSSrinivas Kandagatla .channels_min = 1, 33708d78602aSSrinivas Kandagatla .channels_max = 4, 33718d78602aSSrinivas Kandagatla }, 33728d78602aSSrinivas Kandagatla .ops = &wcd938x_sdw_dai_ops, 33738d78602aSSrinivas Kandagatla }, 33748d78602aSSrinivas Kandagatla }; 33758d78602aSSrinivas Kandagatla 33768d78602aSSrinivas Kandagatla static int wcd938x_bind(struct device *dev) 33778d78602aSSrinivas Kandagatla { 33788d78602aSSrinivas Kandagatla struct wcd938x_priv *wcd938x = dev_get_drvdata(dev); 33798d78602aSSrinivas Kandagatla int ret; 33808d78602aSSrinivas Kandagatla 33818d78602aSSrinivas Kandagatla ret = component_bind_all(dev, wcd938x); 33828d78602aSSrinivas Kandagatla if (ret) { 33838d78602aSSrinivas Kandagatla dev_err(dev, "%s: Slave bind failed, ret = %d\n", 33848d78602aSSrinivas Kandagatla __func__, ret); 33858d78602aSSrinivas Kandagatla return ret; 33868d78602aSSrinivas Kandagatla } 33878d78602aSSrinivas Kandagatla 338816572522SSrinivas Kandagatla wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode); 338916572522SSrinivas Kandagatla if (!wcd938x->rxdev) { 339016572522SSrinivas Kandagatla dev_err(dev, "could not find slave with matching of node\n"); 339116572522SSrinivas Kandagatla return -EINVAL; 339216572522SSrinivas Kandagatla } 339316572522SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev); 339416572522SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x; 339516572522SSrinivas Kandagatla 339616572522SSrinivas Kandagatla wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode); 339716572522SSrinivas Kandagatla if (!wcd938x->txdev) { 339816572522SSrinivas Kandagatla dev_err(dev, "could not find txslave with matching of node\n"); 339916572522SSrinivas Kandagatla return -EINVAL; 340016572522SSrinivas Kandagatla } 340116572522SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev); 340216572522SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x; 340316572522SSrinivas Kandagatla wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev); 340416572522SSrinivas Kandagatla if (!wcd938x->tx_sdw_dev) { 340516572522SSrinivas Kandagatla dev_err(dev, "could not get txslave with matching of dev\n"); 340616572522SSrinivas Kandagatla return -EINVAL; 340716572522SSrinivas Kandagatla } 340816572522SSrinivas Kandagatla 340916572522SSrinivas Kandagatla /* As TX is main CSR reg interface, which should not be suspended first. 341016572522SSrinivas Kandagatla * expicilty add the dependency link */ 341116572522SSrinivas Kandagatla if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS | 341216572522SSrinivas Kandagatla DL_FLAG_PM_RUNTIME)) { 341316572522SSrinivas Kandagatla dev_err(dev, "could not devlink tx and rx\n"); 341416572522SSrinivas Kandagatla return -EINVAL; 341516572522SSrinivas Kandagatla } 341616572522SSrinivas Kandagatla 341716572522SSrinivas Kandagatla if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS | 341816572522SSrinivas Kandagatla DL_FLAG_PM_RUNTIME)) { 341916572522SSrinivas Kandagatla dev_err(dev, "could not devlink wcd and tx\n"); 342016572522SSrinivas Kandagatla return -EINVAL; 342116572522SSrinivas Kandagatla } 342216572522SSrinivas Kandagatla 342316572522SSrinivas Kandagatla if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS | 342416572522SSrinivas Kandagatla DL_FLAG_PM_RUNTIME)) { 342516572522SSrinivas Kandagatla dev_err(dev, "could not devlink wcd and rx\n"); 342616572522SSrinivas Kandagatla return -EINVAL; 342716572522SSrinivas Kandagatla } 342816572522SSrinivas Kandagatla 342984822215SKrzysztof Kozlowski wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL); 343084822215SKrzysztof Kozlowski if (!wcd938x->regmap) { 343184822215SKrzysztof Kozlowski dev_err(dev, "could not get TX device regmap\n"); 343284822215SKrzysztof Kozlowski return -EINVAL; 343316572522SSrinivas Kandagatla } 343416572522SSrinivas Kandagatla 3435f99986c0SSrinivas Kandagatla ret = wcd938x_irq_init(wcd938x, dev); 3436f99986c0SSrinivas Kandagatla if (ret) { 3437f99986c0SSrinivas Kandagatla dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret); 3438f99986c0SSrinivas Kandagatla return ret; 3439f99986c0SSrinivas Kandagatla } 3440f99986c0SSrinivas Kandagatla 3441f99986c0SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq; 3442f99986c0SSrinivas Kandagatla wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq; 3443f99986c0SSrinivas Kandagatla 34448d78602aSSrinivas Kandagatla ret = wcd938x_set_micbias_data(wcd938x); 34458d78602aSSrinivas Kandagatla if (ret < 0) { 34468d78602aSSrinivas Kandagatla dev_err(dev, "%s: bad micbias pdata\n", __func__); 34478d78602aSSrinivas Kandagatla return ret; 34488d78602aSSrinivas Kandagatla } 34498d78602aSSrinivas Kandagatla 34508d78602aSSrinivas Kandagatla ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x, 34518d78602aSSrinivas Kandagatla wcd938x_dais, ARRAY_SIZE(wcd938x_dais)); 34528d78602aSSrinivas Kandagatla if (ret) 34538d78602aSSrinivas Kandagatla dev_err(dev, "%s: Codec registration failed\n", 34548d78602aSSrinivas Kandagatla __func__); 34558d78602aSSrinivas Kandagatla 34568d78602aSSrinivas Kandagatla return ret; 34578d78602aSSrinivas Kandagatla 34588d78602aSSrinivas Kandagatla } 34598d78602aSSrinivas Kandagatla 34608d78602aSSrinivas Kandagatla static void wcd938x_unbind(struct device *dev) 34618d78602aSSrinivas Kandagatla { 34628d78602aSSrinivas Kandagatla struct wcd938x_priv *wcd938x = dev_get_drvdata(dev); 34638d78602aSSrinivas Kandagatla 346416572522SSrinivas Kandagatla device_link_remove(dev, wcd938x->txdev); 346516572522SSrinivas Kandagatla device_link_remove(dev, wcd938x->rxdev); 346616572522SSrinivas Kandagatla device_link_remove(wcd938x->rxdev, wcd938x->txdev); 34678d78602aSSrinivas Kandagatla snd_soc_unregister_component(dev); 34688d78602aSSrinivas Kandagatla component_unbind_all(dev, wcd938x); 34698d78602aSSrinivas Kandagatla } 34708d78602aSSrinivas Kandagatla 34718d78602aSSrinivas Kandagatla static const struct component_master_ops wcd938x_comp_ops = { 34728d78602aSSrinivas Kandagatla .bind = wcd938x_bind, 34738d78602aSSrinivas Kandagatla .unbind = wcd938x_unbind, 34748d78602aSSrinivas Kandagatla }; 34758d78602aSSrinivas Kandagatla 34768d78602aSSrinivas Kandagatla static int wcd938x_add_slave_components(struct wcd938x_priv *wcd938x, 34778d78602aSSrinivas Kandagatla struct device *dev, 34788d78602aSSrinivas Kandagatla struct component_match **matchptr) 34798d78602aSSrinivas Kandagatla { 34808d78602aSSrinivas Kandagatla struct device_node *np; 34818d78602aSSrinivas Kandagatla 34828d78602aSSrinivas Kandagatla np = dev->of_node; 34838d78602aSSrinivas Kandagatla 34848d78602aSSrinivas Kandagatla wcd938x->rxnode = of_parse_phandle(np, "qcom,rx-device", 0); 34858d78602aSSrinivas Kandagatla if (!wcd938x->rxnode) { 34868d78602aSSrinivas Kandagatla dev_err(dev, "%s: Rx-device node not defined\n", __func__); 34878d78602aSSrinivas Kandagatla return -ENODEV; 34888d78602aSSrinivas Kandagatla } 34898d78602aSSrinivas Kandagatla 34908d78602aSSrinivas Kandagatla of_node_get(wcd938x->rxnode); 3491a8271d7eSYong Wu component_match_add_release(dev, matchptr, component_release_of, 3492a8271d7eSYong Wu component_compare_of, wcd938x->rxnode); 34938d78602aSSrinivas Kandagatla 34948d78602aSSrinivas Kandagatla wcd938x->txnode = of_parse_phandle(np, "qcom,tx-device", 0); 34958d78602aSSrinivas Kandagatla if (!wcd938x->txnode) { 34968d78602aSSrinivas Kandagatla dev_err(dev, "%s: Tx-device node not defined\n", __func__); 34978d78602aSSrinivas Kandagatla return -ENODEV; 34988d78602aSSrinivas Kandagatla } 34998d78602aSSrinivas Kandagatla of_node_get(wcd938x->txnode); 3500a8271d7eSYong Wu component_match_add_release(dev, matchptr, component_release_of, 3501a8271d7eSYong Wu component_compare_of, wcd938x->txnode); 35028d78602aSSrinivas Kandagatla return 0; 35038d78602aSSrinivas Kandagatla } 35048d78602aSSrinivas Kandagatla 35058d78602aSSrinivas Kandagatla static int wcd938x_probe(struct platform_device *pdev) 35068d78602aSSrinivas Kandagatla { 35078d78602aSSrinivas Kandagatla struct component_match *match = NULL; 35088d78602aSSrinivas Kandagatla struct wcd938x_priv *wcd938x = NULL; 35098d78602aSSrinivas Kandagatla struct device *dev = &pdev->dev; 35108d78602aSSrinivas Kandagatla int ret; 35118d78602aSSrinivas Kandagatla 35128d78602aSSrinivas Kandagatla wcd938x = devm_kzalloc(dev, sizeof(struct wcd938x_priv), 35138d78602aSSrinivas Kandagatla GFP_KERNEL); 35148d78602aSSrinivas Kandagatla if (!wcd938x) 35158d78602aSSrinivas Kandagatla return -ENOMEM; 35168d78602aSSrinivas Kandagatla 35178d78602aSSrinivas Kandagatla dev_set_drvdata(dev, wcd938x); 3518bcee7ed0SSrinivas Kandagatla mutex_init(&wcd938x->micb_lock); 35198d78602aSSrinivas Kandagatla 35208d78602aSSrinivas Kandagatla ret = wcd938x_populate_dt_data(wcd938x, dev); 35218d78602aSSrinivas Kandagatla if (ret) { 35228d78602aSSrinivas Kandagatla dev_err(dev, "%s: Fail to obtain platform data\n", __func__); 35238d78602aSSrinivas Kandagatla return -EINVAL; 35248d78602aSSrinivas Kandagatla } 35258d78602aSSrinivas Kandagatla 35268d78602aSSrinivas Kandagatla ret = wcd938x_add_slave_components(wcd938x, dev, &match); 35278d78602aSSrinivas Kandagatla if (ret) 35288d78602aSSrinivas Kandagatla return ret; 35298d78602aSSrinivas Kandagatla 35308d78602aSSrinivas Kandagatla wcd938x_reset(wcd938x); 35318d78602aSSrinivas Kandagatla 35328d78602aSSrinivas Kandagatla ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match); 35338d78602aSSrinivas Kandagatla if (ret) 35348d78602aSSrinivas Kandagatla return ret; 35358d78602aSSrinivas Kandagatla 35368d78602aSSrinivas Kandagatla pm_runtime_set_autosuspend_delay(dev, 1000); 35378d78602aSSrinivas Kandagatla pm_runtime_use_autosuspend(dev); 35388d78602aSSrinivas Kandagatla pm_runtime_mark_last_busy(dev); 35398d78602aSSrinivas Kandagatla pm_runtime_set_active(dev); 35408d78602aSSrinivas Kandagatla pm_runtime_enable(dev); 35418d78602aSSrinivas Kandagatla pm_runtime_idle(dev); 35428d78602aSSrinivas Kandagatla 35438c62dbcbSPierre-Louis Bossart return 0; 35448d78602aSSrinivas Kandagatla } 35458d78602aSSrinivas Kandagatla 35467cd686a5SUwe Kleine-König static void wcd938x_remove(struct platform_device *pdev) 35478d78602aSSrinivas Kandagatla { 35488d78602aSSrinivas Kandagatla component_master_del(&pdev->dev, &wcd938x_comp_ops); 35498d78602aSSrinivas Kandagatla } 35508d78602aSSrinivas Kandagatla 35518c4863c2SSrinivas Kandagatla #if defined(CONFIG_OF) 35528d78602aSSrinivas Kandagatla static const struct of_device_id wcd938x_dt_match[] = { 35538d78602aSSrinivas Kandagatla { .compatible = "qcom,wcd9380-codec" }, 35548d78602aSSrinivas Kandagatla { .compatible = "qcom,wcd9385-codec" }, 35558d78602aSSrinivas Kandagatla {} 35568d78602aSSrinivas Kandagatla }; 35578d78602aSSrinivas Kandagatla MODULE_DEVICE_TABLE(of, wcd938x_dt_match); 35588c4863c2SSrinivas Kandagatla #endif 35598d78602aSSrinivas Kandagatla 35608d78602aSSrinivas Kandagatla static struct platform_driver wcd938x_codec_driver = { 35618d78602aSSrinivas Kandagatla .probe = wcd938x_probe, 35627cd686a5SUwe Kleine-König .remove_new = wcd938x_remove, 35638d78602aSSrinivas Kandagatla .driver = { 35648d78602aSSrinivas Kandagatla .name = "wcd938x_codec", 35658d78602aSSrinivas Kandagatla .of_match_table = of_match_ptr(wcd938x_dt_match), 35668d78602aSSrinivas Kandagatla .suppress_bind_attrs = true, 35678d78602aSSrinivas Kandagatla }, 35688d78602aSSrinivas Kandagatla }; 35698d78602aSSrinivas Kandagatla 35708d78602aSSrinivas Kandagatla module_platform_driver(wcd938x_codec_driver); 35718d78602aSSrinivas Kandagatla MODULE_DESCRIPTION("WCD938X Codec driver"); 35728d78602aSSrinivas Kandagatla MODULE_LICENSE("GPL"); 3573