xref: /openbmc/linux/sound/soc/codecs/es8316.c (revision 39db65a0)
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);
56f972d02fSKatsuhiro Suzuki static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
57f972d02fSKatsuhiro Suzuki 	0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
58f972d02fSKatsuhiro Suzuki 	8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
59f972d02fSKatsuhiro Suzuki );
60b8b88b70SDaniel Drake 
61b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
62b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
63b8b88b70SDaniel Drake 	1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
64b8b88b70SDaniel Drake 	2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
65b8b88b70SDaniel Drake 	3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
66bb18c678SHans de Goede 	4, 7, TLV_DB_SCALE_ITEM(700, 300, 0),
67bb18c678SHans de Goede 	8, 10, TLV_DB_SCALE_ITEM(1800, 300, 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,
92f6e77921SKatsuhiro Suzuki 		       4, 0, 11, 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);
3636dd567dcSKatsuhiro Suzuki 	int i, ret;
364b8b88b70SDaniel Drake 	int count = 0;
365b8b88b70SDaniel Drake 
366b8b88b70SDaniel Drake 	es8316->sysclk = freq;
367b8b88b70SDaniel Drake 
368ebe02a5bSKatsuhiro Suzuki 	if (freq == 0) {
369ebe02a5bSKatsuhiro Suzuki 		es8316->sysclk_constraints.list = NULL;
370ebe02a5bSKatsuhiro Suzuki 		es8316->sysclk_constraints.count = 0;
371ebe02a5bSKatsuhiro Suzuki 
372b8b88b70SDaniel Drake 		return 0;
373ebe02a5bSKatsuhiro Suzuki 	}
374b8b88b70SDaniel Drake 
3756dd567dcSKatsuhiro Suzuki 	ret = clk_set_rate(es8316->mclk, freq);
3766dd567dcSKatsuhiro Suzuki 	if (ret)
3776dd567dcSKatsuhiro Suzuki 		return ret;
378b8b88b70SDaniel Drake 
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 
4043684020aSZhu Ning 	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBP_CFP)
4053684020aSZhu Ning 		serdata1 |= ES8316_SERDATA1_MASTER;
406b8b88b70SDaniel Drake 
407b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
4082ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports I2S format\n");
409b8b88b70SDaniel Drake 		return -EINVAL;
410b8b88b70SDaniel Drake 	}
411b8b88b70SDaniel Drake 
412b8b88b70SDaniel Drake 	/* Clock inversion */
413b8b88b70SDaniel Drake 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
414b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_NF:
415b8b88b70SDaniel Drake 		break;
416b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_IF:
417b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
418b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
419b8b88b70SDaniel Drake 		break;
420b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_NF:
421b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
422b8b88b70SDaniel Drake 		break;
423b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_IF:
424b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
425b8b88b70SDaniel Drake 		break;
426b8b88b70SDaniel Drake 	default:
427b8b88b70SDaniel Drake 		return -EINVAL;
428b8b88b70SDaniel Drake 	}
429b8b88b70SDaniel Drake 
430b8b88b70SDaniel Drake 	mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
4312ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA1, mask, serdata1);
432b8b88b70SDaniel Drake 
433b8b88b70SDaniel Drake 	mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
4342ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, mask, serdata2);
4352ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, mask, serdata2);
436b8b88b70SDaniel Drake 
437b8b88b70SDaniel Drake 	/* Enable BCLK and MCLK inputs in slave mode */
438b8b88b70SDaniel Drake 	clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
4392ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW, clksw, clksw);
440b8b88b70SDaniel Drake 
441b8b88b70SDaniel Drake 	return 0;
442b8b88b70SDaniel Drake }
443b8b88b70SDaniel Drake 
444b8b88b70SDaniel Drake static int es8316_pcm_startup(struct snd_pcm_substream *substream,
445b8b88b70SDaniel Drake 			      struct snd_soc_dai *dai)
446b8b88b70SDaniel Drake {
4472ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4482ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
449b8b88b70SDaniel Drake 
450ebe02a5bSKatsuhiro Suzuki 	if (es8316->sysclk_constraints.list)
451b8b88b70SDaniel Drake 		snd_pcm_hw_constraint_list(substream->runtime, 0,
452b8b88b70SDaniel Drake 					   SNDRV_PCM_HW_PARAM_RATE,
453b8b88b70SDaniel Drake 					   &es8316->sysclk_constraints);
454b8b88b70SDaniel Drake 
455b8b88b70SDaniel Drake 	return 0;
456b8b88b70SDaniel Drake }
457b8b88b70SDaniel Drake 
458b8b88b70SDaniel Drake static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
459b8b88b70SDaniel Drake 				struct snd_pcm_hw_params *params,
460b8b88b70SDaniel Drake 				struct snd_soc_dai *dai)
461b8b88b70SDaniel Drake {
4622ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4632ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
464b8b88b70SDaniel Drake 	u8 wordlen = 0;
4653684020aSZhu Ning 	u8 bclk_divider;
4663684020aSZhu Ning 	u16 lrck_divider;
467ebe02a5bSKatsuhiro Suzuki 	int i;
468b8b88b70SDaniel Drake 
469ebe02a5bSKatsuhiro Suzuki 	/* Validate supported sample rates that are autodetected from MCLK */
470ebe02a5bSKatsuhiro Suzuki 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
471ebe02a5bSKatsuhiro Suzuki 		const unsigned int ratio = supported_mclk_lrck_ratios[i];
472ebe02a5bSKatsuhiro Suzuki 
473ebe02a5bSKatsuhiro Suzuki 		if (es8316->sysclk % ratio != 0)
474ebe02a5bSKatsuhiro Suzuki 			continue;
475ebe02a5bSKatsuhiro Suzuki 		if (es8316->sysclk / ratio == params_rate(params))
476ebe02a5bSKatsuhiro Suzuki 			break;
477b8b88b70SDaniel Drake 	}
478ebe02a5bSKatsuhiro Suzuki 	if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
479ebe02a5bSKatsuhiro Suzuki 		return -EINVAL;
4803684020aSZhu Ning 	lrck_divider = es8316->sysclk / params_rate(params);
4813684020aSZhu Ning 	bclk_divider = lrck_divider / 4;
482b8b88b70SDaniel Drake 	switch (params_format(params)) {
483b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S16_LE:
484b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_16;
4853684020aSZhu Ning 		bclk_divider /= 16;
486b8b88b70SDaniel Drake 		break;
487b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S20_3LE:
488b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_20;
4893684020aSZhu Ning 		bclk_divider /= 20;
490b8b88b70SDaniel Drake 		break;
491b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S24_LE:
492b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_24;
4933684020aSZhu Ning 		bclk_divider /= 24;
494b8b88b70SDaniel Drake 		break;
495b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S32_LE:
496b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_32;
4973684020aSZhu Ning 		bclk_divider /= 32;
498b8b88b70SDaniel Drake 		break;
499b8b88b70SDaniel Drake 	default:
500b8b88b70SDaniel Drake 		return -EINVAL;
501b8b88b70SDaniel Drake 	}
502b8b88b70SDaniel Drake 
5032ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
504b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
5052ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
506b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
5073684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_SERDATA1, 0x1f, bclk_divider);
5083684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_ADCDIV1, 0x0f, lrck_divider >> 8);
5093684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_ADCDIV2, 0xff, lrck_divider & 0xff);
5103684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_DACDIV1, 0x0f, lrck_divider >> 8);
5113684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_DACDIV2, 0xff, lrck_divider & 0xff);
512b8b88b70SDaniel Drake 	return 0;
513b8b88b70SDaniel Drake }
514b8b88b70SDaniel Drake 
5158667d948SKuninori Morimoto static int es8316_mute(struct snd_soc_dai *dai, int mute, int direction)
516b8b88b70SDaniel Drake {
5172ff52976SKuninori Morimoto 	snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20,
518b8b88b70SDaniel Drake 			    mute ? 0x20 : 0);
519b8b88b70SDaniel Drake 	return 0;
520b8b88b70SDaniel Drake }
521b8b88b70SDaniel Drake 
522b8b88b70SDaniel Drake #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
523b8b88b70SDaniel Drake 			SNDRV_PCM_FMTBIT_S24_LE)
524b8b88b70SDaniel Drake 
525eb59d73cSArvind Yadav static const struct snd_soc_dai_ops es8316_ops = {
526b8b88b70SDaniel Drake 	.startup = es8316_pcm_startup,
527b8b88b70SDaniel Drake 	.hw_params = es8316_pcm_hw_params,
528b8b88b70SDaniel Drake 	.set_fmt = es8316_set_dai_fmt,
529b8b88b70SDaniel Drake 	.set_sysclk = es8316_set_dai_sysclk,
5308667d948SKuninori Morimoto 	.mute_stream = es8316_mute,
5318667d948SKuninori Morimoto 	.no_capture_mute = 1,
532b8b88b70SDaniel Drake };
533b8b88b70SDaniel Drake 
534b8b88b70SDaniel Drake static struct snd_soc_dai_driver es8316_dai = {
535b8b88b70SDaniel Drake 	.name = "ES8316 HiFi",
536b8b88b70SDaniel Drake 	.playback = {
537b8b88b70SDaniel Drake 		.stream_name = "Playback",
538b8b88b70SDaniel Drake 		.channels_min = 1,
539b8b88b70SDaniel Drake 		.channels_max = 2,
540b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
541b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
542b8b88b70SDaniel Drake 	},
543b8b88b70SDaniel Drake 	.capture = {
544b8b88b70SDaniel Drake 		.stream_name = "Capture",
545b8b88b70SDaniel Drake 		.channels_min = 1,
546b8b88b70SDaniel Drake 		.channels_max = 2,
547b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
548b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
549b8b88b70SDaniel Drake 	},
550b8b88b70SDaniel Drake 	.ops = &es8316_ops,
5514060064eSKuninori Morimoto 	.symmetric_rate = 1,
552b8b88b70SDaniel Drake };
553b8b88b70SDaniel Drake 
55482225766SHans de Goede static void es8316_enable_micbias_for_mic_gnd_short_detect(
55582225766SHans de Goede 	struct snd_soc_component *component)
55682225766SHans de Goede {
55782225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
55882225766SHans de Goede 
55982225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
56082225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias");
56182225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power");
56282225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias");
56382225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
56482225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
56582225766SHans de Goede 
56682225766SHans de Goede 	msleep(20);
56782225766SHans de Goede }
56882225766SHans de Goede 
56982225766SHans de Goede static void es8316_disable_micbias_for_mic_gnd_short_detect(
57082225766SHans de Goede 	struct snd_soc_component *component)
57182225766SHans de Goede {
57282225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
57382225766SHans de Goede 
57482225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
57582225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias");
57682225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power");
57782225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Bias");
57882225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
57982225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
58082225766SHans de Goede }
58182225766SHans de Goede 
58282225766SHans de Goede static irqreturn_t es8316_irq(int irq, void *data)
58382225766SHans de Goede {
58482225766SHans de Goede 	struct es8316_priv *es8316 = data;
58582225766SHans de Goede 	struct snd_soc_component *comp = es8316->component;
58682225766SHans de Goede 	unsigned int flags;
58782225766SHans de Goede 
58882225766SHans de Goede 	mutex_lock(&es8316->lock);
58982225766SHans de Goede 
59082225766SHans de Goede 	regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
59182225766SHans de Goede 	if (flags == 0x00)
59282225766SHans de Goede 		goto out; /* Powered-down / reset */
59382225766SHans de Goede 
59482225766SHans de Goede 	/* Catch spurious IRQ before set_jack is called */
59582225766SHans de Goede 	if (!es8316->jack)
59682225766SHans de Goede 		goto out;
59782225766SHans de Goede 
5980bbcedd6SPaul Cercueil 	if (es8316->jd_inverted)
5990bbcedd6SPaul Cercueil 		flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
6000bbcedd6SPaul Cercueil 
60182225766SHans de Goede 	dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
60282225766SHans de Goede 	if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
60382225766SHans de Goede 		/* Jack removed, or spurious IRQ? */
60482225766SHans de Goede 		if (es8316->jack->status & SND_JACK_MICROPHONE)
60582225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
60682225766SHans de Goede 
60782225766SHans de Goede 		if (es8316->jack->status & SND_JACK_HEADPHONE) {
60882225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0,
60982225766SHans de Goede 					    SND_JACK_HEADSET | SND_JACK_BTN_0);
61082225766SHans de Goede 			dev_dbg(comp->dev, "jack unplugged\n");
61182225766SHans de Goede 		}
61282225766SHans de Goede 	} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
61382225766SHans de Goede 		/* Jack inserted, determine type */
61482225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(comp);
61582225766SHans de Goede 		regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
6160bbcedd6SPaul Cercueil 		if (es8316->jd_inverted)
6170bbcedd6SPaul Cercueil 			flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
61882225766SHans de Goede 		dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
61982225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
62082225766SHans de Goede 			/* Jack unplugged underneath us */
62182225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
62282225766SHans de Goede 		} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
62382225766SHans de Goede 			/* Open, headset */
62482225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
62582225766SHans de Goede 					    SND_JACK_HEADSET,
62682225766SHans de Goede 					    SND_JACK_HEADSET);
62782225766SHans de Goede 			/* Keep mic-gnd-short detection on for button press */
62882225766SHans de Goede 		} else {
62982225766SHans de Goede 			/* Shorted, headphones */
63082225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
63182225766SHans de Goede 					    SND_JACK_HEADPHONE,
63282225766SHans de Goede 					    SND_JACK_HEADSET);
63382225766SHans de Goede 			/* No longer need mic-gnd-short detection */
63482225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
63582225766SHans de Goede 		}
63682225766SHans de Goede 	} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
63782225766SHans de Goede 		/* Interrupt while jack inserted, report button state */
63882225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
63982225766SHans de Goede 			/* Open, button release */
64082225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
64182225766SHans de Goede 		} else {
64282225766SHans de Goede 			/* Short, button press */
64382225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
64482225766SHans de Goede 					    SND_JACK_BTN_0,
64582225766SHans de Goede 					    SND_JACK_BTN_0);
64682225766SHans de Goede 		}
64782225766SHans de Goede 	}
64882225766SHans de Goede 
64982225766SHans de Goede out:
65082225766SHans de Goede 	mutex_unlock(&es8316->lock);
65182225766SHans de Goede 	return IRQ_HANDLED;
65282225766SHans de Goede }
65382225766SHans de Goede 
65482225766SHans de Goede static void es8316_enable_jack_detect(struct snd_soc_component *component,
65582225766SHans de Goede 				      struct snd_soc_jack *jack)
65682225766SHans de Goede {
65782225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
65882225766SHans de Goede 
6590bbcedd6SPaul Cercueil 	/*
6600bbcedd6SPaul Cercueil 	 * Init es8316->jd_inverted here and not in the probe, as we cannot
6610bbcedd6SPaul Cercueil 	 * guarantee that the bytchr-es8316 driver, which might set this
6620bbcedd6SPaul Cercueil 	 * property, will probe before us.
6630bbcedd6SPaul Cercueil 	 */
6640bbcedd6SPaul Cercueil 	es8316->jd_inverted = device_property_read_bool(component->dev,
6650bbcedd6SPaul Cercueil 							"everest,jack-detect-inverted");
6660bbcedd6SPaul Cercueil 
66782225766SHans de Goede 	mutex_lock(&es8316->lock);
66882225766SHans de Goede 
66982225766SHans de Goede 	es8316->jack = jack;
67082225766SHans de Goede 
67182225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE)
67282225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(component);
67382225766SHans de Goede 
67482225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
67582225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT,
67682225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT);
67782225766SHans de Goede 
67882225766SHans de Goede 	mutex_unlock(&es8316->lock);
67982225766SHans de Goede 
68082225766SHans de Goede 	/* Enable irq and sync initial jack state */
68182225766SHans de Goede 	enable_irq(es8316->irq);
68282225766SHans de Goede 	es8316_irq(es8316->irq, es8316);
68382225766SHans de Goede }
68482225766SHans de Goede 
68582225766SHans de Goede static void es8316_disable_jack_detect(struct snd_soc_component *component)
68682225766SHans de Goede {
68782225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
68882225766SHans de Goede 
689f2973a1dSHans de Goede 	if (!es8316->jack)
690f2973a1dSHans de Goede 		return; /* Already disabled (or never enabled) */
691f2973a1dSHans de Goede 
69282225766SHans de Goede 	disable_irq(es8316->irq);
69382225766SHans de Goede 
69482225766SHans de Goede 	mutex_lock(&es8316->lock);
69582225766SHans de Goede 
69682225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
69782225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT, 0);
69882225766SHans de Goede 
69982225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE) {
70082225766SHans de Goede 		es8316_disable_micbias_for_mic_gnd_short_detect(component);
70182225766SHans de Goede 		snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
70282225766SHans de Goede 	}
70382225766SHans de Goede 
70482225766SHans de Goede 	es8316->jack = NULL;
70582225766SHans de Goede 
70682225766SHans de Goede 	mutex_unlock(&es8316->lock);
70782225766SHans de Goede }
70882225766SHans de Goede 
70982225766SHans de Goede static int es8316_set_jack(struct snd_soc_component *component,
71082225766SHans de Goede 			   struct snd_soc_jack *jack, void *data)
71182225766SHans de Goede {
71282225766SHans de Goede 	if (jack)
71382225766SHans de Goede 		es8316_enable_jack_detect(component, jack);
71482225766SHans de Goede 	else
71582225766SHans de Goede 		es8316_disable_jack_detect(component);
71682225766SHans de Goede 
71782225766SHans de Goede 	return 0;
71882225766SHans de Goede }
71982225766SHans de Goede 
7202ff52976SKuninori Morimoto static int es8316_probe(struct snd_soc_component *component)
721b8b88b70SDaniel Drake {
72282225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7236dd567dcSKatsuhiro Suzuki 	int ret;
72482225766SHans de Goede 
72582225766SHans de Goede 	es8316->component = component;
72682225766SHans de Goede 
7270db0c62cSKatsuhiro Suzuki 	es8316->mclk = devm_clk_get_optional(component->dev, "mclk");
7286dd567dcSKatsuhiro Suzuki 	if (IS_ERR(es8316->mclk)) {
7290db0c62cSKatsuhiro Suzuki 		dev_err(component->dev, "unable to get mclk\n");
7300db0c62cSKatsuhiro Suzuki 		return PTR_ERR(es8316->mclk);
7316dd567dcSKatsuhiro Suzuki 	}
7320db0c62cSKatsuhiro Suzuki 	if (!es8316->mclk)
7330db0c62cSKatsuhiro Suzuki 		dev_warn(component->dev, "assuming static mclk\n");
7346dd567dcSKatsuhiro Suzuki 
7356dd567dcSKatsuhiro Suzuki 	ret = clk_prepare_enable(es8316->mclk);
7366dd567dcSKatsuhiro Suzuki 	if (ret) {
7370db0c62cSKatsuhiro Suzuki 		dev_err(component->dev, "unable to enable mclk\n");
7386dd567dcSKatsuhiro Suzuki 		return ret;
7396dd567dcSKatsuhiro Suzuki 	}
7406dd567dcSKatsuhiro Suzuki 
741b8b88b70SDaniel Drake 	/* Reset codec and enable current state machine */
7422ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
743b8b88b70SDaniel Drake 	usleep_range(5000, 5500);
7442ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, ES8316_RESET_CSM_ON);
745b8b88b70SDaniel Drake 	msleep(30);
746b8b88b70SDaniel Drake 
747b8b88b70SDaniel Drake 	/*
748b8b88b70SDaniel Drake 	 * Documentation is unclear, but this value from the vendor driver is
749b8b88b70SDaniel Drake 	 * needed otherwise audio output is silent.
750b8b88b70SDaniel Drake 	 */
7512ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_SYS_VMIDSEL, 0xff);
752b8b88b70SDaniel Drake 
753b8b88b70SDaniel Drake 	/*
754b8b88b70SDaniel Drake 	 * Documentation for this register is unclear and incomplete,
755b8b88b70SDaniel Drake 	 * but here is a vendor-provided value that improves volume
756b8b88b70SDaniel Drake 	 * and quality for Intel CHT platforms.
757b8b88b70SDaniel Drake 	 */
7582ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
759b8b88b70SDaniel Drake 
760b8b88b70SDaniel Drake 	return 0;
761b8b88b70SDaniel Drake }
762b8b88b70SDaniel Drake 
7636dd567dcSKatsuhiro Suzuki static void es8316_remove(struct snd_soc_component *component)
7646dd567dcSKatsuhiro Suzuki {
7656dd567dcSKatsuhiro Suzuki 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7666dd567dcSKatsuhiro Suzuki 
7676dd567dcSKatsuhiro Suzuki 	clk_disable_unprepare(es8316->mclk);
7686dd567dcSKatsuhiro Suzuki }
7696dd567dcSKatsuhiro Suzuki 
7704bac47a7SZhu Ning static int es8316_resume(struct snd_soc_component *component)
7714bac47a7SZhu Ning {
7724bac47a7SZhu Ning 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7734bac47a7SZhu Ning 
7744bac47a7SZhu Ning 	regcache_cache_only(es8316->regmap, false);
7754bac47a7SZhu Ning 	regcache_sync(es8316->regmap);
7764bac47a7SZhu Ning 
7774bac47a7SZhu Ning 	return 0;
7784bac47a7SZhu Ning }
7794bac47a7SZhu Ning 
7804bac47a7SZhu Ning static int es8316_suspend(struct snd_soc_component *component)
7814bac47a7SZhu Ning {
7824bac47a7SZhu Ning 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7834bac47a7SZhu Ning 
7844bac47a7SZhu Ning 	regcache_cache_only(es8316->regmap, true);
7854bac47a7SZhu Ning 	regcache_mark_dirty(es8316->regmap);
7864bac47a7SZhu Ning 
7874bac47a7SZhu Ning 	return 0;
7884bac47a7SZhu Ning }
7894bac47a7SZhu Ning 
7902ff52976SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_es8316 = {
791b8b88b70SDaniel Drake 	.probe			= es8316_probe,
7926dd567dcSKatsuhiro Suzuki 	.remove			= es8316_remove,
7934bac47a7SZhu Ning 	.resume			= es8316_resume,
7944bac47a7SZhu Ning 	.suspend		= es8316_suspend,
79582225766SHans de Goede 	.set_jack		= es8316_set_jack,
796b8b88b70SDaniel Drake 	.controls		= es8316_snd_controls,
797b8b88b70SDaniel Drake 	.num_controls		= ARRAY_SIZE(es8316_snd_controls),
798b8b88b70SDaniel Drake 	.dapm_widgets		= es8316_dapm_widgets,
799b8b88b70SDaniel Drake 	.num_dapm_widgets	= ARRAY_SIZE(es8316_dapm_widgets),
800b8b88b70SDaniel Drake 	.dapm_routes		= es8316_dapm_routes,
801b8b88b70SDaniel Drake 	.num_dapm_routes	= ARRAY_SIZE(es8316_dapm_routes),
8022ff52976SKuninori Morimoto 	.use_pmdown_time	= 1,
8032ff52976SKuninori Morimoto 	.endianness		= 1,
804b8b88b70SDaniel Drake };
805b8b88b70SDaniel Drake 
80682225766SHans de Goede static const struct regmap_range es8316_volatile_ranges[] = {
80782225766SHans de Goede 	regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG),
80882225766SHans de Goede };
80982225766SHans de Goede 
81082225766SHans de Goede static const struct regmap_access_table es8316_volatile_table = {
81182225766SHans de Goede 	.yes_ranges	= es8316_volatile_ranges,
81282225766SHans de Goede 	.n_yes_ranges	= ARRAY_SIZE(es8316_volatile_ranges),
81382225766SHans de Goede };
81482225766SHans de Goede 
815b8b88b70SDaniel Drake static const struct regmap_config es8316_regmap = {
816b8b88b70SDaniel Drake 	.reg_bits = 8,
817b8b88b70SDaniel Drake 	.val_bits = 8,
8186de0b029SPierre-Louis Bossart 	.use_single_read = true,
8196de0b029SPierre-Louis Bossart 	.use_single_write = true,
820b8b88b70SDaniel Drake 	.max_register = 0x53,
82182225766SHans de Goede 	.volatile_table	= &es8316_volatile_table,
822b8b88b70SDaniel Drake 	.cache_type = REGCACHE_RBTREE,
823b8b88b70SDaniel Drake };
824b8b88b70SDaniel Drake 
825a327bdc6SStephen Kitt static int es8316_i2c_probe(struct i2c_client *i2c_client)
826b8b88b70SDaniel Drake {
82782225766SHans de Goede 	struct device *dev = &i2c_client->dev;
828b8b88b70SDaniel Drake 	struct es8316_priv *es8316;
82982225766SHans de Goede 	int ret;
830b8b88b70SDaniel Drake 
831b8b88b70SDaniel Drake 	es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
832b8b88b70SDaniel Drake 			      GFP_KERNEL);
833b8b88b70SDaniel Drake 	if (es8316 == NULL)
834b8b88b70SDaniel Drake 		return -ENOMEM;
835b8b88b70SDaniel Drake 
836b8b88b70SDaniel Drake 	i2c_set_clientdata(i2c_client, es8316);
837b8b88b70SDaniel Drake 
83882225766SHans de Goede 	es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
83982225766SHans de Goede 	if (IS_ERR(es8316->regmap))
84082225766SHans de Goede 		return PTR_ERR(es8316->regmap);
84182225766SHans de Goede 
84282225766SHans de Goede 	es8316->irq = i2c_client->irq;
84382225766SHans de Goede 	mutex_init(&es8316->lock);
84482225766SHans de Goede 
845*39db65a0SCristian Ciocaltea 	if (es8316->irq > 0) {
84682225766SHans de Goede 		ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq,
8471cf2aa66SHans de Goede 						IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
84882225766SHans de Goede 						"es8316", es8316);
8491cf2aa66SHans de Goede 		if (ret) {
85082225766SHans de Goede 			dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret);
85182225766SHans de Goede 			es8316->irq = -ENXIO;
85282225766SHans de Goede 		}
853*39db65a0SCristian Ciocaltea 	}
854b8b88b70SDaniel Drake 
8552ff52976SKuninori Morimoto 	return devm_snd_soc_register_component(&i2c_client->dev,
8562ff52976SKuninori Morimoto 				      &soc_component_dev_es8316,
857b8b88b70SDaniel Drake 				      &es8316_dai, 1);
858b8b88b70SDaniel Drake }
859b8b88b70SDaniel Drake 
860b8b88b70SDaniel Drake static const struct i2c_device_id es8316_i2c_id[] = {
861b8b88b70SDaniel Drake 	{"es8316", 0 },
862b8b88b70SDaniel Drake 	{}
863b8b88b70SDaniel Drake };
864b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
865b8b88b70SDaniel Drake 
86675333af4SKrzysztof Kozlowski #ifdef CONFIG_OF
867b8b88b70SDaniel Drake static const struct of_device_id es8316_of_match[] = {
868b8b88b70SDaniel Drake 	{ .compatible = "everest,es8316", },
869b8b88b70SDaniel Drake 	{},
870b8b88b70SDaniel Drake };
871b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(of, es8316_of_match);
87275333af4SKrzysztof Kozlowski #endif
873b8b88b70SDaniel Drake 
87407ac6709SPierre-Louis Bossart #ifdef CONFIG_ACPI
875b8b88b70SDaniel Drake static const struct acpi_device_id es8316_acpi_match[] = {
876b8b88b70SDaniel Drake 	{"ESSX8316", 0},
877986c5b0aSPierre-Louis Bossart 	{"ESSX8336", 0},
878b8b88b70SDaniel Drake 	{},
879b8b88b70SDaniel Drake };
880b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
88107ac6709SPierre-Louis Bossart #endif
882b8b88b70SDaniel Drake 
883b8b88b70SDaniel Drake static struct i2c_driver es8316_i2c_driver = {
884b8b88b70SDaniel Drake 	.driver = {
885b8b88b70SDaniel Drake 		.name			= "es8316",
886b8b88b70SDaniel Drake 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
887b8b88b70SDaniel Drake 		.of_match_table		= of_match_ptr(es8316_of_match),
888b8b88b70SDaniel Drake 	},
889a327bdc6SStephen Kitt 	.probe_new	= es8316_i2c_probe,
890b8b88b70SDaniel Drake 	.id_table	= es8316_i2c_id,
891b8b88b70SDaniel Drake };
892b8b88b70SDaniel Drake module_i2c_driver(es8316_i2c_driver);
893b8b88b70SDaniel Drake 
894b8b88b70SDaniel Drake MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
895b8b88b70SDaniel Drake MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
896b8b88b70SDaniel Drake MODULE_LICENSE("GPL v2");
897