1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2b8b88b70SDaniel Drake /* 3b8b88b70SDaniel Drake * es8316.c -- es8316 ALSA SoC audio driver 4b8b88b70SDaniel Drake * Copyright Everest Semiconductor Co.,Ltd 5b8b88b70SDaniel Drake * 6b8b88b70SDaniel Drake * Authors: David Yang <yangxiaohua@everest-semi.com>, 7b8b88b70SDaniel Drake * Daniel Drake <drake@endlessm.com> 8b8b88b70SDaniel Drake */ 9b8b88b70SDaniel Drake 10b8b88b70SDaniel Drake #include <linux/module.h> 11b8b88b70SDaniel Drake #include <linux/acpi.h> 12b8b88b70SDaniel Drake #include <linux/delay.h> 13b8b88b70SDaniel Drake #include <linux/i2c.h> 14b8b88b70SDaniel Drake #include <linux/mod_devicetable.h> 1582225766SHans de Goede #include <linux/mutex.h> 16b8b88b70SDaniel Drake #include <linux/regmap.h> 17b8b88b70SDaniel Drake #include <sound/pcm.h> 18b8b88b70SDaniel Drake #include <sound/pcm_params.h> 19b8b88b70SDaniel Drake #include <sound/soc.h> 20b8b88b70SDaniel Drake #include <sound/soc-dapm.h> 21b8b88b70SDaniel Drake #include <sound/tlv.h> 2282225766SHans de Goede #include <sound/jack.h> 23b8b88b70SDaniel Drake #include "es8316.h" 24b8b88b70SDaniel Drake 25b8b88b70SDaniel Drake /* In slave mode at single speed, the codec is documented as accepting 5 26b8b88b70SDaniel Drake * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on 27b8b88b70SDaniel Drake * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK). 28b8b88b70SDaniel Drake */ 29b8b88b70SDaniel Drake #define NR_SUPPORTED_MCLK_LRCK_RATIOS 6 30b8b88b70SDaniel Drake static const unsigned int supported_mclk_lrck_ratios[] = { 31b8b88b70SDaniel Drake 256, 384, 400, 512, 768, 1024 32b8b88b70SDaniel Drake }; 33b8b88b70SDaniel Drake 34b8b88b70SDaniel Drake struct es8316_priv { 3582225766SHans de Goede struct mutex lock; 3682225766SHans de Goede struct regmap *regmap; 3782225766SHans de Goede struct snd_soc_component *component; 3882225766SHans de Goede struct snd_soc_jack *jack; 3982225766SHans de Goede int irq; 40b8b88b70SDaniel Drake unsigned int sysclk; 41b8b88b70SDaniel Drake unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS]; 42b8b88b70SDaniel Drake struct snd_pcm_hw_constraint_list sysclk_constraints; 430bbcedd6SPaul Cercueil bool jd_inverted; 44b8b88b70SDaniel Drake }; 45b8b88b70SDaniel Drake 46b8b88b70SDaniel Drake /* 47b8b88b70SDaniel Drake * ES8316 controls 48b8b88b70SDaniel Drake */ 49b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1); 50b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1); 51b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0); 52b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0); 53b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0); 54b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0); 55b8b88b70SDaniel Drake 56b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv, 57b8b88b70SDaniel Drake 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0), 58b8b88b70SDaniel Drake 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0), 59b8b88b70SDaniel Drake 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0), 60b8b88b70SDaniel Drake 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), 61b8b88b70SDaniel Drake 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0), 62b8b88b70SDaniel Drake 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0), 63b8b88b70SDaniel Drake 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0), 64b8b88b70SDaniel Drake 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0), 65b8b88b70SDaniel Drake 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0), 66b8b88b70SDaniel Drake 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0), 67b8b88b70SDaniel Drake 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0), 68b8b88b70SDaniel Drake ); 69b8b88b70SDaniel Drake 70b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv, 71b8b88b70SDaniel Drake 0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0), 72b8b88b70SDaniel Drake 1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0), 73b8b88b70SDaniel Drake ); 74b8b88b70SDaniel Drake 75b8b88b70SDaniel Drake static const char * const ng_type_txt[] = 76b8b88b70SDaniel Drake { "Constant PGA Gain", "Mute ADC Output" }; 77b8b88b70SDaniel Drake static const struct soc_enum ng_type = 78b8b88b70SDaniel Drake SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt); 79b8b88b70SDaniel Drake 80b8b88b70SDaniel Drake static const char * const adcpol_txt[] = { "Normal", "Invert" }; 81b8b88b70SDaniel Drake static const struct soc_enum adcpol = 82b8b88b70SDaniel Drake SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt); 83b8b88b70SDaniel Drake static const char *const dacpol_txt[] = 84b8b88b70SDaniel Drake { "Normal", "R Invert", "L Invert", "L + R Invert" }; 85b8b88b70SDaniel Drake static const struct soc_enum dacpol = 86b8b88b70SDaniel Drake SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt); 87b8b88b70SDaniel Drake 88b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_snd_controls[] = { 89b8b88b70SDaniel Drake SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL, 90b8b88b70SDaniel Drake 4, 0, 3, 1, hpout_vol_tlv), 91b8b88b70SDaniel Drake SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL, 92b8b88b70SDaniel Drake 0, 4, 7, 0, hpmixer_gain_tlv), 93b8b88b70SDaniel Drake 94b8b88b70SDaniel Drake SOC_ENUM("Playback Polarity", dacpol), 95b8b88b70SDaniel Drake SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL, 96b8b88b70SDaniel Drake ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv), 97b8b88b70SDaniel Drake SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1), 98b8b88b70SDaniel Drake SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0), 99b8b88b70SDaniel Drake SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0), 100b8b88b70SDaniel Drake SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0), 101b8b88b70SDaniel Drake SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0), 10224b53f17SHans de Goede SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0), 103b8b88b70SDaniel Drake 104b8b88b70SDaniel Drake SOC_ENUM("Capture Polarity", adcpol), 105b8b88b70SDaniel Drake SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0), 106b8b88b70SDaniel Drake SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME, 107b8b88b70SDaniel Drake 0, 0xc0, 1, adc_vol_tlv), 108b8b88b70SDaniel Drake SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN, 109b8b88b70SDaniel Drake 4, 10, 0, adc_pga_gain_tlv), 110b8b88b70SDaniel Drake SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0), 111b8b88b70SDaniel Drake SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0), 112b8b88b70SDaniel Drake 113b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0), 114b8b88b70SDaniel Drake SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0, 115b8b88b70SDaniel Drake alc_max_gain_tlv), 116b8b88b70SDaniel Drake SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0, 117b8b88b70SDaniel Drake alc_min_gain_tlv), 118b8b88b70SDaniel Drake SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0, 119b8b88b70SDaniel Drake alc_target_tlv), 120b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0), 121b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0), 122b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0), 123b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG, 124b8b88b70SDaniel Drake 5, 1, 0), 125b8b88b70SDaniel Drake SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG, 126b8b88b70SDaniel Drake 0, 31, 0), 127b8b88b70SDaniel Drake SOC_ENUM("ALC Capture Noise Gate Type", ng_type), 128b8b88b70SDaniel Drake }; 129b8b88b70SDaniel Drake 130b8b88b70SDaniel Drake /* Analog Input Mux */ 131b8b88b70SDaniel Drake static const char * const es8316_analog_in_txt[] = { 132b8b88b70SDaniel Drake "lin1-rin1", 133b8b88b70SDaniel Drake "lin2-rin2", 134b8b88b70SDaniel Drake "lin1-rin1 with 20db Boost", 135b8b88b70SDaniel Drake "lin2-rin2 with 20db Boost" 136b8b88b70SDaniel Drake }; 137b8b88b70SDaniel Drake static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 }; 138b8b88b70SDaniel Drake static const struct soc_enum es8316_analog_input_enum = 139b8b88b70SDaniel Drake SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3, 140b8b88b70SDaniel Drake ARRAY_SIZE(es8316_analog_in_txt), 141b8b88b70SDaniel Drake es8316_analog_in_txt, 142b8b88b70SDaniel Drake es8316_analog_in_values); 143b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_analog_in_mux_controls = 144b8b88b70SDaniel Drake SOC_DAPM_ENUM("Route", es8316_analog_input_enum); 145b8b88b70SDaniel Drake 146b8b88b70SDaniel Drake static const char * const es8316_dmic_txt[] = { 147b8b88b70SDaniel Drake "dmic disable", 148b8b88b70SDaniel Drake "dmic data at high level", 149b8b88b70SDaniel Drake "dmic data at low level", 150b8b88b70SDaniel Drake }; 151b8b88b70SDaniel Drake static const unsigned int es8316_dmic_values[] = { 0, 1, 2 }; 152b8b88b70SDaniel Drake static const struct soc_enum es8316_dmic_src_enum = 153b8b88b70SDaniel Drake SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3, 154b8b88b70SDaniel Drake ARRAY_SIZE(es8316_dmic_txt), 155b8b88b70SDaniel Drake es8316_dmic_txt, 156b8b88b70SDaniel Drake es8316_dmic_values); 157b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dmic_src_controls = 158b8b88b70SDaniel Drake SOC_DAPM_ENUM("Route", es8316_dmic_src_enum); 159b8b88b70SDaniel Drake 160b8b88b70SDaniel Drake /* hp mixer mux */ 161b8b88b70SDaniel Drake static const char * const es8316_hpmux_texts[] = { 162b8b88b70SDaniel Drake "lin1-rin1", 163b8b88b70SDaniel Drake "lin2-rin2", 164b8b88b70SDaniel Drake "lin-rin with Boost", 165b8b88b70SDaniel Drake "lin-rin with Boost and PGA" 166b8b88b70SDaniel Drake }; 167b8b88b70SDaniel Drake 168b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL, 169b8b88b70SDaniel Drake 4, es8316_hpmux_texts); 170b8b88b70SDaniel Drake 171b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_left_hpmux_controls = 172b8b88b70SDaniel Drake SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum); 173b8b88b70SDaniel Drake 174b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL, 175b8b88b70SDaniel Drake 0, es8316_hpmux_texts); 176b8b88b70SDaniel Drake 177b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_right_hpmux_controls = 178b8b88b70SDaniel Drake SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum); 179b8b88b70SDaniel Drake 180b8b88b70SDaniel Drake /* headphone Output Mixer */ 181b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_left_mix[] = { 182b8b88b70SDaniel Drake SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0), 183b8b88b70SDaniel Drake SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0), 184b8b88b70SDaniel Drake }; 185b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_right_mix[] = { 186b8b88b70SDaniel Drake SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0), 187b8b88b70SDaniel Drake SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0), 188b8b88b70SDaniel Drake }; 189b8b88b70SDaniel Drake 190b8b88b70SDaniel Drake /* DAC data source mux */ 191b8b88b70SDaniel Drake static const char * const es8316_dacsrc_texts[] = { 192b8b88b70SDaniel Drake "LDATA TO LDAC, RDATA TO RDAC", 193b8b88b70SDaniel Drake "LDATA TO LDAC, LDATA TO RDAC", 194b8b88b70SDaniel Drake "RDATA TO LDAC, RDATA TO RDAC", 195b8b88b70SDaniel Drake "RDATA TO LDAC, LDATA TO RDAC", 196b8b88b70SDaniel Drake }; 197b8b88b70SDaniel Drake 198b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1, 199b8b88b70SDaniel Drake 6, es8316_dacsrc_texts); 200b8b88b70SDaniel Drake 201b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dacsrc_mux_controls = 202b8b88b70SDaniel Drake SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum); 203b8b88b70SDaniel Drake 204b8b88b70SDaniel Drake static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { 205b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0), 206b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0), 207b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0), 208b8b88b70SDaniel Drake 209b8b88b70SDaniel Drake SND_SOC_DAPM_INPUT("DMIC"), 210b8b88b70SDaniel Drake SND_SOC_DAPM_INPUT("MIC1"), 211b8b88b70SDaniel Drake SND_SOC_DAPM_INPUT("MIC2"), 212b8b88b70SDaniel Drake 213b8b88b70SDaniel Drake /* Input Mux */ 214b8b88b70SDaniel Drake SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, 215b8b88b70SDaniel Drake &es8316_analog_in_mux_controls), 216b8b88b70SDaniel Drake 217b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0), 218b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0), 219b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0), 220b8b88b70SDaniel Drake SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL, 221b8b88b70SDaniel Drake 7, 1, NULL, 0), 222b8b88b70SDaniel Drake SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1), 223b8b88b70SDaniel Drake SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0, 224b8b88b70SDaniel Drake &es8316_dmic_src_controls), 225b8b88b70SDaniel Drake 226b8b88b70SDaniel Drake /* Digital Interface */ 227b8b88b70SDaniel Drake SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1, 228b8b88b70SDaniel Drake ES8316_SERDATA_ADC, 6, 1), 229b8b88b70SDaniel Drake SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, 230b8b88b70SDaniel Drake SND_SOC_NOPM, 0, 0), 231b8b88b70SDaniel Drake 232b8b88b70SDaniel Drake SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0, 233b8b88b70SDaniel Drake &es8316_dacsrc_mux_controls), 234b8b88b70SDaniel Drake 235b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0), 236b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0), 237b8b88b70SDaniel Drake SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1), 238b8b88b70SDaniel Drake SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1), 239b8b88b70SDaniel Drake 240b8b88b70SDaniel Drake /* Headphone Output Side */ 241b8b88b70SDaniel Drake SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, 242b8b88b70SDaniel Drake &es8316_left_hpmux_controls), 243b8b88b70SDaniel Drake SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, 244b8b88b70SDaniel Drake &es8316_right_hpmux_controls), 245b8b88b70SDaniel Drake SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN, 246b8b88b70SDaniel Drake 5, 1, &es8316_out_left_mix[0], 247b8b88b70SDaniel Drake ARRAY_SIZE(es8316_out_left_mix)), 248b8b88b70SDaniel Drake SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN, 249b8b88b70SDaniel Drake 1, 1, &es8316_out_right_mix[0], 250b8b88b70SDaniel Drake ARRAY_SIZE(es8316_out_right_mix)), 251b8b88b70SDaniel Drake SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN, 252b8b88b70SDaniel Drake 4, 1, NULL, 0), 253b8b88b70SDaniel Drake SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN, 254b8b88b70SDaniel Drake 0, 1, NULL, 0), 255b8b88b70SDaniel Drake 256b8b88b70SDaniel Drake SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN, 257b8b88b70SDaniel Drake 6, 0, NULL, 0), 258b8b88b70SDaniel Drake SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN, 259b8b88b70SDaniel Drake 2, 0, NULL, 0), 260b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2, 261b8b88b70SDaniel Drake 5, 1, NULL, 0), 262b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW, 263b8b88b70SDaniel Drake 4, 0, NULL, 0), 264b8b88b70SDaniel Drake 265b8b88b70SDaniel Drake SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN, 266b8b88b70SDaniel Drake 5, 0, NULL, 0), 267b8b88b70SDaniel Drake SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN, 268b8b88b70SDaniel Drake 1, 0, NULL, 0), 269b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0), 270b8b88b70SDaniel Drake 271b8b88b70SDaniel Drake /* pdn_Lical and pdn_Rical bits are documented as Reserved, but must 272b8b88b70SDaniel Drake * be explicitly unset in order to enable HP output 273b8b88b70SDaniel Drake */ 274b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL, 275b8b88b70SDaniel Drake 7, 1, NULL, 0), 276b8b88b70SDaniel Drake SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL, 277b8b88b70SDaniel Drake 3, 1, NULL, 0), 278b8b88b70SDaniel Drake 279b8b88b70SDaniel Drake SND_SOC_DAPM_OUTPUT("HPOL"), 280b8b88b70SDaniel Drake SND_SOC_DAPM_OUTPUT("HPOR"), 281b8b88b70SDaniel Drake }; 282b8b88b70SDaniel Drake 283b8b88b70SDaniel Drake static const struct snd_soc_dapm_route es8316_dapm_routes[] = { 284b8b88b70SDaniel Drake /* Recording */ 285b8b88b70SDaniel Drake {"MIC1", NULL, "Mic Bias"}, 286b8b88b70SDaniel Drake {"MIC2", NULL, "Mic Bias"}, 287b8b88b70SDaniel Drake {"MIC1", NULL, "Bias"}, 288b8b88b70SDaniel Drake {"MIC2", NULL, "Bias"}, 289b8b88b70SDaniel Drake {"MIC1", NULL, "Analog power"}, 290b8b88b70SDaniel Drake {"MIC2", NULL, "Analog power"}, 291b8b88b70SDaniel Drake 292b8b88b70SDaniel Drake {"Differential Mux", "lin1-rin1", "MIC1"}, 293b8b88b70SDaniel Drake {"Differential Mux", "lin2-rin2", "MIC2"}, 294b8b88b70SDaniel Drake {"Line input PGA", NULL, "Differential Mux"}, 295b8b88b70SDaniel Drake 296b8b88b70SDaniel Drake {"Mono ADC", NULL, "ADC Clock"}, 297b8b88b70SDaniel Drake {"Mono ADC", NULL, "ADC Vref"}, 298b8b88b70SDaniel Drake {"Mono ADC", NULL, "ADC bias"}, 299b8b88b70SDaniel Drake {"Mono ADC", NULL, "Line input PGA"}, 300b8b88b70SDaniel Drake 301b8b88b70SDaniel Drake /* It's not clear why, but to avoid recording only silence, 302b8b88b70SDaniel Drake * the DAC clock must be running for the ADC to work. 303b8b88b70SDaniel Drake */ 304b8b88b70SDaniel Drake {"Mono ADC", NULL, "DAC Clock"}, 305b8b88b70SDaniel Drake 306b8b88b70SDaniel Drake {"Digital Mic Mux", "dmic disable", "Mono ADC"}, 307b8b88b70SDaniel Drake 308b8b88b70SDaniel Drake {"I2S OUT", NULL, "Digital Mic Mux"}, 309b8b88b70SDaniel Drake 310b8b88b70SDaniel Drake /* Playback */ 311b8b88b70SDaniel Drake {"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"}, 312b8b88b70SDaniel Drake 313b8b88b70SDaniel Drake {"Left DAC", NULL, "DAC Clock"}, 314b8b88b70SDaniel Drake {"Right DAC", NULL, "DAC Clock"}, 315b8b88b70SDaniel Drake 316b8b88b70SDaniel Drake {"Left DAC", NULL, "DAC Vref"}, 317b8b88b70SDaniel Drake {"Right DAC", NULL, "DAC Vref"}, 318b8b88b70SDaniel Drake 319b8b88b70SDaniel Drake {"Left DAC", NULL, "DAC Source Mux"}, 320b8b88b70SDaniel Drake {"Right DAC", NULL, "DAC Source Mux"}, 321b8b88b70SDaniel Drake 322b8b88b70SDaniel Drake {"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"}, 323b8b88b70SDaniel Drake {"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"}, 324b8b88b70SDaniel Drake 325b8b88b70SDaniel Drake {"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"}, 326b8b88b70SDaniel Drake {"Left Headphone Mixer", "Left DAC Switch", "Left DAC"}, 327b8b88b70SDaniel Drake 328b8b88b70SDaniel Drake {"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"}, 329b8b88b70SDaniel Drake {"Right Headphone Mixer", "Right DAC Switch", "Right DAC"}, 330b8b88b70SDaniel Drake 331b8b88b70SDaniel Drake {"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"}, 332b8b88b70SDaniel Drake {"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"}, 333b8b88b70SDaniel Drake 334b8b88b70SDaniel Drake {"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"}, 335b8b88b70SDaniel Drake {"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"}, 336b8b88b70SDaniel Drake 337b8b88b70SDaniel Drake {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"}, 338b8b88b70SDaniel Drake {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"}, 339b8b88b70SDaniel Drake 340b8b88b70SDaniel Drake {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"}, 341b8b88b70SDaniel Drake {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"}, 342b8b88b70SDaniel Drake 343b8b88b70SDaniel Drake {"Left Headphone Driver", NULL, "Left Headphone Charge Pump"}, 344b8b88b70SDaniel Drake {"Right Headphone Driver", NULL, "Right Headphone Charge Pump"}, 345b8b88b70SDaniel Drake 346b8b88b70SDaniel Drake {"HPOL", NULL, "Left Headphone Driver"}, 347b8b88b70SDaniel Drake {"HPOR", NULL, "Right Headphone Driver"}, 348b8b88b70SDaniel Drake 349b8b88b70SDaniel Drake {"HPOL", NULL, "Left Headphone ical"}, 350b8b88b70SDaniel Drake {"HPOR", NULL, "Right Headphone ical"}, 351b8b88b70SDaniel Drake 352b8b88b70SDaniel Drake {"Headphone Out", NULL, "Bias"}, 353b8b88b70SDaniel Drake {"Headphone Out", NULL, "Analog power"}, 354b8b88b70SDaniel Drake {"HPOL", NULL, "Headphone Out"}, 355b8b88b70SDaniel Drake {"HPOR", NULL, "Headphone Out"}, 356b8b88b70SDaniel Drake }; 357b8b88b70SDaniel Drake 358b8b88b70SDaniel Drake static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, 359b8b88b70SDaniel Drake int clk_id, unsigned int freq, int dir) 360b8b88b70SDaniel Drake { 3612ff52976SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 3622ff52976SKuninori Morimoto struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 363b8b88b70SDaniel Drake int i; 364b8b88b70SDaniel Drake int count = 0; 365b8b88b70SDaniel Drake 366b8b88b70SDaniel Drake es8316->sysclk = freq; 367b8b88b70SDaniel Drake 368b8b88b70SDaniel Drake if (freq == 0) 369b8b88b70SDaniel Drake return 0; 370b8b88b70SDaniel Drake 371b8b88b70SDaniel Drake /* Limit supported sample rates to ones that can be autodetected 372b8b88b70SDaniel Drake * by the codec running in slave mode. 373b8b88b70SDaniel Drake */ 374b8b88b70SDaniel Drake for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) { 375b8b88b70SDaniel Drake const unsigned int ratio = supported_mclk_lrck_ratios[i]; 376b8b88b70SDaniel Drake 377b8b88b70SDaniel Drake if (freq % ratio == 0) 378b8b88b70SDaniel Drake es8316->allowed_rates[count++] = freq / ratio; 379b8b88b70SDaniel Drake } 380b8b88b70SDaniel Drake 381b8b88b70SDaniel Drake es8316->sysclk_constraints.list = es8316->allowed_rates; 382b8b88b70SDaniel Drake es8316->sysclk_constraints.count = count; 383b8b88b70SDaniel Drake 384b8b88b70SDaniel Drake return 0; 385b8b88b70SDaniel Drake } 386b8b88b70SDaniel Drake 387b8b88b70SDaniel Drake static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai, 388b8b88b70SDaniel Drake unsigned int fmt) 389b8b88b70SDaniel Drake { 3902ff52976SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 391b8b88b70SDaniel Drake u8 serdata1 = 0; 392b8b88b70SDaniel Drake u8 serdata2 = 0; 393b8b88b70SDaniel Drake u8 clksw; 394b8b88b70SDaniel Drake u8 mask; 395b8b88b70SDaniel Drake 396b8b88b70SDaniel Drake if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { 3972ff52976SKuninori Morimoto dev_err(component->dev, "Codec driver only supports slave mode\n"); 398b8b88b70SDaniel Drake return -EINVAL; 399b8b88b70SDaniel Drake } 400b8b88b70SDaniel Drake 401b8b88b70SDaniel Drake if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) { 4022ff52976SKuninori Morimoto dev_err(component->dev, "Codec driver only supports I2S format\n"); 403b8b88b70SDaniel Drake return -EINVAL; 404b8b88b70SDaniel Drake } 405b8b88b70SDaniel Drake 406b8b88b70SDaniel Drake /* Clock inversion */ 407b8b88b70SDaniel Drake switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 408b8b88b70SDaniel Drake case SND_SOC_DAIFMT_NB_NF: 409b8b88b70SDaniel Drake break; 410b8b88b70SDaniel Drake case SND_SOC_DAIFMT_IB_IF: 411b8b88b70SDaniel Drake serdata1 |= ES8316_SERDATA1_BCLK_INV; 412b8b88b70SDaniel Drake serdata2 |= ES8316_SERDATA2_ADCLRP; 413b8b88b70SDaniel Drake break; 414b8b88b70SDaniel Drake case SND_SOC_DAIFMT_IB_NF: 415b8b88b70SDaniel Drake serdata1 |= ES8316_SERDATA1_BCLK_INV; 416b8b88b70SDaniel Drake break; 417b8b88b70SDaniel Drake case SND_SOC_DAIFMT_NB_IF: 418b8b88b70SDaniel Drake serdata2 |= ES8316_SERDATA2_ADCLRP; 419b8b88b70SDaniel Drake break; 420b8b88b70SDaniel Drake default: 421b8b88b70SDaniel Drake return -EINVAL; 422b8b88b70SDaniel Drake } 423b8b88b70SDaniel Drake 424b8b88b70SDaniel Drake mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV; 4252ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_SERDATA1, mask, serdata1); 426b8b88b70SDaniel Drake 427b8b88b70SDaniel Drake mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP; 4282ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, mask, serdata2); 4292ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, mask, serdata2); 430b8b88b70SDaniel Drake 431b8b88b70SDaniel Drake /* Enable BCLK and MCLK inputs in slave mode */ 432b8b88b70SDaniel Drake clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON; 4332ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW, clksw, clksw); 434b8b88b70SDaniel Drake 435b8b88b70SDaniel Drake return 0; 436b8b88b70SDaniel Drake } 437b8b88b70SDaniel Drake 438b8b88b70SDaniel Drake static int es8316_pcm_startup(struct snd_pcm_substream *substream, 439b8b88b70SDaniel Drake struct snd_soc_dai *dai) 440b8b88b70SDaniel Drake { 4412ff52976SKuninori Morimoto struct snd_soc_component *component = dai->component; 4422ff52976SKuninori Morimoto struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 443b8b88b70SDaniel Drake 444b8b88b70SDaniel Drake if (es8316->sysclk == 0) { 4452ff52976SKuninori Morimoto dev_err(component->dev, "No sysclk provided\n"); 446b8b88b70SDaniel Drake return -EINVAL; 447b8b88b70SDaniel Drake } 448b8b88b70SDaniel Drake 449b8b88b70SDaniel Drake /* The set of sample rates that can be supported depends on the 450b8b88b70SDaniel Drake * MCLK supplied to the CODEC. 451b8b88b70SDaniel Drake */ 452b8b88b70SDaniel Drake snd_pcm_hw_constraint_list(substream->runtime, 0, 453b8b88b70SDaniel Drake SNDRV_PCM_HW_PARAM_RATE, 454b8b88b70SDaniel Drake &es8316->sysclk_constraints); 455b8b88b70SDaniel Drake 456b8b88b70SDaniel Drake return 0; 457b8b88b70SDaniel Drake } 458b8b88b70SDaniel Drake 459b8b88b70SDaniel Drake static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, 460b8b88b70SDaniel Drake struct snd_pcm_hw_params *params, 461b8b88b70SDaniel Drake struct snd_soc_dai *dai) 462b8b88b70SDaniel Drake { 4632ff52976SKuninori Morimoto struct snd_soc_component *component = dai->component; 4642ff52976SKuninori Morimoto struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 465b8b88b70SDaniel Drake u8 wordlen = 0; 466b8b88b70SDaniel Drake 467b8b88b70SDaniel Drake if (!es8316->sysclk) { 4682ff52976SKuninori Morimoto dev_err(component->dev, "No MCLK configured\n"); 469b8b88b70SDaniel Drake return -EINVAL; 470b8b88b70SDaniel Drake } 471b8b88b70SDaniel Drake 472b8b88b70SDaniel Drake switch (params_format(params)) { 473b8b88b70SDaniel Drake case SNDRV_PCM_FORMAT_S16_LE: 474b8b88b70SDaniel Drake wordlen = ES8316_SERDATA2_LEN_16; 475b8b88b70SDaniel Drake break; 476b8b88b70SDaniel Drake case SNDRV_PCM_FORMAT_S20_3LE: 477b8b88b70SDaniel Drake wordlen = ES8316_SERDATA2_LEN_20; 478b8b88b70SDaniel Drake break; 479b8b88b70SDaniel Drake case SNDRV_PCM_FORMAT_S24_LE: 480b8b88b70SDaniel Drake wordlen = ES8316_SERDATA2_LEN_24; 481b8b88b70SDaniel Drake break; 482b8b88b70SDaniel Drake case SNDRV_PCM_FORMAT_S32_LE: 483b8b88b70SDaniel Drake wordlen = ES8316_SERDATA2_LEN_32; 484b8b88b70SDaniel Drake break; 485b8b88b70SDaniel Drake default: 486b8b88b70SDaniel Drake return -EINVAL; 487b8b88b70SDaniel Drake } 488b8b88b70SDaniel Drake 4892ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, 490b8b88b70SDaniel Drake ES8316_SERDATA2_LEN_MASK, wordlen); 4912ff52976SKuninori Morimoto snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, 492b8b88b70SDaniel Drake ES8316_SERDATA2_LEN_MASK, wordlen); 493b8b88b70SDaniel Drake return 0; 494b8b88b70SDaniel Drake } 495b8b88b70SDaniel Drake 496b8b88b70SDaniel Drake static int es8316_mute(struct snd_soc_dai *dai, int mute) 497b8b88b70SDaniel Drake { 4982ff52976SKuninori Morimoto snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20, 499b8b88b70SDaniel Drake mute ? 0x20 : 0); 500b8b88b70SDaniel Drake return 0; 501b8b88b70SDaniel Drake } 502b8b88b70SDaniel Drake 503b8b88b70SDaniel Drake #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 504b8b88b70SDaniel Drake SNDRV_PCM_FMTBIT_S24_LE) 505b8b88b70SDaniel Drake 506eb59d73cSArvind Yadav static const struct snd_soc_dai_ops es8316_ops = { 507b8b88b70SDaniel Drake .startup = es8316_pcm_startup, 508b8b88b70SDaniel Drake .hw_params = es8316_pcm_hw_params, 509b8b88b70SDaniel Drake .set_fmt = es8316_set_dai_fmt, 510b8b88b70SDaniel Drake .set_sysclk = es8316_set_dai_sysclk, 511b8b88b70SDaniel Drake .digital_mute = es8316_mute, 512b8b88b70SDaniel Drake }; 513b8b88b70SDaniel Drake 514b8b88b70SDaniel Drake static struct snd_soc_dai_driver es8316_dai = { 515b8b88b70SDaniel Drake .name = "ES8316 HiFi", 516b8b88b70SDaniel Drake .playback = { 517b8b88b70SDaniel Drake .stream_name = "Playback", 518b8b88b70SDaniel Drake .channels_min = 1, 519b8b88b70SDaniel Drake .channels_max = 2, 520b8b88b70SDaniel Drake .rates = SNDRV_PCM_RATE_8000_48000, 521b8b88b70SDaniel Drake .formats = ES8316_FORMATS, 522b8b88b70SDaniel Drake }, 523b8b88b70SDaniel Drake .capture = { 524b8b88b70SDaniel Drake .stream_name = "Capture", 525b8b88b70SDaniel Drake .channels_min = 1, 526b8b88b70SDaniel Drake .channels_max = 2, 527b8b88b70SDaniel Drake .rates = SNDRV_PCM_RATE_8000_48000, 528b8b88b70SDaniel Drake .formats = ES8316_FORMATS, 529b8b88b70SDaniel Drake }, 530b8b88b70SDaniel Drake .ops = &es8316_ops, 531b8b88b70SDaniel Drake .symmetric_rates = 1, 532b8b88b70SDaniel Drake }; 533b8b88b70SDaniel Drake 53482225766SHans de Goede static void es8316_enable_micbias_for_mic_gnd_short_detect( 53582225766SHans de Goede struct snd_soc_component *component) 53682225766SHans de Goede { 53782225766SHans de Goede struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 53882225766SHans de Goede 53982225766SHans de Goede snd_soc_dapm_mutex_lock(dapm); 54082225766SHans de Goede snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias"); 54182225766SHans de Goede snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power"); 54282225766SHans de Goede snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias"); 54382225766SHans de Goede snd_soc_dapm_sync_unlocked(dapm); 54482225766SHans de Goede snd_soc_dapm_mutex_unlock(dapm); 54582225766SHans de Goede 54682225766SHans de Goede msleep(20); 54782225766SHans de Goede } 54882225766SHans de Goede 54982225766SHans de Goede static void es8316_disable_micbias_for_mic_gnd_short_detect( 55082225766SHans de Goede struct snd_soc_component *component) 55182225766SHans de Goede { 55282225766SHans de Goede struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 55382225766SHans de Goede 55482225766SHans de Goede snd_soc_dapm_mutex_lock(dapm); 55582225766SHans de Goede snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias"); 55682225766SHans de Goede snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power"); 55782225766SHans de Goede snd_soc_dapm_disable_pin_unlocked(dapm, "Bias"); 55882225766SHans de Goede snd_soc_dapm_sync_unlocked(dapm); 55982225766SHans de Goede snd_soc_dapm_mutex_unlock(dapm); 56082225766SHans de Goede } 56182225766SHans de Goede 56282225766SHans de Goede static irqreturn_t es8316_irq(int irq, void *data) 56382225766SHans de Goede { 56482225766SHans de Goede struct es8316_priv *es8316 = data; 56582225766SHans de Goede struct snd_soc_component *comp = es8316->component; 56682225766SHans de Goede unsigned int flags; 56782225766SHans de Goede 56882225766SHans de Goede mutex_lock(&es8316->lock); 56982225766SHans de Goede 57082225766SHans de Goede regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags); 57182225766SHans de Goede if (flags == 0x00) 57282225766SHans de Goede goto out; /* Powered-down / reset */ 57382225766SHans de Goede 57482225766SHans de Goede /* Catch spurious IRQ before set_jack is called */ 57582225766SHans de Goede if (!es8316->jack) 57682225766SHans de Goede goto out; 57782225766SHans de Goede 5780bbcedd6SPaul Cercueil if (es8316->jd_inverted) 5790bbcedd6SPaul Cercueil flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED; 5800bbcedd6SPaul Cercueil 58182225766SHans de Goede dev_dbg(comp->dev, "gpio flags %#04x\n", flags); 58282225766SHans de Goede if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) { 58382225766SHans de Goede /* Jack removed, or spurious IRQ? */ 58482225766SHans de Goede if (es8316->jack->status & SND_JACK_MICROPHONE) 58582225766SHans de Goede es8316_disable_micbias_for_mic_gnd_short_detect(comp); 58682225766SHans de Goede 58782225766SHans de Goede if (es8316->jack->status & SND_JACK_HEADPHONE) { 58882225766SHans de Goede snd_soc_jack_report(es8316->jack, 0, 58982225766SHans de Goede SND_JACK_HEADSET | SND_JACK_BTN_0); 59082225766SHans de Goede dev_dbg(comp->dev, "jack unplugged\n"); 59182225766SHans de Goede } 59282225766SHans de Goede } else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) { 59382225766SHans de Goede /* Jack inserted, determine type */ 59482225766SHans de Goede es8316_enable_micbias_for_mic_gnd_short_detect(comp); 59582225766SHans de Goede regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags); 5960bbcedd6SPaul Cercueil if (es8316->jd_inverted) 5970bbcedd6SPaul Cercueil flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED; 59882225766SHans de Goede dev_dbg(comp->dev, "gpio flags %#04x\n", flags); 59982225766SHans de Goede if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) { 60082225766SHans de Goede /* Jack unplugged underneath us */ 60182225766SHans de Goede es8316_disable_micbias_for_mic_gnd_short_detect(comp); 60282225766SHans de Goede } else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) { 60382225766SHans de Goede /* Open, headset */ 60482225766SHans de Goede snd_soc_jack_report(es8316->jack, 60582225766SHans de Goede SND_JACK_HEADSET, 60682225766SHans de Goede SND_JACK_HEADSET); 60782225766SHans de Goede /* Keep mic-gnd-short detection on for button press */ 60882225766SHans de Goede } else { 60982225766SHans de Goede /* Shorted, headphones */ 61082225766SHans de Goede snd_soc_jack_report(es8316->jack, 61182225766SHans de Goede SND_JACK_HEADPHONE, 61282225766SHans de Goede SND_JACK_HEADSET); 61382225766SHans de Goede /* No longer need mic-gnd-short detection */ 61482225766SHans de Goede es8316_disable_micbias_for_mic_gnd_short_detect(comp); 61582225766SHans de Goede } 61682225766SHans de Goede } else if (es8316->jack->status & SND_JACK_MICROPHONE) { 61782225766SHans de Goede /* Interrupt while jack inserted, report button state */ 61882225766SHans de Goede if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) { 61982225766SHans de Goede /* Open, button release */ 62082225766SHans de Goede snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); 62182225766SHans de Goede } else { 62282225766SHans de Goede /* Short, button press */ 62382225766SHans de Goede snd_soc_jack_report(es8316->jack, 62482225766SHans de Goede SND_JACK_BTN_0, 62582225766SHans de Goede SND_JACK_BTN_0); 62682225766SHans de Goede } 62782225766SHans de Goede } 62882225766SHans de Goede 62982225766SHans de Goede out: 63082225766SHans de Goede mutex_unlock(&es8316->lock); 63182225766SHans de Goede return IRQ_HANDLED; 63282225766SHans de Goede } 63382225766SHans de Goede 63482225766SHans de Goede static void es8316_enable_jack_detect(struct snd_soc_component *component, 63582225766SHans de Goede struct snd_soc_jack *jack) 63682225766SHans de Goede { 63782225766SHans de Goede struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 63882225766SHans de Goede 6390bbcedd6SPaul Cercueil /* 6400bbcedd6SPaul Cercueil * Init es8316->jd_inverted here and not in the probe, as we cannot 6410bbcedd6SPaul Cercueil * guarantee that the bytchr-es8316 driver, which might set this 6420bbcedd6SPaul Cercueil * property, will probe before us. 6430bbcedd6SPaul Cercueil */ 6440bbcedd6SPaul Cercueil es8316->jd_inverted = device_property_read_bool(component->dev, 6450bbcedd6SPaul Cercueil "everest,jack-detect-inverted"); 6460bbcedd6SPaul Cercueil 64782225766SHans de Goede mutex_lock(&es8316->lock); 64882225766SHans de Goede 64982225766SHans de Goede es8316->jack = jack; 65082225766SHans de Goede 65182225766SHans de Goede if (es8316->jack->status & SND_JACK_MICROPHONE) 65282225766SHans de Goede es8316_enable_micbias_for_mic_gnd_short_detect(component); 65382225766SHans de Goede 65482225766SHans de Goede snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE, 65582225766SHans de Goede ES8316_GPIO_ENABLE_INTERRUPT, 65682225766SHans de Goede ES8316_GPIO_ENABLE_INTERRUPT); 65782225766SHans de Goede 65882225766SHans de Goede mutex_unlock(&es8316->lock); 65982225766SHans de Goede 66082225766SHans de Goede /* Enable irq and sync initial jack state */ 66182225766SHans de Goede enable_irq(es8316->irq); 66282225766SHans de Goede es8316_irq(es8316->irq, es8316); 66382225766SHans de Goede } 66482225766SHans de Goede 66582225766SHans de Goede static void es8316_disable_jack_detect(struct snd_soc_component *component) 66682225766SHans de Goede { 66782225766SHans de Goede struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 66882225766SHans de Goede 66982225766SHans de Goede disable_irq(es8316->irq); 67082225766SHans de Goede 67182225766SHans de Goede mutex_lock(&es8316->lock); 67282225766SHans de Goede 67382225766SHans de Goede snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE, 67482225766SHans de Goede ES8316_GPIO_ENABLE_INTERRUPT, 0); 67582225766SHans de Goede 67682225766SHans de Goede if (es8316->jack->status & SND_JACK_MICROPHONE) { 67782225766SHans de Goede es8316_disable_micbias_for_mic_gnd_short_detect(component); 67882225766SHans de Goede snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); 67982225766SHans de Goede } 68082225766SHans de Goede 68182225766SHans de Goede es8316->jack = NULL; 68282225766SHans de Goede 68382225766SHans de Goede mutex_unlock(&es8316->lock); 68482225766SHans de Goede } 68582225766SHans de Goede 68682225766SHans de Goede static int es8316_set_jack(struct snd_soc_component *component, 68782225766SHans de Goede struct snd_soc_jack *jack, void *data) 68882225766SHans de Goede { 68982225766SHans de Goede if (jack) 69082225766SHans de Goede es8316_enable_jack_detect(component, jack); 69182225766SHans de Goede else 69282225766SHans de Goede es8316_disable_jack_detect(component); 69382225766SHans de Goede 69482225766SHans de Goede return 0; 69582225766SHans de Goede } 69682225766SHans de Goede 6972ff52976SKuninori Morimoto static int es8316_probe(struct snd_soc_component *component) 698b8b88b70SDaniel Drake { 69982225766SHans de Goede struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); 70082225766SHans de Goede 70182225766SHans de Goede es8316->component = component; 70282225766SHans de Goede 703b8b88b70SDaniel Drake /* Reset codec and enable current state machine */ 7042ff52976SKuninori Morimoto snd_soc_component_write(component, ES8316_RESET, 0x3f); 705b8b88b70SDaniel Drake usleep_range(5000, 5500); 7062ff52976SKuninori Morimoto snd_soc_component_write(component, ES8316_RESET, ES8316_RESET_CSM_ON); 707b8b88b70SDaniel Drake msleep(30); 708b8b88b70SDaniel Drake 709b8b88b70SDaniel Drake /* 710b8b88b70SDaniel Drake * Documentation is unclear, but this value from the vendor driver is 711b8b88b70SDaniel Drake * needed otherwise audio output is silent. 712b8b88b70SDaniel Drake */ 7132ff52976SKuninori Morimoto snd_soc_component_write(component, ES8316_SYS_VMIDSEL, 0xff); 714b8b88b70SDaniel Drake 715b8b88b70SDaniel Drake /* 716b8b88b70SDaniel Drake * Documentation for this register is unclear and incomplete, 717b8b88b70SDaniel Drake * but here is a vendor-provided value that improves volume 718b8b88b70SDaniel Drake * and quality for Intel CHT platforms. 719b8b88b70SDaniel Drake */ 7202ff52976SKuninori Morimoto snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32); 721b8b88b70SDaniel Drake 722b8b88b70SDaniel Drake return 0; 723b8b88b70SDaniel Drake } 724b8b88b70SDaniel Drake 7252ff52976SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_es8316 = { 726b8b88b70SDaniel Drake .probe = es8316_probe, 72782225766SHans de Goede .set_jack = es8316_set_jack, 728b8b88b70SDaniel Drake .controls = es8316_snd_controls, 729b8b88b70SDaniel Drake .num_controls = ARRAY_SIZE(es8316_snd_controls), 730b8b88b70SDaniel Drake .dapm_widgets = es8316_dapm_widgets, 731b8b88b70SDaniel Drake .num_dapm_widgets = ARRAY_SIZE(es8316_dapm_widgets), 732b8b88b70SDaniel Drake .dapm_routes = es8316_dapm_routes, 733b8b88b70SDaniel Drake .num_dapm_routes = ARRAY_SIZE(es8316_dapm_routes), 7342ff52976SKuninori Morimoto .use_pmdown_time = 1, 7352ff52976SKuninori Morimoto .endianness = 1, 7362ff52976SKuninori Morimoto .non_legacy_dai_naming = 1, 737b8b88b70SDaniel Drake }; 738b8b88b70SDaniel Drake 73982225766SHans de Goede static const struct regmap_range es8316_volatile_ranges[] = { 74082225766SHans de Goede regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG), 74182225766SHans de Goede }; 74282225766SHans de Goede 74382225766SHans de Goede static const struct regmap_access_table es8316_volatile_table = { 74482225766SHans de Goede .yes_ranges = es8316_volatile_ranges, 74582225766SHans de Goede .n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges), 74682225766SHans de Goede }; 74782225766SHans de Goede 748b8b88b70SDaniel Drake static const struct regmap_config es8316_regmap = { 749b8b88b70SDaniel Drake .reg_bits = 8, 750b8b88b70SDaniel Drake .val_bits = 8, 751b8b88b70SDaniel Drake .max_register = 0x53, 75282225766SHans de Goede .volatile_table = &es8316_volatile_table, 753b8b88b70SDaniel Drake .cache_type = REGCACHE_RBTREE, 754b8b88b70SDaniel Drake }; 755b8b88b70SDaniel Drake 756b8b88b70SDaniel Drake static int es8316_i2c_probe(struct i2c_client *i2c_client, 757b8b88b70SDaniel Drake const struct i2c_device_id *id) 758b8b88b70SDaniel Drake { 75982225766SHans de Goede struct device *dev = &i2c_client->dev; 760b8b88b70SDaniel Drake struct es8316_priv *es8316; 76182225766SHans de Goede int ret; 762b8b88b70SDaniel Drake 763b8b88b70SDaniel Drake es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv), 764b8b88b70SDaniel Drake GFP_KERNEL); 765b8b88b70SDaniel Drake if (es8316 == NULL) 766b8b88b70SDaniel Drake return -ENOMEM; 767b8b88b70SDaniel Drake 768b8b88b70SDaniel Drake i2c_set_clientdata(i2c_client, es8316); 769b8b88b70SDaniel Drake 77082225766SHans de Goede es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap); 77182225766SHans de Goede if (IS_ERR(es8316->regmap)) 77282225766SHans de Goede return PTR_ERR(es8316->regmap); 77382225766SHans de Goede 77482225766SHans de Goede es8316->irq = i2c_client->irq; 77582225766SHans de Goede mutex_init(&es8316->lock); 77682225766SHans de Goede 77782225766SHans de Goede ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, 77882225766SHans de Goede IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 77982225766SHans de Goede "es8316", es8316); 78082225766SHans de Goede if (ret == 0) { 78182225766SHans de Goede /* Gets re-enabled by es8316_set_jack() */ 78282225766SHans de Goede disable_irq(es8316->irq); 78382225766SHans de Goede } else { 78482225766SHans de Goede dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); 78582225766SHans de Goede es8316->irq = -ENXIO; 78682225766SHans de Goede } 787b8b88b70SDaniel Drake 7882ff52976SKuninori Morimoto return devm_snd_soc_register_component(&i2c_client->dev, 7892ff52976SKuninori Morimoto &soc_component_dev_es8316, 790b8b88b70SDaniel Drake &es8316_dai, 1); 791b8b88b70SDaniel Drake } 792b8b88b70SDaniel Drake 793b8b88b70SDaniel Drake static const struct i2c_device_id es8316_i2c_id[] = { 794b8b88b70SDaniel Drake {"es8316", 0 }, 795b8b88b70SDaniel Drake {} 796b8b88b70SDaniel Drake }; 797b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(i2c, es8316_i2c_id); 798b8b88b70SDaniel Drake 799b8b88b70SDaniel Drake static const struct of_device_id es8316_of_match[] = { 800b8b88b70SDaniel Drake { .compatible = "everest,es8316", }, 801b8b88b70SDaniel Drake {}, 802b8b88b70SDaniel Drake }; 803b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(of, es8316_of_match); 804b8b88b70SDaniel Drake 805b8b88b70SDaniel Drake static const struct acpi_device_id es8316_acpi_match[] = { 806b8b88b70SDaniel Drake {"ESSX8316", 0}, 807b8b88b70SDaniel Drake {}, 808b8b88b70SDaniel Drake }; 809b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); 810b8b88b70SDaniel Drake 811b8b88b70SDaniel Drake static struct i2c_driver es8316_i2c_driver = { 812b8b88b70SDaniel Drake .driver = { 813b8b88b70SDaniel Drake .name = "es8316", 814b8b88b70SDaniel Drake .acpi_match_table = ACPI_PTR(es8316_acpi_match), 815b8b88b70SDaniel Drake .of_match_table = of_match_ptr(es8316_of_match), 816b8b88b70SDaniel Drake }, 817b8b88b70SDaniel Drake .probe = es8316_i2c_probe, 818b8b88b70SDaniel Drake .id_table = es8316_i2c_id, 819b8b88b70SDaniel Drake }; 820b8b88b70SDaniel Drake module_i2c_driver(es8316_i2c_driver); 821b8b88b70SDaniel Drake 822b8b88b70SDaniel Drake MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver"); 823b8b88b70SDaniel Drake MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>"); 824b8b88b70SDaniel Drake MODULE_LICENSE("GPL v2"); 825