15c439937SZhu Ning // SPDX-License-Identifier: GPL-2.0-only 25c439937SZhu Ning // 35c439937SZhu Ning // es8326.c -- es8326 ALSA SoC audio driver 45c439937SZhu Ning // Copyright Everest Semiconductor Co., Ltd 55c439937SZhu Ning // 65c439937SZhu Ning // Authors: David Yang <yangxiaohua@everest-semi.com> 75c439937SZhu Ning // 85c439937SZhu Ning 95c439937SZhu Ning #include <linux/clk.h> 105c439937SZhu Ning #include <linux/i2c.h> 115c439937SZhu Ning #include <linux/interrupt.h> 125c439937SZhu Ning #include <linux/irq.h> 135c439937SZhu Ning #include <linux/module.h> 145c439937SZhu Ning #include <sound/jack.h> 155c439937SZhu Ning #include <sound/pcm_params.h> 165c439937SZhu Ning #include <sound/soc.h> 175c439937SZhu Ning #include <sound/soc-dapm.h> 185c439937SZhu Ning #include <sound/tlv.h> 195c439937SZhu Ning #include "es8326.h" 205c439937SZhu Ning 215c439937SZhu Ning struct es8326_priv { 225c439937SZhu Ning struct clk *mclk; 235c439937SZhu Ning struct i2c_client *i2c; 245c439937SZhu Ning struct regmap *regmap; 255c439937SZhu Ning struct snd_soc_component *component; 265c439937SZhu Ning struct delayed_work jack_detect_work; 275c439937SZhu Ning struct delayed_work button_press_work; 285c439937SZhu Ning struct snd_soc_jack *jack; 295c439937SZhu Ning int irq; 305c439937SZhu Ning /* The lock protects the situation that an irq is generated 315c439937SZhu Ning * while enabling or disabling or during an irq. 325c439937SZhu Ning */ 335c439937SZhu Ning struct mutex lock; 345c439937SZhu Ning u8 jack_pol; 355c439937SZhu Ning u8 interrupt_src; 365c439937SZhu Ning u8 interrupt_clk; 37966323ddSZhu Ning u8 hpl_vol; 38966323ddSZhu Ning u8 hpr_vol; 395c439937SZhu Ning bool jd_inverted; 405c439937SZhu Ning unsigned int sysclk; 41083912c2SZhu Ning 42083912c2SZhu Ning bool calibrated; 43083912c2SZhu Ning int version; 4404f96c93SZhu Ning int hp; 4504f96c93SZhu Ning int jack_remove_retry; 465c439937SZhu Ning }; 475c439937SZhu Ning 48523d242dSZhu Ning static int es8326_crosstalk1_get(struct snd_kcontrol *kcontrol, 49523d242dSZhu Ning struct snd_ctl_elem_value *ucontrol) 50523d242dSZhu Ning { 51523d242dSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 52523d242dSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 53523d242dSZhu Ning unsigned int crosstalk_h, crosstalk_l; 54523d242dSZhu Ning unsigned int crosstalk; 55523d242dSZhu Ning 56523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_RAMPRATE, &crosstalk_h); 57523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); 58523d242dSZhu Ning crosstalk_h &= 0x20; 59523d242dSZhu Ning crosstalk_l &= 0xf0; 60523d242dSZhu Ning crosstalk = crosstalk_h >> 1 | crosstalk_l >> 4; 61523d242dSZhu Ning ucontrol->value.integer.value[0] = crosstalk; 62523d242dSZhu Ning 63523d242dSZhu Ning return 0; 64523d242dSZhu Ning } 65523d242dSZhu Ning 66523d242dSZhu Ning static int es8326_crosstalk1_set(struct snd_kcontrol *kcontrol, 67523d242dSZhu Ning struct snd_ctl_elem_value *ucontrol) 68523d242dSZhu Ning { 69523d242dSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 70523d242dSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 71523d242dSZhu Ning unsigned int crosstalk_h, crosstalk_l; 72523d242dSZhu Ning unsigned int crosstalk; 73523d242dSZhu Ning 74523d242dSZhu Ning crosstalk = ucontrol->value.integer.value[0]; 75523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); 76523d242dSZhu Ning crosstalk_h = (crosstalk & 0x10) << 1; 77523d242dSZhu Ning crosstalk_l &= 0x0f; 78523d242dSZhu Ning crosstalk_l |= (crosstalk & 0x0f) << 4; 79523d242dSZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_RAMPRATE, 80523d242dSZhu Ning 0x20, crosstalk_h); 81523d242dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, crosstalk_l); 82523d242dSZhu Ning 83523d242dSZhu Ning return 0; 84523d242dSZhu Ning } 85523d242dSZhu Ning 86523d242dSZhu Ning static int es8326_crosstalk2_get(struct snd_kcontrol *kcontrol, 87523d242dSZhu Ning struct snd_ctl_elem_value *ucontrol) 88523d242dSZhu Ning { 89523d242dSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 90523d242dSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 91523d242dSZhu Ning unsigned int crosstalk_h, crosstalk_l; 92523d242dSZhu Ning unsigned int crosstalk; 93523d242dSZhu Ning 94523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_RAMPRATE, &crosstalk_h); 95523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); 96523d242dSZhu Ning crosstalk_h &= 0x10; 97523d242dSZhu Ning crosstalk_l &= 0x0f; 98523d242dSZhu Ning crosstalk = crosstalk_h | crosstalk_l; 99523d242dSZhu Ning ucontrol->value.integer.value[0] = crosstalk; 100523d242dSZhu Ning 101523d242dSZhu Ning return 0; 102523d242dSZhu Ning } 103523d242dSZhu Ning 104523d242dSZhu Ning static int es8326_crosstalk2_set(struct snd_kcontrol *kcontrol, 105523d242dSZhu Ning struct snd_ctl_elem_value *ucontrol) 106523d242dSZhu Ning { 107523d242dSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 108523d242dSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 109523d242dSZhu Ning unsigned int crosstalk_h, crosstalk_l; 110523d242dSZhu Ning unsigned int crosstalk; 111523d242dSZhu Ning 112523d242dSZhu Ning crosstalk = ucontrol->value.integer.value[0]; 113523d242dSZhu Ning regmap_read(es8326->regmap, ES8326_DAC_CROSSTALK, &crosstalk_l); 114523d242dSZhu Ning crosstalk_h = crosstalk & 0x10; 115523d242dSZhu Ning crosstalk_l &= 0xf0; 116523d242dSZhu Ning crosstalk_l |= crosstalk & 0x0f; 117523d242dSZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_RAMPRATE, 118523d242dSZhu Ning 0x10, crosstalk_h); 119523d242dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, crosstalk_l); 120523d242dSZhu Ning 121523d242dSZhu Ning return 0; 122523d242dSZhu Ning } 123523d242dSZhu Ning 124966323ddSZhu Ning static int es8326_hplvol_get(struct snd_kcontrol *kcontrol, 125966323ddSZhu Ning struct snd_ctl_elem_value *ucontrol) 126966323ddSZhu Ning { 127966323ddSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 128966323ddSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 129966323ddSZhu Ning 130966323ddSZhu Ning ucontrol->value.integer.value[0] = es8326->hpl_vol; 131966323ddSZhu Ning 132966323ddSZhu Ning return 0; 133966323ddSZhu Ning } 134966323ddSZhu Ning 135966323ddSZhu Ning static int es8326_hplvol_set(struct snd_kcontrol *kcontrol, 136966323ddSZhu Ning struct snd_ctl_elem_value *ucontrol) 137966323ddSZhu Ning { 138966323ddSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 139966323ddSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 140966323ddSZhu Ning unsigned int hp_vol; 141966323ddSZhu Ning 142966323ddSZhu Ning hp_vol = ucontrol->value.integer.value[0]; 143966323ddSZhu Ning if (hp_vol > 5) 144966323ddSZhu Ning return -EINVAL; 145966323ddSZhu Ning if (es8326->hpl_vol != hp_vol) { 146966323ddSZhu Ning es8326->hpl_vol = hp_vol; 147966323ddSZhu Ning if (hp_vol >= 3) 148966323ddSZhu Ning hp_vol++; 149966323ddSZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_VOL, 150966323ddSZhu Ning 0x70, (hp_vol << 4)); 151966323ddSZhu Ning return 1; 152966323ddSZhu Ning } 153966323ddSZhu Ning 154966323ddSZhu Ning return 0; 155966323ddSZhu Ning } 156966323ddSZhu Ning 157966323ddSZhu Ning static int es8326_hprvol_get(struct snd_kcontrol *kcontrol, 158966323ddSZhu Ning struct snd_ctl_elem_value *ucontrol) 159966323ddSZhu Ning { 160966323ddSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 161966323ddSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 162966323ddSZhu Ning 163966323ddSZhu Ning ucontrol->value.integer.value[0] = es8326->hpr_vol; 164966323ddSZhu Ning 165966323ddSZhu Ning return 0; 166966323ddSZhu Ning } 167966323ddSZhu Ning 168966323ddSZhu Ning static int es8326_hprvol_set(struct snd_kcontrol *kcontrol, 169966323ddSZhu Ning struct snd_ctl_elem_value *ucontrol) 170966323ddSZhu Ning { 171966323ddSZhu Ning struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 172966323ddSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 173966323ddSZhu Ning unsigned int hp_vol; 174966323ddSZhu Ning 175966323ddSZhu Ning hp_vol = ucontrol->value.integer.value[0]; 176966323ddSZhu Ning if (hp_vol > 5) 177966323ddSZhu Ning return -EINVAL; 178966323ddSZhu Ning if (es8326->hpr_vol != hp_vol) { 179966323ddSZhu Ning es8326->hpr_vol = hp_vol; 180966323ddSZhu Ning if (hp_vol >= 3) 181966323ddSZhu Ning hp_vol++; 182966323ddSZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_VOL, 183966323ddSZhu Ning 0x07, hp_vol); 184966323ddSZhu Ning return 1; 185966323ddSZhu Ning } 186966323ddSZhu Ning 187966323ddSZhu Ning return 0; 188966323ddSZhu Ning } 189966323ddSZhu Ning 1905c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9550, 50, 0); 1915c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9550, 50, 0); 1925c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_analog_pga_tlv, 0, 300, 0); 1935c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_pga_tlv, 0, 600, 0); 1945c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(softramp_rate, 0, 100, 0); 1955c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(drc_target_tlv, -3200, 200, 0); 1965c439937SZhu Ning static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(drc_recovery_tlv, -125, 250, 0); 1975c439937SZhu Ning 1985c439937SZhu Ning static const char *const winsize[] = { 1995c439937SZhu Ning "0.25db/2 LRCK", 2005c439937SZhu Ning "0.25db/4 LRCK", 2015c439937SZhu Ning "0.25db/8 LRCK", 2025c439937SZhu Ning "0.25db/16 LRCK", 2035c439937SZhu Ning "0.25db/32 LRCK", 2045c439937SZhu Ning "0.25db/64 LRCK", 2055c439937SZhu Ning "0.25db/128 LRCK", 2065c439937SZhu Ning "0.25db/256 LRCK", 2075c439937SZhu Ning "0.25db/512 LRCK", 2085c439937SZhu Ning "0.25db/1024 LRCK", 2095c439937SZhu Ning "0.25db/2048 LRCK", 2105c439937SZhu Ning "0.25db/4096 LRCK", 2115c439937SZhu Ning "0.25db/8192 LRCK", 2125c439937SZhu Ning "0.25db/16384 LRCK", 2135c439937SZhu Ning "0.25db/32768 LRCK", 2145c439937SZhu Ning "0.25db/65536 LRCK", 2155c439937SZhu Ning }; 2165c439937SZhu Ning 2175c439937SZhu Ning static const char *const dacpol_txt[] = { 2185c439937SZhu Ning "Normal", "R Invert", "L Invert", "L + R Invert" }; 2195c439937SZhu Ning 220966323ddSZhu Ning static const char *const hp_spkvol_switch[] = { 221966323ddSZhu Ning "HPVOL: HPL+HPL, SPKVOL: HPL+HPL", 222966323ddSZhu Ning "HPVOL: HPL+HPR, SPKVOL: HPL+HPR", 223966323ddSZhu Ning "HPVOL: HPL+HPL, SPKVOL: SPKL+SPKR", 224966323ddSZhu Ning "HPVOL: HPL+HPR, SPKVOL: SPKL+SPKR", 225966323ddSZhu Ning }; 226966323ddSZhu Ning 2275c439937SZhu Ning static const struct soc_enum dacpol = 2285c439937SZhu Ning SOC_ENUM_SINGLE(ES8326_DAC_DSM, 4, 4, dacpol_txt); 2295c439937SZhu Ning static const struct soc_enum alc_winsize = 2305c439937SZhu Ning SOC_ENUM_SINGLE(ES8326_ADC_RAMPRATE, 4, 16, winsize); 2315c439937SZhu Ning static const struct soc_enum drc_winsize = 2325c439937SZhu Ning SOC_ENUM_SINGLE(ES8326_DRC_WINSIZE, 4, 16, winsize); 233966323ddSZhu Ning static const struct soc_enum hpvol_spkvol_switch = 234966323ddSZhu Ning SOC_ENUM_SINGLE(ES8326_HP_MISC, 6, 4, hp_spkvol_switch); 2355c439937SZhu Ning 2365c439937SZhu Ning static const struct snd_kcontrol_new es8326_snd_controls[] = { 237966323ddSZhu Ning SOC_SINGLE_TLV("DAC Playback Volume", ES8326_DACL_VOL, 0, 0xbf, 0, dac_vol_tlv), 2385c439937SZhu Ning SOC_ENUM("Playback Polarity", dacpol), 2395c439937SZhu Ning SOC_SINGLE_TLV("DAC Ramp Rate", ES8326_DAC_RAMPRATE, 0, 0x0f, 0, softramp_rate), 2405c439937SZhu Ning SOC_SINGLE_TLV("DRC Recovery Level", ES8326_DRC_RECOVERY, 0, 4, 0, drc_recovery_tlv), 2415c439937SZhu Ning SOC_ENUM("DRC Winsize", drc_winsize), 2425c439937SZhu Ning SOC_SINGLE_TLV("DRC Target Level", ES8326_DRC_WINSIZE, 0, 0x0f, 0, drc_target_tlv), 2435c439937SZhu Ning 2445c439937SZhu Ning SOC_DOUBLE_R_TLV("ADC Capture Volume", ES8326_ADC1_VOL, ES8326_ADC2_VOL, 0, 0xff, 0, 2455c439937SZhu Ning adc_vol_tlv), 2465c439937SZhu Ning SOC_DOUBLE_TLV("ADC PGA Volume", ES8326_ADC_SCALE, 4, 0, 5, 0, adc_pga_tlv), 2475c439937SZhu Ning SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8326_PGAGAIN, 0, 10, 0, adc_analog_pga_tlv), 2485c439937SZhu Ning SOC_SINGLE_TLV("ADC Ramp Rate", ES8326_ADC_RAMPRATE, 0, 0x0f, 0, softramp_rate), 2495c439937SZhu Ning SOC_SINGLE("ALC Capture Switch", ES8326_ALC_RECOVERY, 3, 1, 0), 2505c439937SZhu Ning SOC_SINGLE_TLV("ALC Capture Recovery Level", ES8326_ALC_LEVEL, 2515c439937SZhu Ning 0, 4, 0, drc_recovery_tlv), 2525c439937SZhu Ning SOC_ENUM("ALC Capture Winsize", alc_winsize), 2535c439937SZhu Ning SOC_SINGLE_TLV("ALC Capture Target Level", ES8326_ALC_LEVEL, 2545c439937SZhu Ning 0, 0x0f, 0, drc_target_tlv), 2555c439937SZhu Ning 256523d242dSZhu Ning SOC_SINGLE_EXT("CROSSTALK1", SND_SOC_NOPM, 0, 31, 0, 257523d242dSZhu Ning es8326_crosstalk1_get, es8326_crosstalk1_set), 258523d242dSZhu Ning SOC_SINGLE_EXT("CROSSTALK2", SND_SOC_NOPM, 0, 31, 0, 259523d242dSZhu Ning es8326_crosstalk2_get, es8326_crosstalk2_set), 260966323ddSZhu Ning SOC_SINGLE_EXT("HPL Volume", SND_SOC_NOPM, 0, 5, 0, 261966323ddSZhu Ning es8326_hplvol_get, es8326_hplvol_set), 262966323ddSZhu Ning SOC_SINGLE_EXT("HPR Volume", SND_SOC_NOPM, 0, 5, 0, 263966323ddSZhu Ning es8326_hprvol_get, es8326_hprvol_set), 264966323ddSZhu Ning 265966323ddSZhu Ning SOC_SINGLE_TLV("HPL Playback Volume", ES8326_DACL_VOL, 0, 0xbf, 0, dac_vol_tlv), 266966323ddSZhu Ning SOC_SINGLE_TLV("HPR Playback Volume", ES8326_DACR_VOL, 0, 0xbf, 0, dac_vol_tlv), 267966323ddSZhu Ning SOC_SINGLE_TLV("SPKL Playback Volume", ES8326_SPKL_VOL, 0, 0xbf, 0, dac_vol_tlv), 268966323ddSZhu Ning SOC_SINGLE_TLV("SPKR Playback Volume", ES8326_SPKR_VOL, 0, 0xbf, 0, dac_vol_tlv), 269966323ddSZhu Ning 270966323ddSZhu Ning SOC_ENUM("HPVol SPKVol Switch", hpvol_spkvol_switch), 2715c439937SZhu Ning }; 2725c439937SZhu Ning 2735c439937SZhu Ning static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = { 2745c439937SZhu Ning SND_SOC_DAPM_INPUT("MIC1"), 2755c439937SZhu Ning SND_SOC_DAPM_INPUT("MIC2"), 2765c439937SZhu Ning SND_SOC_DAPM_INPUT("MIC3"), 2775c439937SZhu Ning SND_SOC_DAPM_INPUT("MIC4"), 2785c439937SZhu Ning 2795c439937SZhu Ning SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0), 2805c439937SZhu Ning SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0), 2815c439937SZhu Ning 2825c439937SZhu Ning /* Digital Interface */ 2835c439937SZhu Ning SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 0, SND_SOC_NOPM, 0, 0), 2845c439937SZhu Ning SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, SND_SOC_NOPM, 0, 0), 2855c439937SZhu Ning 2865c439937SZhu Ning /* Analog Power Supply*/ 2875c439937SZhu Ning SND_SOC_DAPM_DAC("Right DAC", NULL, ES8326_ANA_PDN, 0, 1), 2885c439937SZhu Ning SND_SOC_DAPM_DAC("Left DAC", NULL, ES8326_ANA_PDN, 1, 1), 2895c439937SZhu Ning SND_SOC_DAPM_SUPPLY("MICBIAS1", ES8326_ANA_MICBIAS, 2, 0, NULL, 0), 2905c439937SZhu Ning SND_SOC_DAPM_SUPPLY("MICBIAS2", ES8326_ANA_MICBIAS, 3, 0, NULL, 0), 2915c439937SZhu Ning 2925c439937SZhu Ning SND_SOC_DAPM_PGA("LHPMIX", ES8326_DAC2HPMIX, 7, 0, NULL, 0), 2935c439937SZhu Ning SND_SOC_DAPM_PGA("RHPMIX", ES8326_DAC2HPMIX, 3, 0, NULL, 0), 2945c439937SZhu Ning 2955c439937SZhu Ning SND_SOC_DAPM_OUTPUT("HPOL"), 2965c439937SZhu Ning SND_SOC_DAPM_OUTPUT("HPOR"), 2975c439937SZhu Ning }; 2985c439937SZhu Ning 2995c439937SZhu Ning static const struct snd_soc_dapm_route es8326_dapm_routes[] = { 3008c99a0a6SZhu Ning {"ADC L", NULL, "MIC1"}, 3018c99a0a6SZhu Ning {"ADC R", NULL, "MIC2"}, 3028c99a0a6SZhu Ning {"ADC L", NULL, "MIC3"}, 3038c99a0a6SZhu Ning {"ADC R", NULL, "MIC4"}, 3045c439937SZhu Ning 3055c439937SZhu Ning {"I2S OUT", NULL, "ADC L"}, 3065c439937SZhu Ning {"I2S OUT", NULL, "ADC R"}, 3075c439937SZhu Ning 3085c439937SZhu Ning {"Right DAC", NULL, "I2S IN"}, 3095c439937SZhu Ning {"Left DAC", NULL, "I2S IN"}, 3105c439937SZhu Ning 3115c439937SZhu Ning {"LHPMIX", NULL, "Left DAC"}, 3125c439937SZhu Ning {"RHPMIX", NULL, "Right DAC"}, 3135c439937SZhu Ning 3145c439937SZhu Ning {"HPOL", NULL, "LHPMIX"}, 3155c439937SZhu Ning {"HPOR", NULL, "RHPMIX"}, 3165c439937SZhu Ning }; 3175c439937SZhu Ning 318f1230a27SZhu Ning static bool es8326_volatile_register(struct device *dev, unsigned int reg) 319f1230a27SZhu Ning { 320f1230a27SZhu Ning switch (reg) { 321f1230a27SZhu Ning case ES8326_HPL_OFFSET_INI: 322f1230a27SZhu Ning case ES8326_HPR_OFFSET_INI: 323f1230a27SZhu Ning case ES8326_HPDET_STA: 324f1230a27SZhu Ning case ES8326_CTIA_OMTP_STA: 325f1230a27SZhu Ning case ES8326_CSM_MUTE_STA: 326f1230a27SZhu Ning return true; 327f1230a27SZhu Ning default: 328f1230a27SZhu Ning return false; 329f1230a27SZhu Ning } 330f1230a27SZhu Ning } 3315c439937SZhu Ning 33234fa846fSZhang Yi static bool es8326_writeable_register(struct device *dev, unsigned int reg) 33334fa846fSZhang Yi { 33434fa846fSZhang Yi switch (reg) { 33534fa846fSZhang Yi case ES8326_BIAS_SW1: 33634fa846fSZhang Yi case ES8326_BIAS_SW2: 33734fa846fSZhang Yi case ES8326_BIAS_SW3: 33834fa846fSZhang Yi case ES8326_BIAS_SW4: 33934fa846fSZhang Yi case ES8326_ADC_HPFS1: 34034fa846fSZhang Yi case ES8326_ADC_HPFS2: 34134fa846fSZhang Yi return false; 34234fa846fSZhang Yi default: 34334fa846fSZhang Yi return true; 34434fa846fSZhang Yi } 34534fa846fSZhang Yi } 34634fa846fSZhang Yi 3475c69f11cSYang Yingliang static const struct regmap_config es8326_regmap_config = { 3485c439937SZhu Ning .reg_bits = 8, 3495c439937SZhu Ning .val_bits = 8, 3505c439937SZhu Ning .max_register = 0xff, 35134fa846fSZhang Yi .use_single_read = true, 35234fa846fSZhang Yi .use_single_write = true, 353f1230a27SZhu Ning .volatile_reg = es8326_volatile_register, 35434fa846fSZhang Yi .writeable_reg = es8326_writeable_register, 3555c439937SZhu Ning .cache_type = REGCACHE_RBTREE, 3565c439937SZhu Ning }; 3575c439937SZhu Ning 3585c439937SZhu Ning struct _coeff_div { 3595c439937SZhu Ning u16 fs; 3605c439937SZhu Ning u32 rate; 3615c439937SZhu Ning u32 mclk; 3625c439937SZhu Ning u8 reg4; 3635c439937SZhu Ning u8 reg5; 3645c439937SZhu Ning u8 reg6; 3655c439937SZhu Ning u8 reg7; 3665c439937SZhu Ning u8 reg8; 3675c439937SZhu Ning u8 reg9; 3685c439937SZhu Ning u8 rega; 3695c439937SZhu Ning u8 regb; 3705c439937SZhu Ning }; 3715c439937SZhu Ning 3725c439937SZhu Ning /* codec hifi mclk clock divider coefficients */ 3735c439937SZhu Ning /* {ratio, LRCK, MCLK, REG04, REG05, REG06, REG07, REG08, REG09, REG10, REG11} */ 374ee09084fSZhu Ning static const struct _coeff_div coeff_div_v0[] = { 375ee09084fSZhu Ning {64, 8000, 512000, 0x60, 0x01, 0x0F, 0x75, 0x0A, 0x1B, 0x1F, 0x7F}, 376ee09084fSZhu Ning {64, 16000, 1024000, 0x20, 0x00, 0x33, 0x35, 0x0A, 0x1B, 0x1F, 0x3F}, 377ee09084fSZhu Ning {64, 44100, 2822400, 0xE0, 0x00, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 378ee09084fSZhu Ning {64, 48000, 3072000, 0xE0, 0x00, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 379ee09084fSZhu Ning {128, 8000, 1024000, 0x60, 0x00, 0x33, 0x35, 0x0A, 0x1B, 0x1F, 0x7F}, 380ee09084fSZhu Ning {128, 16000, 2048000, 0x20, 0x00, 0x03, 0x35, 0x0A, 0x1B, 0x1F, 0x3F}, 381ee09084fSZhu Ning {128, 44100, 5644800, 0xE0, 0x01, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 382ee09084fSZhu Ning {128, 48000, 6144000, 0xE0, 0x01, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 3835c439937SZhu Ning 384ee09084fSZhu Ning {192, 32000, 6144000, 0xE0, 0x02, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 385ee09084fSZhu Ning {256, 8000, 2048000, 0x60, 0x00, 0x03, 0x35, 0x0A, 0x1B, 0x1F, 0x7F}, 386ee09084fSZhu Ning {256, 16000, 4096000, 0x20, 0x01, 0x03, 0x35, 0x0A, 0x1B, 0x1F, 0x3F}, 387ee09084fSZhu Ning {256, 44100, 11289600, 0xE0, 0x00, 0x30, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 388ee09084fSZhu Ning {256, 48000, 12288000, 0xE0, 0x00, 0x30, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 389ee09084fSZhu Ning {384, 32000, 12288000, 0xE0, 0x05, 0x03, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 390ee09084fSZhu Ning {400, 48000, 19200000, 0xE9, 0x04, 0x0F, 0x6d, 0x4A, 0x0A, 0x1F, 0x1F}, 3915c439937SZhu Ning 392ee09084fSZhu Ning {500, 48000, 24000000, 0xF8, 0x04, 0x3F, 0x6D, 0x4A, 0x0A, 0x1F, 0x1F}, 393ee09084fSZhu Ning {512, 8000, 4096000, 0x60, 0x01, 0x03, 0x35, 0x0A, 0x1B, 0x1F, 0x7F}, 394ee09084fSZhu Ning {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x0A, 0x1B, 0x1F, 0x3F}, 395ee09084fSZhu Ning {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 396ee09084fSZhu Ning {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 397ee09084fSZhu Ning {768, 32000, 24576000, 0xE0, 0x02, 0x30, 0x2D, 0x4A, 0x0A, 0x1F, 0x1F}, 398ee09084fSZhu Ning {1024, 8000, 8192000, 0x60, 0x00, 0x30, 0x35, 0x0A, 0x1B, 0x1F, 0x7F}, 3995c439937SZhu Ning {1024, 16000, 16384000, 0x20, 0x00, 0x00, 0x35, 0x0A, 0x1B, 0x1F, 0x3F}, 4005c439937SZhu Ning }; 4015c439937SZhu Ning 402ee09084fSZhu Ning static const struct _coeff_div coeff_div_v3[] = { 403ee09084fSZhu Ning {32, 8000, 256000, 0x60, 0x00, 0x0F, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 404ee09084fSZhu Ning {32, 16000, 512000, 0x20, 0x00, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x3F}, 405ee09084fSZhu Ning {32, 44100, 1411200, 0x00, 0x00, 0x13, 0x2D, 0x8A, 0x0A, 0x1F, 0x1F}, 406ee09084fSZhu Ning {32, 48000, 1536000, 0x00, 0x00, 0x13, 0x2D, 0x8A, 0x0A, 0x1F, 0x1F}, 407ee09084fSZhu Ning {36, 8000, 288000, 0x20, 0x00, 0x0D, 0x75, 0x8A, 0x1B, 0x23, 0x47}, 408ee09084fSZhu Ning {36, 16000, 576000, 0x20, 0x00, 0x0D, 0x75, 0x8A, 0x1B, 0x23, 0x47}, 409ee09084fSZhu Ning {48, 8000, 384000, 0x60, 0x02, 0x1F, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 410ee09084fSZhu Ning {48, 16000, 768000, 0x20, 0x02, 0x0F, 0x75, 0x8A, 0x1B, 0x1F, 0x3F}, 411ee09084fSZhu Ning {48, 48000, 2304000, 0x00, 0x02, 0x0D, 0x2D, 0x8A, 0x0A, 0x1F, 0x1F}, 412ee09084fSZhu Ning 413ee09084fSZhu Ning {64, 8000, 512000, 0x60, 0x00, 0x35, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 414ee09084fSZhu Ning {64, 16000, 1024000, 0x20, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x3F}, 415ee09084fSZhu Ning {64, 44100, 2822400, 0xE0, 0x00, 0x31, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 416ee09084fSZhu Ning {64, 48000, 3072000, 0xE0, 0x00, 0x31, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 417ee09084fSZhu Ning {72, 8000, 576000, 0x20, 0x00, 0x13, 0x35, 0x8A, 0x1B, 0x23, 0x47}, 418ee09084fSZhu Ning {72, 16000, 1152000, 0x20, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x23, 0x47}, 419ee09084fSZhu Ning {96, 8000, 768000, 0x60, 0x02, 0x1D, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 420ee09084fSZhu Ning {96, 16000, 1536000, 0x20, 0x02, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x3F}, 421ee09084fSZhu Ning {100, 48000, 4800000, 0x04, 0x04, 0x3F, 0x6D, 0xB8, 0x08, 0x4f, 0x1f}, 422ee09084fSZhu Ning {125, 48000, 6000000, 0x04, 0x04, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27}, 423ee09084fSZhu Ning 424ee09084fSZhu Ning {128, 8000, 1024000, 0x60, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 4254581468dSZhang Yi {128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x3F}, 4264581468dSZhang Yi {128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 4274581468dSZhang Yi {128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 428ee09084fSZhu Ning {144, 8000, 1152000, 0x20, 0x00, 0x03, 0x35, 0x8A, 0x1B, 0x23, 0x47}, 429ee09084fSZhu Ning {144, 16000, 2304000, 0x20, 0x00, 0x11, 0x35, 0x8A, 0x1B, 0x23, 0x47}, 430ee09084fSZhu Ning {192, 8000, 1536000, 0x60, 0x02, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 431ee09084fSZhu Ning {192, 32000, 6144000, 0xE0, 0x02, 0x31, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 432ee09084fSZhu Ning {192, 16000, 3072000, 0x20, 0x02, 0x05, 0x75, 0xCA, 0x1B, 0x1F, 0x3F}, 433ee09084fSZhu Ning 434ee09084fSZhu Ning {200, 48000, 9600000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 435ee09084fSZhu Ning {250, 48000, 12000000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x27, 0x27}, 4364581468dSZhang Yi {256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x7F}, 4374581468dSZhang Yi {256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x08, 0x19, 0x1F, 0x3F}, 4384581468dSZhang Yi {256, 44100, 11289600, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 4394581468dSZhang Yi {256, 48000, 12288000, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 440ee09084fSZhu Ning {288, 8000, 2304000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x23, 0x47}, 441ee09084fSZhu Ning {384, 8000, 3072000, 0x60, 0x02, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F}, 442ee09084fSZhu Ning {384, 16000, 6144000, 0x20, 0x02, 0x03, 0x35, 0x8A, 0x1B, 0x1F, 0x3F}, 443ee09084fSZhu Ning {384, 32000, 12288000, 0xE0, 0x02, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 444ee09084fSZhu Ning {384, 48000, 18432000, 0x00, 0x02, 0x01, 0x2D, 0x8A, 0x0A, 0x1F, 0x1F}, 445ee09084fSZhu Ning 446ee09084fSZhu Ning {400, 48000, 19200000, 0xE4, 0x04, 0x35, 0x6d, 0xCA, 0x0A, 0x1F, 0x1F}, 447ee09084fSZhu Ning {500, 48000, 24000000, 0xF8, 0x04, 0x3F, 0x6D, 0xCA, 0x0A, 0x1F, 0x1F}, 4484581468dSZhang Yi {512, 8000, 4096000, 0x60, 0x00, 0x01, 0x08, 0x19, 0x1B, 0x1F, 0x7F}, 4494581468dSZhang Yi {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x08, 0x19, 0x1F, 0x3F}, 4504581468dSZhang Yi {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 4514581468dSZhang Yi {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F}, 452ee09084fSZhu Ning {768, 8000, 6144000, 0x60, 0x02, 0x11, 0x35, 0x8A, 0x1B, 0x1F, 0x7F}, 453ee09084fSZhu Ning {768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F}, 454ee09084fSZhu Ning {768, 32000, 24576000, 0xE0, 0x02, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F}, 455ee09084fSZhu Ning {800, 48000, 38400000, 0x00, 0x18, 0x13, 0x2D, 0x8A, 0x0A, 0x1F, 0x1F}, 456ee09084fSZhu Ning 457ee09084fSZhu Ning {1024, 8000, 8192000, 0x60, 0x00, 0x30, 0x35, 0x8A, 0x1B, 0x1F, 0x7F}, 458ee09084fSZhu Ning {1024, 16000, 16384000, 0x20, 0x00, 0x00, 0x35, 0x8A, 0x1B, 0x1F, 0x3F}, 459ee09084fSZhu Ning {1152, 16000, 18432000, 0x20, 0x08, 0x11, 0x35, 0x8A, 0x1B, 0x1F, 0x3F}, 460ee09084fSZhu Ning {1536, 8000, 12288000, 0x60, 0x02, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x7F}, 461ee09084fSZhu Ning {1536, 16000, 24576000, 0x20, 0x02, 0x10, 0x35, 0x8A, 0x1B, 0x1F, 0x3F}, 462ee09084fSZhu Ning {1625, 8000, 13000000, 0x0C, 0x18, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27}, 463ee09084fSZhu Ning {1625, 16000, 26000000, 0x0C, 0x18, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27}, 464ee09084fSZhu Ning {2048, 8000, 16384000, 0x60, 0x00, 0x00, 0x35, 0x8A, 0x1B, 0x1F, 0x7F}, 465ee09084fSZhu Ning {2304, 8000, 18432000, 0x40, 0x02, 0x10, 0x35, 0x8A, 0x1B, 0x1F, 0x5F}, 466ee09084fSZhu Ning {3072, 8000, 24576000, 0x60, 0x02, 0x10, 0x35, 0x8A, 0x1B, 0x1F, 0x7F}, 467ee09084fSZhu Ning {3250, 8000, 26000000, 0x0C, 0x18, 0x0F, 0x2D, 0x8A, 0x0A, 0x27, 0x27}, 468ee09084fSZhu Ning }; 469ee09084fSZhu Ning 470ee09084fSZhu Ning static inline int get_coeff(int mclk, int rate, int array, 471ee09084fSZhu Ning const struct _coeff_div *coeff_div) 4725c439937SZhu Ning { 4735c439937SZhu Ning int i; 4745c439937SZhu Ning 475ee09084fSZhu Ning for (i = 0; i < array; i++) { 4765c439937SZhu Ning if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 4775c439937SZhu Ning return i; 4785c439937SZhu Ning } 4795c439937SZhu Ning 4805c439937SZhu Ning return -EINVAL; 4815c439937SZhu Ning } 4825c439937SZhu Ning 4835c439937SZhu Ning static int es8326_set_dai_sysclk(struct snd_soc_dai *codec_dai, 4845c439937SZhu Ning int clk_id, unsigned int freq, int dir) 4855c439937SZhu Ning { 4865c439937SZhu Ning struct snd_soc_component *codec = codec_dai->component; 4875c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(codec); 4885c439937SZhu Ning 4895c439937SZhu Ning es8326->sysclk = freq; 4905c439937SZhu Ning 4915c439937SZhu Ning return 0; 4925c439937SZhu Ning } 4935c439937SZhu Ning 4945c439937SZhu Ning static int es8326_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 4955c439937SZhu Ning { 4965c439937SZhu Ning struct snd_soc_component *component = codec_dai->component; 4975c439937SZhu Ning u8 iface = 0; 4985c439937SZhu Ning 4995c439937SZhu Ning switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 5005c439937SZhu Ning case SND_SOC_DAIFMT_CBC_CFP: 5015c439937SZhu Ning snd_soc_component_update_bits(component, ES8326_RESET, 5025c439937SZhu Ning ES8326_MASTER_MODE_EN, ES8326_MASTER_MODE_EN); 5035c439937SZhu Ning break; 5045c439937SZhu Ning case SND_SOC_DAIFMT_CBC_CFC: 5055c439937SZhu Ning break; 5065c439937SZhu Ning default: 5075c439937SZhu Ning return -EINVAL; 5085c439937SZhu Ning } 5095c439937SZhu Ning 5105c439937SZhu Ning /* interface format */ 5115c439937SZhu Ning switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 5125c439937SZhu Ning case SND_SOC_DAIFMT_I2S: 5135c439937SZhu Ning break; 5145c439937SZhu Ning case SND_SOC_DAIFMT_RIGHT_J: 5155c439937SZhu Ning dev_err(component->dev, "Codec driver does not support right justified\n"); 5165c439937SZhu Ning return -EINVAL; 5175c439937SZhu Ning case SND_SOC_DAIFMT_LEFT_J: 5185c439937SZhu Ning iface |= ES8326_DAIFMT_LEFT_J; 5195c439937SZhu Ning break; 5205c439937SZhu Ning case SND_SOC_DAIFMT_DSP_A: 5215c439937SZhu Ning iface |= ES8326_DAIFMT_DSP_A; 5225c439937SZhu Ning break; 5235c439937SZhu Ning case SND_SOC_DAIFMT_DSP_B: 5245c439937SZhu Ning iface |= ES8326_DAIFMT_DSP_B; 5255c439937SZhu Ning break; 5265c439937SZhu Ning default: 5275c439937SZhu Ning return -EINVAL; 5285c439937SZhu Ning } 5295c439937SZhu Ning 5305c439937SZhu Ning snd_soc_component_update_bits(component, ES8326_FMT, ES8326_DAIFMT_MASK, iface); 5315c439937SZhu Ning 5325c439937SZhu Ning return 0; 5335c439937SZhu Ning } 5345c439937SZhu Ning 5355c439937SZhu Ning static int es8326_pcm_hw_params(struct snd_pcm_substream *substream, 5365c439937SZhu Ning struct snd_pcm_hw_params *params, 5375c439937SZhu Ning struct snd_soc_dai *dai) 5385c439937SZhu Ning { 5395c439937SZhu Ning struct snd_soc_component *component = dai->component; 540ee09084fSZhu Ning const struct _coeff_div *coeff_div; 5415c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 5425c439937SZhu Ning u8 srate = 0; 543ee09084fSZhu Ning int coeff, array; 5445c439937SZhu Ning 545ee09084fSZhu Ning if (es8326->version == 0) { 546ee09084fSZhu Ning coeff_div = coeff_div_v0; 547ee09084fSZhu Ning array = ARRAY_SIZE(coeff_div_v0); 548ee09084fSZhu Ning } else { 549ee09084fSZhu Ning coeff_div = coeff_div_v3; 550ee09084fSZhu Ning array = ARRAY_SIZE(coeff_div_v3); 551ee09084fSZhu Ning } 552ee09084fSZhu Ning coeff = get_coeff(es8326->sysclk, params_rate(params), array, coeff_div); 5535c439937SZhu Ning /* bit size */ 5545c439937SZhu Ning switch (params_format(params)) { 5555c439937SZhu Ning case SNDRV_PCM_FORMAT_S16_LE: 5565c439937SZhu Ning srate |= ES8326_S16_LE; 5575c439937SZhu Ning break; 5585c439937SZhu Ning case SNDRV_PCM_FORMAT_S20_3LE: 5595c439937SZhu Ning srate |= ES8326_S20_3_LE; 5605c439937SZhu Ning break; 5615c439937SZhu Ning case SNDRV_PCM_FORMAT_S18_3LE: 5625c439937SZhu Ning srate |= ES8326_S18_LE; 5635c439937SZhu Ning break; 5645c439937SZhu Ning case SNDRV_PCM_FORMAT_S24_LE: 5655c439937SZhu Ning srate |= ES8326_S24_LE; 5665c439937SZhu Ning break; 5675c439937SZhu Ning case SNDRV_PCM_FORMAT_S32_LE: 5685c439937SZhu Ning srate |= ES8326_S32_LE; 5695c439937SZhu Ning break; 5705c439937SZhu Ning default: 5715c439937SZhu Ning return -EINVAL; 5725c439937SZhu Ning } 5735c439937SZhu Ning 5745c439937SZhu Ning /* set iface & srate */ 5755c439937SZhu Ning snd_soc_component_update_bits(component, ES8326_FMT, ES8326_DATA_LEN_MASK, srate); 5765c439937SZhu Ning 5775c439937SZhu Ning if (coeff >= 0) { 5785c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DIV1, 5795c439937SZhu Ning coeff_div[coeff].reg4); 5805c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DIV2, 5815c439937SZhu Ning coeff_div[coeff].reg5); 5825c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DLL, 5835c439937SZhu Ning coeff_div[coeff].reg6); 5845c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_MUX, 5855c439937SZhu Ning coeff_div[coeff].reg7); 5865c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_ADC_SEL, 5875c439937SZhu Ning coeff_div[coeff].reg8); 5885c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DAC_SEL, 5895c439937SZhu Ning coeff_div[coeff].reg9); 5905c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_ADC_OSR, 5915c439937SZhu Ning coeff_div[coeff].rega); 5925c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DAC_OSR, 5935c439937SZhu Ning coeff_div[coeff].regb); 5945c439937SZhu Ning } else { 5955c439937SZhu Ning dev_warn(component->dev, "Clock coefficients do not match"); 5965c439937SZhu Ning } 5975c439937SZhu Ning 5985c439937SZhu Ning return 0; 5995c439937SZhu Ning } 6005c439937SZhu Ning 601083912c2SZhu Ning static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction) 602083912c2SZhu Ning { 603083912c2SZhu Ning struct snd_soc_component *component = dai->component; 604083912c2SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 6050663286eSZhu Ning unsigned int offset_l, offset_r; 606083912c2SZhu Ning 607083912c2SZhu Ning if (mute) { 6088c99a0a6SZhu Ning if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 609083912c2SZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF); 610083912c2SZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, 611083912c2SZhu Ning ES8326_MUTE_MASK, ES8326_MUTE); 612a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 613a3aa9255SZhu Ning 0x30, 0x00); 614083912c2SZhu Ning } else { 6158c99a0a6SZhu Ning regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, 6168c99a0a6SZhu Ning 0x0F, 0x0F); 6178c99a0a6SZhu Ning } 6188c99a0a6SZhu Ning } else { 619083912c2SZhu Ning if (!es8326->calibrated) { 620083912c2SZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_FORCE_CAL); 621083912c2SZhu Ning msleep(30); 6220663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF); 6230663286eSZhu Ning regmap_read(es8326->regmap, ES8326_HPL_OFFSET_INI, &offset_l); 6240663286eSZhu Ning regmap_read(es8326->regmap, ES8326_HPR_OFFSET_INI, &offset_r); 6250663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c); 6260663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HPL_OFFSET_INI, offset_l); 6270663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r); 628083912c2SZhu Ning es8326->calibrated = true; 629083912c2SZhu Ning } 6308c99a0a6SZhu Ning if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 631a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x01); 632a3aa9255SZhu Ning usleep_range(1000, 5000); 633a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x00); 634a3aa9255SZhu Ning usleep_range(1000, 5000); 635a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x30, 0x20); 636a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x30, 0x30); 637fc702b2cSZhu Ning regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa1); 638083912c2SZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_ON); 639083912c2SZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, 640083912c2SZhu Ning ES8326_MUTE_MASK, ~(ES8326_MUTE)); 6418c99a0a6SZhu Ning } else { 6428c99a0a6SZhu Ning msleep(300); 6438c99a0a6SZhu Ning regmap_update_bits(es8326->regmap, ES8326_ADC_MUTE, 6448c99a0a6SZhu Ning 0x0F, 0x00); 6458c99a0a6SZhu Ning } 646083912c2SZhu Ning } 647083912c2SZhu Ning return 0; 648083912c2SZhu Ning } 649083912c2SZhu Ning 6505c439937SZhu Ning static int es8326_set_bias_level(struct snd_soc_component *codec, 6515c439937SZhu Ning enum snd_soc_bias_level level) 6525c439937SZhu Ning { 6535c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(codec); 6545c439937SZhu Ning int ret; 6555c439937SZhu Ning 6565c439937SZhu Ning switch (level) { 6575c439937SZhu Ning case SND_SOC_BIAS_ON: 6585c439937SZhu Ning ret = clk_prepare_enable(es8326->mclk); 6595c439937SZhu Ning if (ret) 6605c439937SZhu Ning return ret; 6610663286eSZhu Ning 662a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x02); 663a3aa9255SZhu Ning usleep_range(5000, 10000); 6640663286eSZhu Ning regmap_write(es8326->regmap, ES8326_INTOUT_IO, es8326->interrupt_clk); 6655c439937SZhu Ning regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, 6665c439937SZhu Ning (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT)); 6675c439937SZhu Ning regmap_write(es8326->regmap, ES8326_PGA_PDN, 0x40); 6680663286eSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); 6690663286eSZhu Ning regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x20); 670a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_RESET, 0x02, 0x00); 6715c439937SZhu Ning break; 6725c439937SZhu Ning case SND_SOC_BIAS_PREPARE: 6735c439937SZhu Ning break; 6745c439937SZhu Ning case SND_SOC_BIAS_STANDBY: 6750663286eSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); 6760663286eSZhu Ning regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00); 6775c439937SZhu Ning regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT); 6785c439937SZhu Ning break; 679fc702b2cSZhu Ning case SND_SOC_BIAS_OFF: 680fc702b2cSZhu Ning clk_disable_unprepare(es8326->mclk); 681fc702b2cSZhu Ning break; 6825c439937SZhu Ning } 6835c439937SZhu Ning 6845c439937SZhu Ning return 0; 6855c439937SZhu Ning } 6865c439937SZhu Ning 6875c439937SZhu Ning #define es8326_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 6885c439937SZhu Ning SNDRV_PCM_FMTBIT_S24_LE) 6895c439937SZhu Ning 6905c439937SZhu Ning static const struct snd_soc_dai_ops es8326_ops = { 6915c439937SZhu Ning .hw_params = es8326_pcm_hw_params, 6925c439937SZhu Ning .set_fmt = es8326_set_dai_fmt, 6935c439937SZhu Ning .set_sysclk = es8326_set_dai_sysclk, 694083912c2SZhu Ning .mute_stream = es8326_mute, 6958c99a0a6SZhu Ning .no_capture_mute = 0, 6965c439937SZhu Ning }; 6975c439937SZhu Ning 6985c439937SZhu Ning static struct snd_soc_dai_driver es8326_dai = { 6995c439937SZhu Ning .name = "ES8326 HiFi", 7005c439937SZhu Ning .playback = { 7015c439937SZhu Ning .stream_name = "Playback", 7025c439937SZhu Ning .channels_min = 1, 7035c439937SZhu Ning .channels_max = 2, 7045c439937SZhu Ning .rates = SNDRV_PCM_RATE_8000_48000, 7055c439937SZhu Ning .formats = es8326_FORMATS, 7065c439937SZhu Ning }, 7075c439937SZhu Ning .capture = { 7085c439937SZhu Ning .stream_name = "Capture", 7095c439937SZhu Ning .channels_min = 1, 7105c439937SZhu Ning .channels_max = 2, 7115c439937SZhu Ning .rates = SNDRV_PCM_RATE_8000_48000, 7125c439937SZhu Ning .formats = es8326_FORMATS, 7135c439937SZhu Ning }, 7145c439937SZhu Ning .ops = &es8326_ops, 7155c439937SZhu Ning .symmetric_rate = 1, 7165c439937SZhu Ning }; 7175c439937SZhu Ning 7185c439937SZhu Ning static void es8326_enable_micbias(struct snd_soc_component *component) 7195c439937SZhu Ning { 7205c439937SZhu Ning struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 7215c439937SZhu Ning 7225c439937SZhu Ning snd_soc_dapm_mutex_lock(dapm); 7235c439937SZhu Ning snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS1"); 7245c439937SZhu Ning snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS2"); 7255c439937SZhu Ning snd_soc_dapm_sync_unlocked(dapm); 7265c439937SZhu Ning snd_soc_dapm_mutex_unlock(dapm); 7275c439937SZhu Ning } 7285c439937SZhu Ning 7295c439937SZhu Ning static void es8326_disable_micbias(struct snd_soc_component *component) 7305c439937SZhu Ning { 7315c439937SZhu Ning struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 7325c439937SZhu Ning 7335c439937SZhu Ning snd_soc_dapm_mutex_lock(dapm); 7345c439937SZhu Ning snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS1"); 7355c439937SZhu Ning snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS2"); 7365c439937SZhu Ning snd_soc_dapm_sync_unlocked(dapm); 7375c439937SZhu Ning snd_soc_dapm_mutex_unlock(dapm); 7385c439937SZhu Ning } 7395c439937SZhu Ning 7405c439937SZhu Ning /* 7415c439937SZhu Ning * For button detection, set the following in soundcard 7425c439937SZhu Ning * snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 7435c439937SZhu Ning * snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); 7445c439937SZhu Ning * snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); 7455c439937SZhu Ning */ 7465c439937SZhu Ning static void es8326_jack_button_handler(struct work_struct *work) 7475c439937SZhu Ning { 7485c439937SZhu Ning struct es8326_priv *es8326 = 7495c439937SZhu Ning container_of(work, struct es8326_priv, button_press_work.work); 7505c439937SZhu Ning struct snd_soc_component *comp = es8326->component; 7515c439937SZhu Ning unsigned int iface; 7525c439937SZhu Ning static int button_to_report, press_count; 7535c439937SZhu Ning static int prev_button, cur_button; 7545c439937SZhu Ning 7555c439937SZhu Ning if (!(es8326->jack->status & SND_JACK_HEADSET)) /* Jack unplugged */ 7565c439937SZhu Ning return; 7575c439937SZhu Ning 7585c439937SZhu Ning mutex_lock(&es8326->lock); 7594ddad00cSZhu Ning iface = snd_soc_component_read(comp, ES8326_HPDET_STA); 7605c439937SZhu Ning switch (iface) { 7615c439937SZhu Ning case 0x93: 7625c439937SZhu Ning /* pause button detected */ 7635c439937SZhu Ning cur_button = SND_JACK_BTN_0; 7645c439937SZhu Ning break; 7655c439937SZhu Ning case 0x6f: 76604f96c93SZhu Ning case 0x4b: 7675c439937SZhu Ning /* button volume up */ 7685c439937SZhu Ning cur_button = SND_JACK_BTN_1; 7695c439937SZhu Ning break; 7705c439937SZhu Ning case 0x27: 7715c439937SZhu Ning /* button volume down */ 7725c439937SZhu Ning cur_button = SND_JACK_BTN_2; 7735c439937SZhu Ning break; 7745c439937SZhu Ning case 0x1e: 77504f96c93SZhu Ning case 0xe2: 7765c439937SZhu Ning /* button released or not pressed */ 7775c439937SZhu Ning cur_button = 0; 7785c439937SZhu Ning break; 7795c439937SZhu Ning default: 7805c439937SZhu Ning break; 7815c439937SZhu Ning } 7825c439937SZhu Ning 7835c439937SZhu Ning if ((prev_button == cur_button) && (cur_button != 0)) { 7845c439937SZhu Ning press_count++; 78504f96c93SZhu Ning if (press_count > 3) { 78604f96c93SZhu Ning /* report a press every 120ms */ 7875c439937SZhu Ning snd_soc_jack_report(es8326->jack, cur_button, 7885c439937SZhu Ning SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); 7895c439937SZhu Ning press_count = 0; 7905c439937SZhu Ning } 7915c439937SZhu Ning button_to_report = cur_button; 7925c439937SZhu Ning queue_delayed_work(system_wq, &es8326->button_press_work, 79304f96c93SZhu Ning msecs_to_jiffies(35)); 7945c439937SZhu Ning } else if (prev_button != cur_button) { 7955c439937SZhu Ning /* mismatch, detect again */ 7965c439937SZhu Ning prev_button = cur_button; 7975c439937SZhu Ning queue_delayed_work(system_wq, &es8326->button_press_work, 79804f96c93SZhu Ning msecs_to_jiffies(35)); 7995c439937SZhu Ning } else { 8005c439937SZhu Ning /* released or no pressed */ 8015c439937SZhu Ning if (button_to_report != 0) { 8025c439937SZhu Ning snd_soc_jack_report(es8326->jack, button_to_report, 8035c439937SZhu Ning SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); 8045c439937SZhu Ning snd_soc_jack_report(es8326->jack, 0, 8055c439937SZhu Ning SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); 8065c439937SZhu Ning button_to_report = 0; 8075c439937SZhu Ning } 8085c439937SZhu Ning } 8095c439937SZhu Ning mutex_unlock(&es8326->lock); 8105c439937SZhu Ning } 8115c439937SZhu Ning 8125c439937SZhu Ning static void es8326_jack_detect_handler(struct work_struct *work) 8135c439937SZhu Ning { 8145c439937SZhu Ning struct es8326_priv *es8326 = 8155c439937SZhu Ning container_of(work, struct es8326_priv, jack_detect_work.work); 8165c439937SZhu Ning struct snd_soc_component *comp = es8326->component; 8175c439937SZhu Ning unsigned int iface; 8185c439937SZhu Ning 8195c439937SZhu Ning mutex_lock(&es8326->lock); 8204ddad00cSZhu Ning iface = snd_soc_component_read(comp, ES8326_HPDET_STA); 8215c439937SZhu Ning dev_dbg(comp->dev, "gpio flag %#04x", iface); 82204f96c93SZhu Ning 823ee09084fSZhu Ning if ((es8326->jack_remove_retry == 1) && (es8326->version != ES8326_VERSION_B)) { 82404f96c93SZhu Ning if (iface & ES8326_HPINSERT_FLAG) 82504f96c93SZhu Ning es8326->jack_remove_retry = 2; 82604f96c93SZhu Ning else 82704f96c93SZhu Ning es8326->jack_remove_retry = 0; 82804f96c93SZhu Ning 82904f96c93SZhu Ning dev_dbg(comp->dev, "remove event check, set HPJACK_POL normal, cnt = %d\n", 83004f96c93SZhu Ning es8326->jack_remove_retry); 83104f96c93SZhu Ning /* 83204f96c93SZhu Ning * Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event 83304f96c93SZhu Ning */ 83404f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 83504f96c93SZhu Ning ES8326_HP_DET_JACK_POL, (es8326->jd_inverted ? 83604f96c93SZhu Ning ~es8326->jack_pol : es8326->jack_pol)); 83704f96c93SZhu Ning goto exit; 83804f96c93SZhu Ning } 83904f96c93SZhu Ning 8405c439937SZhu Ning if ((iface & ES8326_HPINSERT_FLAG) == 0) { 8415c439937SZhu Ning /* Jack unplugged or spurious IRQ */ 84204f96c93SZhu Ning dev_dbg(comp->dev, "No headset detected\n"); 84304f96c93SZhu Ning es8326_disable_micbias(es8326->component); 8445c439937SZhu Ning if (es8326->jack->status & SND_JACK_HEADPHONE) { 84504f96c93SZhu Ning dev_dbg(comp->dev, "Report hp remove event\n"); 846*4684a2dfSZhang Yi snd_soc_jack_report(es8326->jack, 0, 847*4684a2dfSZhang Yi SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); 8485c439937SZhu Ning snd_soc_jack_report(es8326->jack, 0, SND_JACK_HEADSET); 84904f96c93SZhu Ning /* mute adc when mic path switch */ 85004f96c93SZhu Ning regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44); 85104f96c93SZhu Ning regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66); 85204f96c93SZhu Ning } 853714f5df0SZhang Yi es8326->hp = 0; 85404f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); 85514a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a); 85614a0a1ecSZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03); 8578a655ceeSZhang Yi regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); 85804f96c93SZhu Ning /* 85904f96c93SZhu Ning * Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event 86004f96c93SZhu Ning */ 861ee09084fSZhu Ning if ((es8326->jack_remove_retry == 0) && (es8326->version != ES8326_VERSION_B)) { 86204f96c93SZhu Ning es8326->jack_remove_retry = 1; 86304f96c93SZhu Ning dev_dbg(comp->dev, "remove event check, invert HPJACK_POL, cnt = %d\n", 86404f96c93SZhu Ning es8326->jack_remove_retry); 86504f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 86604f96c93SZhu Ning ES8326_HP_DET_JACK_POL, (es8326->jd_inverted ? 86704f96c93SZhu Ning es8326->jack_pol : ~es8326->jack_pol)); 86804f96c93SZhu Ning 86904f96c93SZhu Ning } else { 87004f96c93SZhu Ning es8326->jack_remove_retry = 0; 8715c439937SZhu Ning } 8725c439937SZhu Ning } else if ((iface & ES8326_HPINSERT_FLAG) == ES8326_HPINSERT_FLAG) { 87304f96c93SZhu Ning es8326->jack_remove_retry = 0; 87404f96c93SZhu Ning if (es8326->hp == 0) { 87504f96c93SZhu Ning dev_dbg(comp->dev, "First insert, start OMTP/CTIA type check\n"); 87604f96c93SZhu Ning /* 8778a81491aSZhu Ning * set auto-check mode, then restart jack_detect_work after 400ms. 87804f96c93SZhu Ning * Don't report jack status. 87904f96c93SZhu Ning */ 880b7c40988SZhang Yi regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00); 88104f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); 882b7c40988SZhang Yi regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00); 883a3aa9255SZhu Ning es8326_enable_micbias(es8326->component); 88404f96c93SZhu Ning usleep_range(50000, 70000); 88504f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); 886b7c40988SZhang Yi regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10); 887b7c40988SZhang Yi usleep_range(50000, 70000); 888b7c40988SZhang Yi regmap_write(es8326->regmap, ES8326_INT_SOURCE, 889b7c40988SZhang Yi (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); 89014a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f); 89114a0a1ecSZhu Ning regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08); 89204f96c93SZhu Ning queue_delayed_work(system_wq, &es8326->jack_detect_work, 8938a81491aSZhu Ning msecs_to_jiffies(400)); 89404f96c93SZhu Ning es8326->hp = 1; 89504f96c93SZhu Ning goto exit; 89604f96c93SZhu Ning } 8975c439937SZhu Ning if (es8326->jack->status & SND_JACK_HEADSET) { 8985c439937SZhu Ning /* detect button */ 89904f96c93SZhu Ning dev_dbg(comp->dev, "button pressed\n"); 9004eed7819SZhang Yi regmap_write(es8326->regmap, ES8326_INT_SOURCE, 9014eed7819SZhang Yi (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); 9025c439937SZhu Ning queue_delayed_work(system_wq, &es8326->button_press_work, 10); 90304f96c93SZhu Ning goto exit; 90404f96c93SZhu Ning } 90504f96c93SZhu Ning if ((iface & ES8326_HPBUTTON_FLAG) == 0x01) { 90604f96c93SZhu Ning dev_dbg(comp->dev, "Headphone detected\n"); 9075c439937SZhu Ning snd_soc_jack_report(es8326->jack, 9085c439937SZhu Ning SND_JACK_HEADPHONE, SND_JACK_HEADSET); 90904f96c93SZhu Ning } else { 91004f96c93SZhu Ning dev_dbg(comp->dev, "Headset detected\n"); 91104f96c93SZhu Ning snd_soc_jack_report(es8326->jack, 91204f96c93SZhu Ning SND_JACK_HEADSET, SND_JACK_HEADSET); 91304f96c93SZhu Ning 91404f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_PGA_PDN, 91504f96c93SZhu Ning 0x08, 0x08); 91604f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_PGAGAIN, 91704f96c93SZhu Ning 0x80, 0x80); 91804f96c93SZhu Ning regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x00); 91904f96c93SZhu Ning regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x00); 92004f96c93SZhu Ning regmap_update_bits(es8326->regmap, ES8326_PGA_PDN, 92104f96c93SZhu Ning 0x08, 0x00); 92204f96c93SZhu Ning usleep_range(10000, 15000); 9235c439937SZhu Ning } 9245c439937SZhu Ning } 92504f96c93SZhu Ning exit: 9265c439937SZhu Ning mutex_unlock(&es8326->lock); 9275c439937SZhu Ning } 9285c439937SZhu Ning 9295c439937SZhu Ning static irqreturn_t es8326_irq(int irq, void *dev_id) 9305c439937SZhu Ning { 9315c439937SZhu Ning struct es8326_priv *es8326 = dev_id; 9325c439937SZhu Ning 9335c439937SZhu Ning if (!es8326->jack) 9345c439937SZhu Ning goto out; 9355c439937SZhu Ning 9365c439937SZhu Ning if (es8326->jack->status & SND_JACK_HEADSET) 9375c439937SZhu Ning queue_delayed_work(system_wq, &es8326->jack_detect_work, 9385c439937SZhu Ning msecs_to_jiffies(10)); 9395c439937SZhu Ning else 9405c439937SZhu Ning queue_delayed_work(system_wq, &es8326->jack_detect_work, 9418a81491aSZhu Ning msecs_to_jiffies(300)); 9425c439937SZhu Ning 9435c439937SZhu Ning out: 9445c439937SZhu Ning return IRQ_HANDLED; 9455c439937SZhu Ning } 9465c439937SZhu Ning 9470663286eSZhu Ning static int es8326_calibrate(struct snd_soc_component *component) 9480663286eSZhu Ning { 9490663286eSZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 9500663286eSZhu Ning unsigned int reg; 9510663286eSZhu Ning unsigned int offset_l, offset_r; 9520663286eSZhu Ning 9530663286eSZhu Ning regmap_read(es8326->regmap, ES8326_CHIP_VERSION, ®); 9540663286eSZhu Ning es8326->version = reg; 9550663286eSZhu Ning 9560663286eSZhu Ning if ((es8326->version == ES8326_VERSION_B) && (es8326->calibrated == false)) { 9570663286eSZhu Ning dev_dbg(component->dev, "ES8326_VERSION_B, calibrating\n"); 9580663286eSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_INV, 0xc0); 95914a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x03); 9600663286eSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DLL, 0x30); 9610663286eSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_MUX, 0xed); 962fc702b2cSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DAC_SEL, 0x08); 9630663286eSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_TRI, 0xc1); 9640663286eSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_MUTE, 0x03); 9650663286eSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_VSEL, 0x7f); 96614a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_VMIDLOW, 0x23); 9670663286eSZhu Ning regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x88); 968fc702b2cSZhu Ning usleep_range(15000, 20000); 9690663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c); 970fc702b2cSZhu Ning usleep_range(15000, 20000); 9710663286eSZhu Ning regmap_write(es8326->regmap, ES8326_RESET, 0xc0); 9720663286eSZhu Ning usleep_range(15000, 20000); 9730663286eSZhu Ning 9740663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, ES8326_HP_OFF); 9750663286eSZhu Ning regmap_read(es8326->regmap, ES8326_CSM_MUTE_STA, ®); 9760663286eSZhu Ning if ((reg & 0xf0) != 0x40) 9770663286eSZhu Ning msleep(50); 9780663286eSZhu Ning 9790663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, 0xd4); 9800663286eSZhu Ning msleep(200); 9810663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, 0x4d); 9820663286eSZhu Ning msleep(200); 9830663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF); 9840663286eSZhu Ning regmap_read(es8326->regmap, ES8326_HPL_OFFSET_INI, &offset_l); 9850663286eSZhu Ning regmap_read(es8326->regmap, ES8326_HPR_OFFSET_INI, &offset_r); 9860663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c); 9870663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HPL_OFFSET_INI, offset_l); 9880663286eSZhu Ning regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r); 9890663286eSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_INV, 0x00); 9900663286eSZhu Ning 9910663286eSZhu Ning es8326->calibrated = true; 9920663286eSZhu Ning } 9930663286eSZhu Ning 9940663286eSZhu Ning return 0; 9950663286eSZhu Ning } 9960663286eSZhu Ning 9977e7dbdeeSZhang Yi static void es8326_init(struct snd_soc_component *component) 9985c439937SZhu Ning { 9995c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 10005c439937SZhu Ning 1001ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_RESET, 0x1f); 1002ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E); 100314a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0); 1004ac20a73dSZhu Ning usleep_range(10000, 15000); 10058a655ceeSZhang Yi regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xd9); 1006714f5df0SZhang Yi regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0xd8); 1007ac20a73dSZhu Ning /* set headphone default type and detect pin */ 1008fc702b2cSZhu Ning regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x83); 1009ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_RESAMPLE, 0x05); 10105c439937SZhu Ning 1011ac20a73dSZhu Ning /* set internal oscillator as clock source of headpone cp */ 1012fc702b2cSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_DIV_CPC, 0x89); 1013ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_ON); 1014ac20a73dSZhu Ning /* clock manager reset release */ 1015ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_RESET, 0x17); 1016ac20a73dSZhu Ning /* set headphone detection as half scan mode */ 101714a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_HP_MISC, 0x3d); 1018ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_PULLUP_CTL, 0x00); 1019ac20a73dSZhu Ning 1020ac20a73dSZhu Ning /* enable headphone driver */ 102114a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_HP_VOL, 0xc4); 1022ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa7); 1023ac20a73dSZhu Ning usleep_range(2000, 5000); 102414a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0x23); 102514a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_HP_DRIVER_REF, 0x33); 1026ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa1); 1027ac20a73dSZhu Ning 1028ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_INV, 0x00); 1029ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_VMIDS1, 0xc4); 1030ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_VMIDS2, 0x81); 1031ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CLK_CAL_TIME, 0x00); 10320663286eSZhu Ning /* calibrate for B version */ 10330663286eSZhu Ning es8326_calibrate(component); 1034523d242dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_CROSSTALK, 0xaa); 1035523d242dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_RAMPRATE, 0x00); 1036ac20a73dSZhu Ning /* turn off headphone out */ 1037ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_HP_CAL, 0x00); 1038ac20a73dSZhu Ning /* set ADC and DAC in low power mode */ 1039ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0); 1040ac20a73dSZhu Ning 10415c439937SZhu Ning regmap_write(es8326->regmap, ES8326_ANA_VSEL, 0x7F); 1042ac20a73dSZhu Ning /* select vdda as micbias source */ 1043714f5df0SZhang Yi regmap_write(es8326->regmap, ES8326_VMIDLOW, 0x03); 1044ac20a73dSZhu Ning /* set dac dsmclip = 1 */ 1045ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_DSM, 0x08); 1046ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_DAC_VPPSCALE, 0x15); 1047ac20a73dSZhu Ning 1048a3aa9255SZhu Ning regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x80 | 1049a3aa9255SZhu Ning ((es8326->version == ES8326_VERSION_B) ? 1050a3aa9255SZhu Ning (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol) : 1051a3aa9255SZhu Ning (ES8326_HP_DET_SRC_PIN9 | es8326->jack_pol | 0x04))); 1052a3aa9255SZhu Ning usleep_range(5000, 10000); 1053a3aa9255SZhu Ning es8326_enable_micbias(es8326->component); 1054a3aa9255SZhu Ning usleep_range(50000, 70000); 1055a3aa9255SZhu Ning regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); 1056ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_INTOUT_IO, 1057ac20a73dSZhu Ning es8326->interrupt_clk); 1058ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, 1059ac20a73dSZhu Ning (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT)); 1060ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_SDINOUT23_IO, ES8326_IO_INPUT); 1061ac20a73dSZhu Ning 106214a0a1ecSZhu Ning regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); 1063ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_RESET, ES8326_CSM_ON); 1064ac20a73dSZhu Ning regmap_update_bits(es8326->regmap, ES8326_PGAGAIN, ES8326_MIC_SEL_MASK, 1065ac20a73dSZhu Ning ES8326_MIC1_SEL); 1066ac20a73dSZhu Ning 1067ac20a73dSZhu Ning regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE, ES8326_MUTE_MASK, 1068ac20a73dSZhu Ning ES8326_MUTE); 1069ac20a73dSZhu Ning 10708c99a0a6SZhu Ning regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); 10717e7dbdeeSZhang Yi regmap_write(es8326->regmap, ES8326_CLK_DIV_LRCK, 0xff); 10727e7dbdeeSZhang Yi 10737e7dbdeeSZhang Yi msleep(200); 10747e7dbdeeSZhang Yi regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); 10757e7dbdeeSZhang Yi } 10767e7dbdeeSZhang Yi 10777e7dbdeeSZhang Yi static int es8326_resume(struct snd_soc_component *component) 10787e7dbdeeSZhang Yi { 10797e7dbdeeSZhang Yi struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 10807e7dbdeeSZhang Yi unsigned int reg; 10817e7dbdeeSZhang Yi 10827e7dbdeeSZhang Yi regcache_cache_only(es8326->regmap, false); 10837e7dbdeeSZhang Yi regcache_cache_bypass(es8326->regmap, true); 10847e7dbdeeSZhang Yi regmap_read(es8326->regmap, ES8326_CLK_RESAMPLE, ®); 10857e7dbdeeSZhang Yi regcache_cache_bypass(es8326->regmap, false); 10867e7dbdeeSZhang Yi /* reset internal clock state */ 10877e7dbdeeSZhang Yi if (reg == 0x05) 10887e7dbdeeSZhang Yi regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_ON); 10897e7dbdeeSZhang Yi else 10907e7dbdeeSZhang Yi es8326_init(component); 10917e7dbdeeSZhang Yi 10927e7dbdeeSZhang Yi regcache_sync(es8326->regmap); 10935c439937SZhu Ning 10946e5f5bf8SZhang Yi es8326_irq(es8326->irq, es8326); 10955c439937SZhu Ning return 0; 10965c439937SZhu Ning } 10975c439937SZhu Ning 10985c439937SZhu Ning static int es8326_suspend(struct snd_soc_component *component) 10995c439937SZhu Ning { 11005c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 11015c439937SZhu Ning 11025c439937SZhu Ning cancel_delayed_work_sync(&es8326->jack_detect_work); 11035c439937SZhu Ning es8326_disable_micbias(component); 1104083912c2SZhu Ning es8326->calibrated = false; 11056e5f5bf8SZhang Yi regmap_write(es8326->regmap, ES8326_CLK_MUX, 0x2d); 11066e5f5bf8SZhang Yi regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x00); 11076e5f5bf8SZhang Yi regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b); 11085c439937SZhu Ning regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_OFF); 11095c439937SZhu Ning regcache_cache_only(es8326->regmap, true); 11105c439937SZhu Ning 1111ac20a73dSZhu Ning /* reset register value to default */ 1112ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); 1113ac20a73dSZhu Ning usleep_range(1000, 3000); 1114ac20a73dSZhu Ning regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); 111539938bb1SZhang Yi 111639938bb1SZhang Yi regcache_mark_dirty(es8326->regmap); 11175c439937SZhu Ning return 0; 11185c439937SZhu Ning } 11195c439937SZhu Ning 11205c439937SZhu Ning static int es8326_probe(struct snd_soc_component *component) 11215c439937SZhu Ning { 11225c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 11235c439937SZhu Ning int ret; 11245c439937SZhu Ning 11255c439937SZhu Ning es8326->component = component; 11265c439937SZhu Ning es8326->jd_inverted = device_property_read_bool(component->dev, 11275c439937SZhu Ning "everest,jack-detect-inverted"); 11285c439937SZhu Ning 11295c439937SZhu Ning ret = device_property_read_u8(component->dev, "everest,jack-pol", &es8326->jack_pol); 11305c439937SZhu Ning if (ret != 0) { 11315c439937SZhu Ning dev_dbg(component->dev, "jack-pol return %d", ret); 1132ac20a73dSZhu Ning es8326->jack_pol = ES8326_HP_TYPE_AUTO; 11335c439937SZhu Ning } 11345c439937SZhu Ning dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol); 11355c439937SZhu Ning 1136fe1e7e8cSAlexey Firago ret = device_property_read_u8(component->dev, "everest,interrupt-src", 1137fe1e7e8cSAlexey Firago &es8326->interrupt_src); 11385c439937SZhu Ning if (ret != 0) { 11395c439937SZhu Ning dev_dbg(component->dev, "interrupt-src return %d", ret); 11405c439937SZhu Ning es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9; 11415c439937SZhu Ning } 11425c439937SZhu Ning dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src); 11435c439937SZhu Ning 1144fe1e7e8cSAlexey Firago ret = device_property_read_u8(component->dev, "everest,interrupt-clk", 1145fe1e7e8cSAlexey Firago &es8326->interrupt_clk); 11465c439937SZhu Ning if (ret != 0) { 11475c439937SZhu Ning dev_dbg(component->dev, "interrupt-clk return %d", ret); 1148bb698384SZhang Yi es8326->interrupt_clk = 0x00; 11495c439937SZhu Ning } 11505c439937SZhu Ning dev_dbg(component->dev, "interrupt-clk %x", es8326->interrupt_clk); 11515c439937SZhu Ning 11527e7dbdeeSZhang Yi es8326_init(component); 11535c439937SZhu Ning return 0; 11545c439937SZhu Ning } 11555c439937SZhu Ning 11565c439937SZhu Ning static void es8326_enable_jack_detect(struct snd_soc_component *component, 11575c439937SZhu Ning struct snd_soc_jack *jack) 11585c439937SZhu Ning { 11595c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 11605c439937SZhu Ning 11615c439937SZhu Ning mutex_lock(&es8326->lock); 11625c439937SZhu Ning if (es8326->jd_inverted) 11634ddad00cSZhu Ning snd_soc_component_update_bits(component, ES8326_HPDET_TYPE, 11645c439937SZhu Ning ES8326_HP_DET_JACK_POL, ~es8326->jack_pol); 11655c439937SZhu Ning es8326->jack = jack; 11665c439937SZhu Ning 11675c439937SZhu Ning mutex_unlock(&es8326->lock); 11685c439937SZhu Ning es8326_irq(es8326->irq, es8326); 11695c439937SZhu Ning } 11705c439937SZhu Ning 11715c439937SZhu Ning static void es8326_disable_jack_detect(struct snd_soc_component *component) 11725c439937SZhu Ning { 11735c439937SZhu Ning struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 11745c439937SZhu Ning 11755c439937SZhu Ning dev_dbg(component->dev, "Enter into %s\n", __func__); 11765c439937SZhu Ning if (!es8326->jack) 11775c439937SZhu Ning return; /* Already disabled (or never enabled) */ 11785c439937SZhu Ning cancel_delayed_work_sync(&es8326->jack_detect_work); 11795c439937SZhu Ning 11805c439937SZhu Ning mutex_lock(&es8326->lock); 11815c439937SZhu Ning if (es8326->jack->status & SND_JACK_MICROPHONE) { 11825c439937SZhu Ning es8326_disable_micbias(component); 11835c439937SZhu Ning snd_soc_jack_report(es8326->jack, 0, SND_JACK_HEADSET); 11845c439937SZhu Ning } 11855c439937SZhu Ning es8326->jack = NULL; 11865c439937SZhu Ning mutex_unlock(&es8326->lock); 11875c439937SZhu Ning } 11885c439937SZhu Ning 11895c439937SZhu Ning static int es8326_set_jack(struct snd_soc_component *component, 11905c439937SZhu Ning struct snd_soc_jack *jack, void *data) 11915c439937SZhu Ning { 11925c439937SZhu Ning if (jack) 11935c439937SZhu Ning es8326_enable_jack_detect(component, jack); 11945c439937SZhu Ning else 11955c439937SZhu Ning es8326_disable_jack_detect(component); 11965c439937SZhu Ning 11975c439937SZhu Ning return 0; 11985c439937SZhu Ning } 11995c439937SZhu Ning 12005c439937SZhu Ning static void es8326_remove(struct snd_soc_component *component) 12015c439937SZhu Ning { 120239938bb1SZhang Yi struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 120339938bb1SZhang Yi 12045c439937SZhu Ning es8326_disable_jack_detect(component); 12055c439937SZhu Ning es8326_set_bias_level(component, SND_SOC_BIAS_OFF); 120639938bb1SZhang Yi regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); 120739938bb1SZhang Yi usleep_range(1000, 3000); 120839938bb1SZhang Yi regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); 12095c439937SZhu Ning } 12105c439937SZhu Ning 12115c439937SZhu Ning static const struct snd_soc_component_driver soc_component_dev_es8326 = { 12125c439937SZhu Ning .probe = es8326_probe, 12135c439937SZhu Ning .remove = es8326_remove, 12145c439937SZhu Ning .resume = es8326_resume, 12155c439937SZhu Ning .suspend = es8326_suspend, 12165c439937SZhu Ning .set_bias_level = es8326_set_bias_level, 12175c439937SZhu Ning .set_jack = es8326_set_jack, 12185c439937SZhu Ning .dapm_widgets = es8326_dapm_widgets, 12195c439937SZhu Ning .num_dapm_widgets = ARRAY_SIZE(es8326_dapm_widgets), 12205c439937SZhu Ning .dapm_routes = es8326_dapm_routes, 12215c439937SZhu Ning .num_dapm_routes = ARRAY_SIZE(es8326_dapm_routes), 12225c439937SZhu Ning .controls = es8326_snd_controls, 12235c439937SZhu Ning .num_controls = ARRAY_SIZE(es8326_snd_controls), 12245c439937SZhu Ning .use_pmdown_time = 1, 12255c439937SZhu Ning .endianness = 1, 12265c439937SZhu Ning }; 12275c439937SZhu Ning 1228784252baSUwe Kleine-König static int es8326_i2c_probe(struct i2c_client *i2c) 12295c439937SZhu Ning { 12305c439937SZhu Ning struct es8326_priv *es8326; 12315c439937SZhu Ning int ret; 12325c439937SZhu Ning 12335c439937SZhu Ning es8326 = devm_kzalloc(&i2c->dev, sizeof(struct es8326_priv), GFP_KERNEL); 12345c439937SZhu Ning if (!es8326) 12355c439937SZhu Ning return -ENOMEM; 12365c439937SZhu Ning 12375c439937SZhu Ning i2c_set_clientdata(i2c, es8326); 12385c439937SZhu Ning es8326->i2c = i2c; 12395c439937SZhu Ning mutex_init(&es8326->lock); 12405c439937SZhu Ning es8326->regmap = devm_regmap_init_i2c(i2c, &es8326_regmap_config); 12415c439937SZhu Ning if (IS_ERR(es8326->regmap)) { 12425c439937SZhu Ning ret = PTR_ERR(es8326->regmap); 12435c439937SZhu Ning dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); 12445c439937SZhu Ning return ret; 12455c439937SZhu Ning } 12465c439937SZhu Ning 12475c439937SZhu Ning es8326->irq = i2c->irq; 12484eed7819SZhang Yi es8326->jack_remove_retry = 0; 12494eed7819SZhang Yi es8326->hp = 0; 12504eed7819SZhang Yi es8326->hpl_vol = 0x03; 12514eed7819SZhang Yi es8326->hpr_vol = 0x03; 12525c439937SZhu Ning INIT_DELAYED_WORK(&es8326->jack_detect_work, 12535c439937SZhu Ning es8326_jack_detect_handler); 12545c439937SZhu Ning INIT_DELAYED_WORK(&es8326->button_press_work, 12555c439937SZhu Ning es8326_jack_button_handler); 12565c439937SZhu Ning /* ES8316 is level-based while ES8326 is edge-based */ 12575c439937SZhu Ning ret = devm_request_threaded_irq(&i2c->dev, es8326->irq, NULL, es8326_irq, 12585c439937SZhu Ning IRQF_TRIGGER_RISING | IRQF_ONESHOT, 12595c439937SZhu Ning "es8326", es8326); 12605c439937SZhu Ning if (ret) { 12615c439937SZhu Ning dev_warn(&i2c->dev, "Failed to request IRQ: %d: %d\n", 12625c439937SZhu Ning es8326->irq, ret); 12635c439937SZhu Ning es8326->irq = -ENXIO; 12645c439937SZhu Ning } 12655c439937SZhu Ning 12665c439937SZhu Ning es8326->mclk = devm_clk_get_optional(&i2c->dev, "mclk"); 12675c439937SZhu Ning if (IS_ERR(es8326->mclk)) { 12685c439937SZhu Ning dev_err(&i2c->dev, "unable to get mclk\n"); 12695c439937SZhu Ning return PTR_ERR(es8326->mclk); 12705c439937SZhu Ning } 12715c439937SZhu Ning if (!es8326->mclk) 12725c439937SZhu Ning dev_warn(&i2c->dev, "assuming static mclk\n"); 12735c439937SZhu Ning 12745c439937SZhu Ning ret = clk_prepare_enable(es8326->mclk); 12755c439937SZhu Ning if (ret) { 12765c439937SZhu Ning dev_err(&i2c->dev, "unable to enable mclk\n"); 12775c439937SZhu Ning return ret; 12785c439937SZhu Ning } 12795c439937SZhu Ning return devm_snd_soc_register_component(&i2c->dev, 12805c439937SZhu Ning &soc_component_dev_es8326, 12815c439937SZhu Ning &es8326_dai, 1); 12825c439937SZhu Ning } 12835c439937SZhu Ning 128439938bb1SZhang Yi 128539938bb1SZhang Yi static void es8326_i2c_shutdown(struct i2c_client *i2c) 128639938bb1SZhang Yi { 128739938bb1SZhang Yi struct snd_soc_component *component; 128839938bb1SZhang Yi struct es8326_priv *es8326; 128939938bb1SZhang Yi 129039938bb1SZhang Yi es8326 = i2c_get_clientdata(i2c); 129139938bb1SZhang Yi component = es8326->component; 129239938bb1SZhang Yi dev_dbg(component->dev, "Enter into %s\n", __func__); 129339938bb1SZhang Yi cancel_delayed_work_sync(&es8326->jack_detect_work); 129439938bb1SZhang Yi cancel_delayed_work_sync(&es8326->button_press_work); 129539938bb1SZhang Yi 129639938bb1SZhang Yi regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); 129739938bb1SZhang Yi usleep_range(1000, 3000); 129839938bb1SZhang Yi regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); 129939938bb1SZhang Yi 130039938bb1SZhang Yi } 130139938bb1SZhang Yi 130239938bb1SZhang Yi static void es8326_i2c_remove(struct i2c_client *i2c) 130339938bb1SZhang Yi { 130439938bb1SZhang Yi es8326_i2c_shutdown(i2c); 130539938bb1SZhang Yi } 130639938bb1SZhang Yi 13075c439937SZhu Ning static const struct i2c_device_id es8326_i2c_id[] = { 1308ba2a2c37SUwe Kleine-König {"es8326" }, 13095c439937SZhu Ning {} 13105c439937SZhu Ning }; 13115c439937SZhu Ning MODULE_DEVICE_TABLE(i2c, es8326_i2c_id); 13125c439937SZhu Ning 13135c439937SZhu Ning #ifdef CONFIG_OF 13145c439937SZhu Ning static const struct of_device_id es8326_of_match[] = { 13155c439937SZhu Ning { .compatible = "everest,es8326", }, 13165c439937SZhu Ning {} 13175c439937SZhu Ning }; 13185c439937SZhu Ning MODULE_DEVICE_TABLE(of, es8326_of_match); 13195c439937SZhu Ning #endif 13205c439937SZhu Ning 13215c439937SZhu Ning #ifdef CONFIG_ACPI 13225c439937SZhu Ning static const struct acpi_device_id es8326_acpi_match[] = { 13235c439937SZhu Ning {"ESSX8326", 0}, 13245c439937SZhu Ning {}, 13255c439937SZhu Ning }; 13265c439937SZhu Ning MODULE_DEVICE_TABLE(acpi, es8326_acpi_match); 13275c439937SZhu Ning #endif 13285c439937SZhu Ning 13295c439937SZhu Ning static struct i2c_driver es8326_i2c_driver = { 13305c439937SZhu Ning .driver = { 13315c439937SZhu Ning .name = "es8326", 13325c439937SZhu Ning .acpi_match_table = ACPI_PTR(es8326_acpi_match), 13335c439937SZhu Ning .of_match_table = of_match_ptr(es8326_of_match), 13345c439937SZhu Ning }, 13359abcd240SUwe Kleine-König .probe = es8326_i2c_probe, 133639938bb1SZhang Yi .shutdown = es8326_i2c_shutdown, 133739938bb1SZhang Yi .remove = es8326_i2c_remove, 13385c439937SZhu Ning .id_table = es8326_i2c_id, 13395c439937SZhu Ning }; 13405c439937SZhu Ning module_i2c_driver(es8326_i2c_driver); 13415c439937SZhu Ning 13425c439937SZhu Ning MODULE_DESCRIPTION("ASoC es8326 driver"); 13435c439937SZhu Ning MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>"); 13445c439937SZhu Ning MODULE_LICENSE("GPL"); 1345