xref: /openbmc/linux/sound/soc/codecs/es8316.c (revision 6dd567dc)
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>
126dd567dcSKatsuhiro Suzuki #include <linux/clk.h>
13b8b88b70SDaniel Drake #include <linux/delay.h>
14b8b88b70SDaniel Drake #include <linux/i2c.h>
15b8b88b70SDaniel Drake #include <linux/mod_devicetable.h>
1682225766SHans de Goede #include <linux/mutex.h>
17b8b88b70SDaniel Drake #include <linux/regmap.h>
18b8b88b70SDaniel Drake #include <sound/pcm.h>
19b8b88b70SDaniel Drake #include <sound/pcm_params.h>
20b8b88b70SDaniel Drake #include <sound/soc.h>
21b8b88b70SDaniel Drake #include <sound/soc-dapm.h>
22b8b88b70SDaniel Drake #include <sound/tlv.h>
2382225766SHans de Goede #include <sound/jack.h>
24b8b88b70SDaniel Drake #include "es8316.h"
25b8b88b70SDaniel Drake 
26b8b88b70SDaniel Drake /* In slave mode at single speed, the codec is documented as accepting 5
27b8b88b70SDaniel Drake  * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
28b8b88b70SDaniel Drake  * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
29b8b88b70SDaniel Drake  */
30b8b88b70SDaniel Drake #define NR_SUPPORTED_MCLK_LRCK_RATIOS 6
31b8b88b70SDaniel Drake static const unsigned int supported_mclk_lrck_ratios[] = {
32b8b88b70SDaniel Drake 	256, 384, 400, 512, 768, 1024
33b8b88b70SDaniel Drake };
34b8b88b70SDaniel Drake 
35b8b88b70SDaniel Drake struct es8316_priv {
3682225766SHans de Goede 	struct mutex lock;
376dd567dcSKatsuhiro Suzuki 	struct clk *mclk;
3882225766SHans de Goede 	struct regmap *regmap;
3982225766SHans de Goede 	struct snd_soc_component *component;
4082225766SHans de Goede 	struct snd_soc_jack *jack;
4182225766SHans de Goede 	int irq;
42b8b88b70SDaniel Drake 	unsigned int sysclk;
43b8b88b70SDaniel Drake 	unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
44b8b88b70SDaniel Drake 	struct snd_pcm_hw_constraint_list sysclk_constraints;
450bbcedd6SPaul Cercueil 	bool jd_inverted;
46b8b88b70SDaniel Drake };
47b8b88b70SDaniel Drake 
48b8b88b70SDaniel Drake /*
49b8b88b70SDaniel Drake  * ES8316 controls
50b8b88b70SDaniel Drake  */
51b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
52b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
53b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
54b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
55b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
56b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
57b8b88b70SDaniel Drake 
58b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
59b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
60b8b88b70SDaniel Drake 	1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
61b8b88b70SDaniel Drake 	2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
62b8b88b70SDaniel Drake 	3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
63b8b88b70SDaniel Drake 	4, 4, TLV_DB_SCALE_ITEM(700, 0, 0),
64b8b88b70SDaniel Drake 	5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0),
65b8b88b70SDaniel Drake 	6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0),
66b8b88b70SDaniel Drake 	7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0),
67b8b88b70SDaniel Drake 	8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0),
68b8b88b70SDaniel Drake 	9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0),
69b8b88b70SDaniel Drake 	10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0),
70b8b88b70SDaniel Drake );
71b8b88b70SDaniel Drake 
72b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
73b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
74b8b88b70SDaniel Drake 	1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
75b8b88b70SDaniel Drake );
76b8b88b70SDaniel Drake 
77b8b88b70SDaniel Drake static const char * const ng_type_txt[] =
78b8b88b70SDaniel Drake 	{ "Constant PGA Gain", "Mute ADC Output" };
79b8b88b70SDaniel Drake static const struct soc_enum ng_type =
80b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt);
81b8b88b70SDaniel Drake 
82b8b88b70SDaniel Drake static const char * const adcpol_txt[] = { "Normal", "Invert" };
83b8b88b70SDaniel Drake static const struct soc_enum adcpol =
84b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt);
85b8b88b70SDaniel Drake static const char *const dacpol_txt[] =
86b8b88b70SDaniel Drake 	{ "Normal", "R Invert", "L Invert", "L + R Invert" };
87b8b88b70SDaniel Drake static const struct soc_enum dacpol =
88b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt);
89b8b88b70SDaniel Drake 
90b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_snd_controls[] = {
91b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
92b8b88b70SDaniel Drake 		       4, 0, 3, 1, hpout_vol_tlv),
93b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
94b8b88b70SDaniel Drake 		       0, 4, 7, 0, hpmixer_gain_tlv),
95b8b88b70SDaniel Drake 
96b8b88b70SDaniel Drake 	SOC_ENUM("Playback Polarity", dacpol),
97b8b88b70SDaniel Drake 	SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
98b8b88b70SDaniel Drake 			 ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv),
99b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
100b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
101b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
102b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
103b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
10424b53f17SHans de Goede 	SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0),
105b8b88b70SDaniel Drake 
106b8b88b70SDaniel Drake 	SOC_ENUM("Capture Polarity", adcpol),
107b8b88b70SDaniel Drake 	SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
108b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME,
109b8b88b70SDaniel Drake 		       0, 0xc0, 1, adc_vol_tlv),
110b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN,
111b8b88b70SDaniel Drake 		       4, 10, 0, adc_pga_gain_tlv),
112b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0),
113b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0),
114b8b88b70SDaniel Drake 
115b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0),
116b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0,
117b8b88b70SDaniel Drake 		       alc_max_gain_tlv),
118b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0,
119b8b88b70SDaniel Drake 		       alc_min_gain_tlv),
120b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0,
121b8b88b70SDaniel Drake 		       alc_target_tlv),
122b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0),
123b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0),
124b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0),
125b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG,
126b8b88b70SDaniel Drake 		   5, 1, 0),
127b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG,
128b8b88b70SDaniel Drake 		   0, 31, 0),
129b8b88b70SDaniel Drake 	SOC_ENUM("ALC Capture Noise Gate Type", ng_type),
130b8b88b70SDaniel Drake };
131b8b88b70SDaniel Drake 
132b8b88b70SDaniel Drake /* Analog Input Mux */
133b8b88b70SDaniel Drake static const char * const es8316_analog_in_txt[] = {
134b8b88b70SDaniel Drake 		"lin1-rin1",
135b8b88b70SDaniel Drake 		"lin2-rin2",
136b8b88b70SDaniel Drake 		"lin1-rin1 with 20db Boost",
137b8b88b70SDaniel Drake 		"lin2-rin2 with 20db Boost"
138b8b88b70SDaniel Drake };
139b8b88b70SDaniel Drake static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 };
140b8b88b70SDaniel Drake static const struct soc_enum es8316_analog_input_enum =
141b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3,
142b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_analog_in_txt),
143b8b88b70SDaniel Drake 			      es8316_analog_in_txt,
144b8b88b70SDaniel Drake 			      es8316_analog_in_values);
145b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_analog_in_mux_controls =
146b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_analog_input_enum);
147b8b88b70SDaniel Drake 
148b8b88b70SDaniel Drake static const char * const es8316_dmic_txt[] = {
149b8b88b70SDaniel Drake 		"dmic disable",
150b8b88b70SDaniel Drake 		"dmic data at high level",
151b8b88b70SDaniel Drake 		"dmic data at low level",
152b8b88b70SDaniel Drake };
153b8b88b70SDaniel Drake static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
154b8b88b70SDaniel Drake static const struct soc_enum es8316_dmic_src_enum =
155b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
156b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_dmic_txt),
157b8b88b70SDaniel Drake 			      es8316_dmic_txt,
158b8b88b70SDaniel Drake 			      es8316_dmic_values);
159b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dmic_src_controls =
160b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dmic_src_enum);
161b8b88b70SDaniel Drake 
162b8b88b70SDaniel Drake /* hp mixer mux */
163b8b88b70SDaniel Drake static const char * const es8316_hpmux_texts[] = {
164b8b88b70SDaniel Drake 	"lin1-rin1",
165b8b88b70SDaniel Drake 	"lin2-rin2",
166b8b88b70SDaniel Drake 	"lin-rin with Boost",
167b8b88b70SDaniel Drake 	"lin-rin with Boost and PGA"
168b8b88b70SDaniel Drake };
169b8b88b70SDaniel Drake 
170b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
171b8b88b70SDaniel Drake 	4, es8316_hpmux_texts);
172b8b88b70SDaniel Drake 
173b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_left_hpmux_controls =
174b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum);
175b8b88b70SDaniel Drake 
176b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL,
177b8b88b70SDaniel Drake 	0, es8316_hpmux_texts);
178b8b88b70SDaniel Drake 
179b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_right_hpmux_controls =
180b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum);
181b8b88b70SDaniel Drake 
182b8b88b70SDaniel Drake /* headphone Output Mixer */
183b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_left_mix[] = {
184b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0),
185b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
186b8b88b70SDaniel Drake };
187b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_right_mix[] = {
188b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0),
189b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
190b8b88b70SDaniel Drake };
191b8b88b70SDaniel Drake 
192b8b88b70SDaniel Drake /* DAC data source mux */
193b8b88b70SDaniel Drake static const char * const es8316_dacsrc_texts[] = {
194b8b88b70SDaniel Drake 	"LDATA TO LDAC, RDATA TO RDAC",
195b8b88b70SDaniel Drake 	"LDATA TO LDAC, LDATA TO RDAC",
196b8b88b70SDaniel Drake 	"RDATA TO LDAC, RDATA TO RDAC",
197b8b88b70SDaniel Drake 	"RDATA TO LDAC, LDATA TO RDAC",
198b8b88b70SDaniel Drake };
199b8b88b70SDaniel Drake 
200b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
201b8b88b70SDaniel Drake 	6, es8316_dacsrc_texts);
202b8b88b70SDaniel Drake 
203b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dacsrc_mux_controls =
204b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum);
205b8b88b70SDaniel Drake 
206b8b88b70SDaniel Drake static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = {
207b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0),
208b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0),
209b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0),
210b8b88b70SDaniel Drake 
211b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("DMIC"),
212b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC1"),
213b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC2"),
214b8b88b70SDaniel Drake 
215b8b88b70SDaniel Drake 	/* Input Mux */
216b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
217b8b88b70SDaniel Drake 			 &es8316_analog_in_mux_controls),
218b8b88b70SDaniel Drake 
219b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0),
220b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0),
221b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0),
222b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL,
223b8b88b70SDaniel Drake 			 7, 1, NULL, 0),
224b8b88b70SDaniel Drake 	SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1),
225b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0,
226b8b88b70SDaniel Drake 			 &es8316_dmic_src_controls),
227b8b88b70SDaniel Drake 
228b8b88b70SDaniel Drake 	/* Digital Interface */
229b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture",  1,
230b8b88b70SDaniel Drake 			     ES8316_SERDATA_ADC, 6, 1),
231b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0,
232b8b88b70SDaniel Drake 			    SND_SOC_NOPM, 0, 0),
233b8b88b70SDaniel Drake 
234b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
235b8b88b70SDaniel Drake 			 &es8316_dacsrc_mux_controls),
236b8b88b70SDaniel Drake 
237b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
238b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
239b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
240b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
241b8b88b70SDaniel Drake 
242b8b88b70SDaniel Drake 	/* Headphone Output Side */
243b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
244b8b88b70SDaniel Drake 			 &es8316_left_hpmux_controls),
245b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
246b8b88b70SDaniel Drake 			 &es8316_right_hpmux_controls),
247b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN,
248b8b88b70SDaniel Drake 			   5, 1, &es8316_out_left_mix[0],
249b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_left_mix)),
250b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN,
251b8b88b70SDaniel Drake 			   1, 1, &es8316_out_right_mix[0],
252b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_right_mix)),
253b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN,
254b8b88b70SDaniel Drake 			 4, 1, NULL, 0),
255b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN,
256b8b88b70SDaniel Drake 			 0, 1, NULL, 0),
257b8b88b70SDaniel Drake 
258b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN,
259b8b88b70SDaniel Drake 			     6, 0, NULL, 0),
260b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN,
261b8b88b70SDaniel Drake 			     2, 0, NULL, 0),
262b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2,
263b8b88b70SDaniel Drake 			    5, 1, NULL, 0),
264b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW,
265b8b88b70SDaniel Drake 			    4, 0, NULL, 0),
266b8b88b70SDaniel Drake 
267b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN,
268b8b88b70SDaniel Drake 			     5, 0, NULL, 0),
269b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN,
270b8b88b70SDaniel Drake 			     1, 0, NULL, 0),
271b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0),
272b8b88b70SDaniel Drake 
273b8b88b70SDaniel Drake 	/* pdn_Lical and pdn_Rical bits are documented as Reserved, but must
274b8b88b70SDaniel Drake 	 * be explicitly unset in order to enable HP output
275b8b88b70SDaniel Drake 	 */
276b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL,
277b8b88b70SDaniel Drake 			    7, 1, NULL, 0),
278b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL,
279b8b88b70SDaniel Drake 			    3, 1, NULL, 0),
280b8b88b70SDaniel Drake 
281b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOL"),
282b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOR"),
283b8b88b70SDaniel Drake };
284b8b88b70SDaniel Drake 
285b8b88b70SDaniel Drake static const struct snd_soc_dapm_route es8316_dapm_routes[] = {
286b8b88b70SDaniel Drake 	/* Recording */
287b8b88b70SDaniel Drake 	{"MIC1", NULL, "Mic Bias"},
288b8b88b70SDaniel Drake 	{"MIC2", NULL, "Mic Bias"},
289b8b88b70SDaniel Drake 	{"MIC1", NULL, "Bias"},
290b8b88b70SDaniel Drake 	{"MIC2", NULL, "Bias"},
291b8b88b70SDaniel Drake 	{"MIC1", NULL, "Analog power"},
292b8b88b70SDaniel Drake 	{"MIC2", NULL, "Analog power"},
293b8b88b70SDaniel Drake 
294b8b88b70SDaniel Drake 	{"Differential Mux", "lin1-rin1", "MIC1"},
295b8b88b70SDaniel Drake 	{"Differential Mux", "lin2-rin2", "MIC2"},
296b8b88b70SDaniel Drake 	{"Line input PGA", NULL, "Differential Mux"},
297b8b88b70SDaniel Drake 
298b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Clock"},
299b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Vref"},
300b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC bias"},
301b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "Line input PGA"},
302b8b88b70SDaniel Drake 
303b8b88b70SDaniel Drake 	/* It's not clear why, but to avoid recording only silence,
304b8b88b70SDaniel Drake 	 * the DAC clock must be running for the ADC to work.
305b8b88b70SDaniel Drake 	 */
306b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "DAC Clock"},
307b8b88b70SDaniel Drake 
308b8b88b70SDaniel Drake 	{"Digital Mic Mux", "dmic disable", "Mono ADC"},
309b8b88b70SDaniel Drake 
310b8b88b70SDaniel Drake 	{"I2S OUT", NULL, "Digital Mic Mux"},
311b8b88b70SDaniel Drake 
312b8b88b70SDaniel Drake 	/* Playback */
313b8b88b70SDaniel Drake 	{"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
314b8b88b70SDaniel Drake 
315b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Clock"},
316b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Clock"},
317b8b88b70SDaniel Drake 
318b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Vref"},
319b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Vref"},
320b8b88b70SDaniel Drake 
321b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Source Mux"},
322b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Source Mux"},
323b8b88b70SDaniel Drake 
324b8b88b70SDaniel Drake 	{"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
325b8b88b70SDaniel Drake 	{"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
326b8b88b70SDaniel Drake 
327b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"},
328b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
329b8b88b70SDaniel Drake 
330b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"},
331b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
332b8b88b70SDaniel Drake 
333b8b88b70SDaniel Drake 	{"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"},
334b8b88b70SDaniel Drake 	{"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"},
335b8b88b70SDaniel Drake 
336b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"},
337b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"},
338b8b88b70SDaniel Drake 
339b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"},
340b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"},
341b8b88b70SDaniel Drake 
342b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
343b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
344b8b88b70SDaniel Drake 
345b8b88b70SDaniel Drake 	{"Left Headphone Driver", NULL, "Left Headphone Charge Pump"},
346b8b88b70SDaniel Drake 	{"Right Headphone Driver", NULL, "Right Headphone Charge Pump"},
347b8b88b70SDaniel Drake 
348b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone Driver"},
349b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone Driver"},
350b8b88b70SDaniel Drake 
351b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone ical"},
352b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone ical"},
353b8b88b70SDaniel Drake 
354b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Bias"},
355b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Analog power"},
356b8b88b70SDaniel Drake 	{"HPOL", NULL, "Headphone Out"},
357b8b88b70SDaniel Drake 	{"HPOR", NULL, "Headphone Out"},
358b8b88b70SDaniel Drake };
359b8b88b70SDaniel Drake 
360b8b88b70SDaniel Drake static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
361b8b88b70SDaniel Drake 				 int clk_id, unsigned int freq, int dir)
362b8b88b70SDaniel Drake {
3632ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
3642ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
3656dd567dcSKatsuhiro Suzuki 	int i, ret;
366b8b88b70SDaniel Drake 	int count = 0;
367b8b88b70SDaniel Drake 
368b8b88b70SDaniel Drake 	es8316->sysclk = freq;
369b8b88b70SDaniel Drake 
370b8b88b70SDaniel Drake 	if (freq == 0)
371b8b88b70SDaniel Drake 		return 0;
372b8b88b70SDaniel Drake 
3736dd567dcSKatsuhiro Suzuki 	if (es8316->mclk) {
3746dd567dcSKatsuhiro Suzuki 		ret = clk_set_rate(es8316->mclk, freq);
3756dd567dcSKatsuhiro Suzuki 		if (ret)
3766dd567dcSKatsuhiro Suzuki 			return ret;
3776dd567dcSKatsuhiro Suzuki 	}
3786dd567dcSKatsuhiro Suzuki 
379b8b88b70SDaniel Drake 	/* Limit supported sample rates to ones that can be autodetected
380b8b88b70SDaniel Drake 	 * by the codec running in slave mode.
381b8b88b70SDaniel Drake 	 */
382b8b88b70SDaniel Drake 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
383b8b88b70SDaniel Drake 		const unsigned int ratio = supported_mclk_lrck_ratios[i];
384b8b88b70SDaniel Drake 
385b8b88b70SDaniel Drake 		if (freq % ratio == 0)
386b8b88b70SDaniel Drake 			es8316->allowed_rates[count++] = freq / ratio;
387b8b88b70SDaniel Drake 	}
388b8b88b70SDaniel Drake 
389b8b88b70SDaniel Drake 	es8316->sysclk_constraints.list = es8316->allowed_rates;
390b8b88b70SDaniel Drake 	es8316->sysclk_constraints.count = count;
391b8b88b70SDaniel Drake 
392b8b88b70SDaniel Drake 	return 0;
393b8b88b70SDaniel Drake }
394b8b88b70SDaniel Drake 
395b8b88b70SDaniel Drake static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai,
396b8b88b70SDaniel Drake 			      unsigned int fmt)
397b8b88b70SDaniel Drake {
3982ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
399b8b88b70SDaniel Drake 	u8 serdata1 = 0;
400b8b88b70SDaniel Drake 	u8 serdata2 = 0;
401b8b88b70SDaniel Drake 	u8 clksw;
402b8b88b70SDaniel Drake 	u8 mask;
403b8b88b70SDaniel Drake 
404b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
4052ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports slave mode\n");
406b8b88b70SDaniel Drake 		return -EINVAL;
407b8b88b70SDaniel Drake 	}
408b8b88b70SDaniel Drake 
409b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
4102ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports I2S format\n");
411b8b88b70SDaniel Drake 		return -EINVAL;
412b8b88b70SDaniel Drake 	}
413b8b88b70SDaniel Drake 
414b8b88b70SDaniel Drake 	/* Clock inversion */
415b8b88b70SDaniel Drake 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
416b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_NF:
417b8b88b70SDaniel Drake 		break;
418b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_IF:
419b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
420b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
421b8b88b70SDaniel Drake 		break;
422b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_NF:
423b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
424b8b88b70SDaniel Drake 		break;
425b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_IF:
426b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
427b8b88b70SDaniel Drake 		break;
428b8b88b70SDaniel Drake 	default:
429b8b88b70SDaniel Drake 		return -EINVAL;
430b8b88b70SDaniel Drake 	}
431b8b88b70SDaniel Drake 
432b8b88b70SDaniel Drake 	mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
4332ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA1, mask, serdata1);
434b8b88b70SDaniel Drake 
435b8b88b70SDaniel Drake 	mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
4362ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, mask, serdata2);
4372ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, mask, serdata2);
438b8b88b70SDaniel Drake 
439b8b88b70SDaniel Drake 	/* Enable BCLK and MCLK inputs in slave mode */
440b8b88b70SDaniel Drake 	clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
4412ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW, clksw, clksw);
442b8b88b70SDaniel Drake 
443b8b88b70SDaniel Drake 	return 0;
444b8b88b70SDaniel Drake }
445b8b88b70SDaniel Drake 
446b8b88b70SDaniel Drake static int es8316_pcm_startup(struct snd_pcm_substream *substream,
447b8b88b70SDaniel Drake 			      struct snd_soc_dai *dai)
448b8b88b70SDaniel Drake {
4492ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4502ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
451b8b88b70SDaniel Drake 
452b8b88b70SDaniel Drake 	if (es8316->sysclk == 0) {
4532ff52976SKuninori Morimoto 		dev_err(component->dev, "No sysclk provided\n");
454b8b88b70SDaniel Drake 		return -EINVAL;
455b8b88b70SDaniel Drake 	}
456b8b88b70SDaniel Drake 
457b8b88b70SDaniel Drake 	/* The set of sample rates that can be supported depends on the
458b8b88b70SDaniel Drake 	 * MCLK supplied to the CODEC.
459b8b88b70SDaniel Drake 	 */
460b8b88b70SDaniel Drake 	snd_pcm_hw_constraint_list(substream->runtime, 0,
461b8b88b70SDaniel Drake 				   SNDRV_PCM_HW_PARAM_RATE,
462b8b88b70SDaniel Drake 				   &es8316->sysclk_constraints);
463b8b88b70SDaniel Drake 
464b8b88b70SDaniel Drake 	return 0;
465b8b88b70SDaniel Drake }
466b8b88b70SDaniel Drake 
467b8b88b70SDaniel Drake static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
468b8b88b70SDaniel Drake 				struct snd_pcm_hw_params *params,
469b8b88b70SDaniel Drake 				struct snd_soc_dai *dai)
470b8b88b70SDaniel Drake {
4712ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4722ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
473b8b88b70SDaniel Drake 	u8 wordlen = 0;
474b8b88b70SDaniel Drake 
475b8b88b70SDaniel Drake 	if (!es8316->sysclk) {
4762ff52976SKuninori Morimoto 		dev_err(component->dev, "No MCLK configured\n");
477b8b88b70SDaniel Drake 		return -EINVAL;
478b8b88b70SDaniel Drake 	}
479b8b88b70SDaniel Drake 
480b8b88b70SDaniel Drake 	switch (params_format(params)) {
481b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S16_LE:
482b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_16;
483b8b88b70SDaniel Drake 		break;
484b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S20_3LE:
485b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_20;
486b8b88b70SDaniel Drake 		break;
487b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S24_LE:
488b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_24;
489b8b88b70SDaniel Drake 		break;
490b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S32_LE:
491b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_32;
492b8b88b70SDaniel Drake 		break;
493b8b88b70SDaniel Drake 	default:
494b8b88b70SDaniel Drake 		return -EINVAL;
495b8b88b70SDaniel Drake 	}
496b8b88b70SDaniel Drake 
4972ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
498b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
4992ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
500b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
501b8b88b70SDaniel Drake 	return 0;
502b8b88b70SDaniel Drake }
503b8b88b70SDaniel Drake 
504b8b88b70SDaniel Drake static int es8316_mute(struct snd_soc_dai *dai, int mute)
505b8b88b70SDaniel Drake {
5062ff52976SKuninori Morimoto 	snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20,
507b8b88b70SDaniel Drake 			    mute ? 0x20 : 0);
508b8b88b70SDaniel Drake 	return 0;
509b8b88b70SDaniel Drake }
510b8b88b70SDaniel Drake 
511b8b88b70SDaniel Drake #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
512b8b88b70SDaniel Drake 			SNDRV_PCM_FMTBIT_S24_LE)
513b8b88b70SDaniel Drake 
514eb59d73cSArvind Yadav static const struct snd_soc_dai_ops es8316_ops = {
515b8b88b70SDaniel Drake 	.startup = es8316_pcm_startup,
516b8b88b70SDaniel Drake 	.hw_params = es8316_pcm_hw_params,
517b8b88b70SDaniel Drake 	.set_fmt = es8316_set_dai_fmt,
518b8b88b70SDaniel Drake 	.set_sysclk = es8316_set_dai_sysclk,
519b8b88b70SDaniel Drake 	.digital_mute = es8316_mute,
520b8b88b70SDaniel Drake };
521b8b88b70SDaniel Drake 
522b8b88b70SDaniel Drake static struct snd_soc_dai_driver es8316_dai = {
523b8b88b70SDaniel Drake 	.name = "ES8316 HiFi",
524b8b88b70SDaniel Drake 	.playback = {
525b8b88b70SDaniel Drake 		.stream_name = "Playback",
526b8b88b70SDaniel Drake 		.channels_min = 1,
527b8b88b70SDaniel Drake 		.channels_max = 2,
528b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
529b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
530b8b88b70SDaniel Drake 	},
531b8b88b70SDaniel Drake 	.capture = {
532b8b88b70SDaniel Drake 		.stream_name = "Capture",
533b8b88b70SDaniel Drake 		.channels_min = 1,
534b8b88b70SDaniel Drake 		.channels_max = 2,
535b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
536b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
537b8b88b70SDaniel Drake 	},
538b8b88b70SDaniel Drake 	.ops = &es8316_ops,
539b8b88b70SDaniel Drake 	.symmetric_rates = 1,
540b8b88b70SDaniel Drake };
541b8b88b70SDaniel Drake 
54282225766SHans de Goede static void es8316_enable_micbias_for_mic_gnd_short_detect(
54382225766SHans de Goede 	struct snd_soc_component *component)
54482225766SHans de Goede {
54582225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
54682225766SHans de Goede 
54782225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
54882225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias");
54982225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power");
55082225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias");
55182225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
55282225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
55382225766SHans de Goede 
55482225766SHans de Goede 	msleep(20);
55582225766SHans de Goede }
55682225766SHans de Goede 
55782225766SHans de Goede static void es8316_disable_micbias_for_mic_gnd_short_detect(
55882225766SHans de Goede 	struct snd_soc_component *component)
55982225766SHans de Goede {
56082225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
56182225766SHans de Goede 
56282225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
56382225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias");
56482225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power");
56582225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Bias");
56682225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
56782225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
56882225766SHans de Goede }
56982225766SHans de Goede 
57082225766SHans de Goede static irqreturn_t es8316_irq(int irq, void *data)
57182225766SHans de Goede {
57282225766SHans de Goede 	struct es8316_priv *es8316 = data;
57382225766SHans de Goede 	struct snd_soc_component *comp = es8316->component;
57482225766SHans de Goede 	unsigned int flags;
57582225766SHans de Goede 
57682225766SHans de Goede 	mutex_lock(&es8316->lock);
57782225766SHans de Goede 
57882225766SHans de Goede 	regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
57982225766SHans de Goede 	if (flags == 0x00)
58082225766SHans de Goede 		goto out; /* Powered-down / reset */
58182225766SHans de Goede 
58282225766SHans de Goede 	/* Catch spurious IRQ before set_jack is called */
58382225766SHans de Goede 	if (!es8316->jack)
58482225766SHans de Goede 		goto out;
58582225766SHans de Goede 
5860bbcedd6SPaul Cercueil 	if (es8316->jd_inverted)
5870bbcedd6SPaul Cercueil 		flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
5880bbcedd6SPaul Cercueil 
58982225766SHans de Goede 	dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
59082225766SHans de Goede 	if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
59182225766SHans de Goede 		/* Jack removed, or spurious IRQ? */
59282225766SHans de Goede 		if (es8316->jack->status & SND_JACK_MICROPHONE)
59382225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
59482225766SHans de Goede 
59582225766SHans de Goede 		if (es8316->jack->status & SND_JACK_HEADPHONE) {
59682225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0,
59782225766SHans de Goede 					    SND_JACK_HEADSET | SND_JACK_BTN_0);
59882225766SHans de Goede 			dev_dbg(comp->dev, "jack unplugged\n");
59982225766SHans de Goede 		}
60082225766SHans de Goede 	} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
60182225766SHans de Goede 		/* Jack inserted, determine type */
60282225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(comp);
60382225766SHans de Goede 		regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
6040bbcedd6SPaul Cercueil 		if (es8316->jd_inverted)
6050bbcedd6SPaul Cercueil 			flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
60682225766SHans de Goede 		dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
60782225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
60882225766SHans de Goede 			/* Jack unplugged underneath us */
60982225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
61082225766SHans de Goede 		} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
61182225766SHans de Goede 			/* Open, headset */
61282225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
61382225766SHans de Goede 					    SND_JACK_HEADSET,
61482225766SHans de Goede 					    SND_JACK_HEADSET);
61582225766SHans de Goede 			/* Keep mic-gnd-short detection on for button press */
61682225766SHans de Goede 		} else {
61782225766SHans de Goede 			/* Shorted, headphones */
61882225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
61982225766SHans de Goede 					    SND_JACK_HEADPHONE,
62082225766SHans de Goede 					    SND_JACK_HEADSET);
62182225766SHans de Goede 			/* No longer need mic-gnd-short detection */
62282225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
62382225766SHans de Goede 		}
62482225766SHans de Goede 	} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
62582225766SHans de Goede 		/* Interrupt while jack inserted, report button state */
62682225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
62782225766SHans de Goede 			/* Open, button release */
62882225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
62982225766SHans de Goede 		} else {
63082225766SHans de Goede 			/* Short, button press */
63182225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
63282225766SHans de Goede 					    SND_JACK_BTN_0,
63382225766SHans de Goede 					    SND_JACK_BTN_0);
63482225766SHans de Goede 		}
63582225766SHans de Goede 	}
63682225766SHans de Goede 
63782225766SHans de Goede out:
63882225766SHans de Goede 	mutex_unlock(&es8316->lock);
63982225766SHans de Goede 	return IRQ_HANDLED;
64082225766SHans de Goede }
64182225766SHans de Goede 
64282225766SHans de Goede static void es8316_enable_jack_detect(struct snd_soc_component *component,
64382225766SHans de Goede 				      struct snd_soc_jack *jack)
64482225766SHans de Goede {
64582225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
64682225766SHans de Goede 
6470bbcedd6SPaul Cercueil 	/*
6480bbcedd6SPaul Cercueil 	 * Init es8316->jd_inverted here and not in the probe, as we cannot
6490bbcedd6SPaul Cercueil 	 * guarantee that the bytchr-es8316 driver, which might set this
6500bbcedd6SPaul Cercueil 	 * property, will probe before us.
6510bbcedd6SPaul Cercueil 	 */
6520bbcedd6SPaul Cercueil 	es8316->jd_inverted = device_property_read_bool(component->dev,
6530bbcedd6SPaul Cercueil 							"everest,jack-detect-inverted");
6540bbcedd6SPaul Cercueil 
65582225766SHans de Goede 	mutex_lock(&es8316->lock);
65682225766SHans de Goede 
65782225766SHans de Goede 	es8316->jack = jack;
65882225766SHans de Goede 
65982225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE)
66082225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(component);
66182225766SHans de Goede 
66282225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
66382225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT,
66482225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT);
66582225766SHans de Goede 
66682225766SHans de Goede 	mutex_unlock(&es8316->lock);
66782225766SHans de Goede 
66882225766SHans de Goede 	/* Enable irq and sync initial jack state */
66982225766SHans de Goede 	enable_irq(es8316->irq);
67082225766SHans de Goede 	es8316_irq(es8316->irq, es8316);
67182225766SHans de Goede }
67282225766SHans de Goede 
67382225766SHans de Goede static void es8316_disable_jack_detect(struct snd_soc_component *component)
67482225766SHans de Goede {
67582225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
67682225766SHans de Goede 
67782225766SHans de Goede 	disable_irq(es8316->irq);
67882225766SHans de Goede 
67982225766SHans de Goede 	mutex_lock(&es8316->lock);
68082225766SHans de Goede 
68182225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
68282225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT, 0);
68382225766SHans de Goede 
68482225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE) {
68582225766SHans de Goede 		es8316_disable_micbias_for_mic_gnd_short_detect(component);
68682225766SHans de Goede 		snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
68782225766SHans de Goede 	}
68882225766SHans de Goede 
68982225766SHans de Goede 	es8316->jack = NULL;
69082225766SHans de Goede 
69182225766SHans de Goede 	mutex_unlock(&es8316->lock);
69282225766SHans de Goede }
69382225766SHans de Goede 
69482225766SHans de Goede static int es8316_set_jack(struct snd_soc_component *component,
69582225766SHans de Goede 			   struct snd_soc_jack *jack, void *data)
69682225766SHans de Goede {
69782225766SHans de Goede 	if (jack)
69882225766SHans de Goede 		es8316_enable_jack_detect(component, jack);
69982225766SHans de Goede 	else
70082225766SHans de Goede 		es8316_disable_jack_detect(component);
70182225766SHans de Goede 
70282225766SHans de Goede 	return 0;
70382225766SHans de Goede }
70482225766SHans de Goede 
7052ff52976SKuninori Morimoto static int es8316_probe(struct snd_soc_component *component)
706b8b88b70SDaniel Drake {
70782225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7086dd567dcSKatsuhiro Suzuki 	int ret;
70982225766SHans de Goede 
71082225766SHans de Goede 	es8316->component = component;
71182225766SHans de Goede 
7126dd567dcSKatsuhiro Suzuki 	es8316->mclk = devm_clk_get(component->dev, "mclk");
7136dd567dcSKatsuhiro Suzuki 	if (PTR_ERR(es8316->mclk) == -EPROBE_DEFER)
7146dd567dcSKatsuhiro Suzuki 		return -EPROBE_DEFER;
7156dd567dcSKatsuhiro Suzuki 	if (IS_ERR(es8316->mclk)) {
7166dd567dcSKatsuhiro Suzuki 		dev_err(component->dev, "clock is invalid, ignored\n");
7176dd567dcSKatsuhiro Suzuki 		es8316->mclk = NULL;
7186dd567dcSKatsuhiro Suzuki 	}
7196dd567dcSKatsuhiro Suzuki 
7206dd567dcSKatsuhiro Suzuki 	if (es8316->mclk) {
7216dd567dcSKatsuhiro Suzuki 		ret = clk_prepare_enable(es8316->mclk);
7226dd567dcSKatsuhiro Suzuki 		if (ret) {
7236dd567dcSKatsuhiro Suzuki 			dev_err(component->dev, "unable to enable clock\n");
7246dd567dcSKatsuhiro Suzuki 			return ret;
7256dd567dcSKatsuhiro Suzuki 		}
7266dd567dcSKatsuhiro Suzuki 	}
7276dd567dcSKatsuhiro Suzuki 
728b8b88b70SDaniel Drake 	/* Reset codec and enable current state machine */
7292ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
730b8b88b70SDaniel Drake 	usleep_range(5000, 5500);
7312ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, ES8316_RESET_CSM_ON);
732b8b88b70SDaniel Drake 	msleep(30);
733b8b88b70SDaniel Drake 
734b8b88b70SDaniel Drake 	/*
735b8b88b70SDaniel Drake 	 * Documentation is unclear, but this value from the vendor driver is
736b8b88b70SDaniel Drake 	 * needed otherwise audio output is silent.
737b8b88b70SDaniel Drake 	 */
7382ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_SYS_VMIDSEL, 0xff);
739b8b88b70SDaniel Drake 
740b8b88b70SDaniel Drake 	/*
741b8b88b70SDaniel Drake 	 * Documentation for this register is unclear and incomplete,
742b8b88b70SDaniel Drake 	 * but here is a vendor-provided value that improves volume
743b8b88b70SDaniel Drake 	 * and quality for Intel CHT platforms.
744b8b88b70SDaniel Drake 	 */
7452ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
746b8b88b70SDaniel Drake 
747b8b88b70SDaniel Drake 	return 0;
748b8b88b70SDaniel Drake }
749b8b88b70SDaniel Drake 
7506dd567dcSKatsuhiro Suzuki static void es8316_remove(struct snd_soc_component *component)
7516dd567dcSKatsuhiro Suzuki {
7526dd567dcSKatsuhiro Suzuki 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7536dd567dcSKatsuhiro Suzuki 
7546dd567dcSKatsuhiro Suzuki 	if (es8316->mclk)
7556dd567dcSKatsuhiro Suzuki 		clk_disable_unprepare(es8316->mclk);
7566dd567dcSKatsuhiro Suzuki }
7576dd567dcSKatsuhiro Suzuki 
7582ff52976SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_es8316 = {
759b8b88b70SDaniel Drake 	.probe			= es8316_probe,
7606dd567dcSKatsuhiro Suzuki 	.remove			= es8316_remove,
76182225766SHans de Goede 	.set_jack		= es8316_set_jack,
762b8b88b70SDaniel Drake 	.controls		= es8316_snd_controls,
763b8b88b70SDaniel Drake 	.num_controls		= ARRAY_SIZE(es8316_snd_controls),
764b8b88b70SDaniel Drake 	.dapm_widgets		= es8316_dapm_widgets,
765b8b88b70SDaniel Drake 	.num_dapm_widgets	= ARRAY_SIZE(es8316_dapm_widgets),
766b8b88b70SDaniel Drake 	.dapm_routes		= es8316_dapm_routes,
767b8b88b70SDaniel Drake 	.num_dapm_routes	= ARRAY_SIZE(es8316_dapm_routes),
7682ff52976SKuninori Morimoto 	.use_pmdown_time	= 1,
7692ff52976SKuninori Morimoto 	.endianness		= 1,
7702ff52976SKuninori Morimoto 	.non_legacy_dai_naming	= 1,
771b8b88b70SDaniel Drake };
772b8b88b70SDaniel Drake 
77382225766SHans de Goede static const struct regmap_range es8316_volatile_ranges[] = {
77482225766SHans de Goede 	regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG),
77582225766SHans de Goede };
77682225766SHans de Goede 
77782225766SHans de Goede static const struct regmap_access_table es8316_volatile_table = {
77882225766SHans de Goede 	.yes_ranges	= es8316_volatile_ranges,
77982225766SHans de Goede 	.n_yes_ranges	= ARRAY_SIZE(es8316_volatile_ranges),
78082225766SHans de Goede };
78182225766SHans de Goede 
782b8b88b70SDaniel Drake static const struct regmap_config es8316_regmap = {
783b8b88b70SDaniel Drake 	.reg_bits = 8,
784b8b88b70SDaniel Drake 	.val_bits = 8,
785b8b88b70SDaniel Drake 	.max_register = 0x53,
78682225766SHans de Goede 	.volatile_table	= &es8316_volatile_table,
787b8b88b70SDaniel Drake 	.cache_type = REGCACHE_RBTREE,
788b8b88b70SDaniel Drake };
789b8b88b70SDaniel Drake 
790b8b88b70SDaniel Drake static int es8316_i2c_probe(struct i2c_client *i2c_client,
791b8b88b70SDaniel Drake 			    const struct i2c_device_id *id)
792b8b88b70SDaniel Drake {
79382225766SHans de Goede 	struct device *dev = &i2c_client->dev;
794b8b88b70SDaniel Drake 	struct es8316_priv *es8316;
79582225766SHans de Goede 	int ret;
796b8b88b70SDaniel Drake 
797b8b88b70SDaniel Drake 	es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
798b8b88b70SDaniel Drake 			      GFP_KERNEL);
799b8b88b70SDaniel Drake 	if (es8316 == NULL)
800b8b88b70SDaniel Drake 		return -ENOMEM;
801b8b88b70SDaniel Drake 
802b8b88b70SDaniel Drake 	i2c_set_clientdata(i2c_client, es8316);
803b8b88b70SDaniel Drake 
80482225766SHans de Goede 	es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
80582225766SHans de Goede 	if (IS_ERR(es8316->regmap))
80682225766SHans de Goede 		return PTR_ERR(es8316->regmap);
80782225766SHans de Goede 
80882225766SHans de Goede 	es8316->irq = i2c_client->irq;
80982225766SHans de Goede 	mutex_init(&es8316->lock);
81082225766SHans de Goede 
81182225766SHans de Goede 	ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq,
81282225766SHans de Goede 					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
81382225766SHans de Goede 					"es8316", es8316);
81482225766SHans de Goede 	if (ret == 0) {
81582225766SHans de Goede 		/* Gets re-enabled by es8316_set_jack() */
81682225766SHans de Goede 		disable_irq(es8316->irq);
81782225766SHans de Goede 	} else {
81882225766SHans de Goede 		dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret);
81982225766SHans de Goede 		es8316->irq = -ENXIO;
82082225766SHans de Goede 	}
821b8b88b70SDaniel Drake 
8222ff52976SKuninori Morimoto 	return devm_snd_soc_register_component(&i2c_client->dev,
8232ff52976SKuninori Morimoto 				      &soc_component_dev_es8316,
824b8b88b70SDaniel Drake 				      &es8316_dai, 1);
825b8b88b70SDaniel Drake }
826b8b88b70SDaniel Drake 
827b8b88b70SDaniel Drake static const struct i2c_device_id es8316_i2c_id[] = {
828b8b88b70SDaniel Drake 	{"es8316", 0 },
829b8b88b70SDaniel Drake 	{}
830b8b88b70SDaniel Drake };
831b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
832b8b88b70SDaniel Drake 
833b8b88b70SDaniel Drake static const struct of_device_id es8316_of_match[] = {
834b8b88b70SDaniel Drake 	{ .compatible = "everest,es8316", },
835b8b88b70SDaniel Drake 	{},
836b8b88b70SDaniel Drake };
837b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(of, es8316_of_match);
838b8b88b70SDaniel Drake 
839b8b88b70SDaniel Drake static const struct acpi_device_id es8316_acpi_match[] = {
840b8b88b70SDaniel Drake 	{"ESSX8316", 0},
841b8b88b70SDaniel Drake 	{},
842b8b88b70SDaniel Drake };
843b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
844b8b88b70SDaniel Drake 
845b8b88b70SDaniel Drake static struct i2c_driver es8316_i2c_driver = {
846b8b88b70SDaniel Drake 	.driver = {
847b8b88b70SDaniel Drake 		.name			= "es8316",
848b8b88b70SDaniel Drake 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
849b8b88b70SDaniel Drake 		.of_match_table		= of_match_ptr(es8316_of_match),
850b8b88b70SDaniel Drake 	},
851b8b88b70SDaniel Drake 	.probe		= es8316_i2c_probe,
852b8b88b70SDaniel Drake 	.id_table	= es8316_i2c_id,
853b8b88b70SDaniel Drake };
854b8b88b70SDaniel Drake module_i2c_driver(es8316_i2c_driver);
855b8b88b70SDaniel Drake 
856b8b88b70SDaniel Drake MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
857b8b88b70SDaniel Drake MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
858b8b88b70SDaniel Drake MODULE_LICENSE("GPL v2");
859