xref: /openbmc/linux/sound/soc/codecs/es8316.c (revision d20d35d1)
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 ARRAY_SIZE(supported_mclk_lrck_ratios)
31b8b88b70SDaniel Drake static const unsigned int supported_mclk_lrck_ratios[] = {
32b8b88b70SDaniel Drake 	256, 384, 400, 500, 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);
556f073429SCristian Ciocaltea 
566f073429SCristian Ciocaltea static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(alc_target_tlv,
576f073429SCristian Ciocaltea 	0, 10, TLV_DB_SCALE_ITEM(-1650, 150, 0),
586f073429SCristian Ciocaltea 	11, 11, TLV_DB_SCALE_ITEM(-150, 0, 0),
596f073429SCristian Ciocaltea );
606f073429SCristian Ciocaltea 
61f972d02fSKatsuhiro Suzuki static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
62f972d02fSKatsuhiro Suzuki 	0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
63f972d02fSKatsuhiro Suzuki 	8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
64f972d02fSKatsuhiro Suzuki );
65b8b88b70SDaniel Drake 
66b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
67b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
68b8b88b70SDaniel Drake 	1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
69b8b88b70SDaniel Drake 	2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
70b8b88b70SDaniel Drake 	3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
71bb18c678SHans de Goede 	4, 7, TLV_DB_SCALE_ITEM(700, 300, 0),
72bb18c678SHans de Goede 	8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0),
73b8b88b70SDaniel Drake );
74b8b88b70SDaniel Drake 
75b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
76b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
77b8b88b70SDaniel Drake 	1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
78b8b88b70SDaniel Drake );
79b8b88b70SDaniel Drake 
80b8b88b70SDaniel Drake static const char * const ng_type_txt[] =
81b8b88b70SDaniel Drake 	{ "Constant PGA Gain", "Mute ADC Output" };
82b8b88b70SDaniel Drake static const struct soc_enum ng_type =
83b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt);
84b8b88b70SDaniel Drake 
85b8b88b70SDaniel Drake static const char * const adcpol_txt[] = { "Normal", "Invert" };
86b8b88b70SDaniel Drake static const struct soc_enum adcpol =
87b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt);
88b8b88b70SDaniel Drake static const char *const dacpol_txt[] =
89b8b88b70SDaniel Drake 	{ "Normal", "R Invert", "L Invert", "L + R Invert" };
90b8b88b70SDaniel Drake static const struct soc_enum dacpol =
91b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt);
92b8b88b70SDaniel Drake 
93b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_snd_controls[] = {
94b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
95b8b88b70SDaniel Drake 		       4, 0, 3, 1, hpout_vol_tlv),
96b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
97f6e77921SKatsuhiro Suzuki 		       4, 0, 11, 0, hpmixer_gain_tlv),
98b8b88b70SDaniel Drake 
99b8b88b70SDaniel Drake 	SOC_ENUM("Playback Polarity", dacpol),
100b8b88b70SDaniel Drake 	SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
101b8b88b70SDaniel Drake 			 ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv),
102b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
103b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
104b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
105b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
106b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
10724b53f17SHans de Goede 	SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0),
108b8b88b70SDaniel Drake 
109b8b88b70SDaniel Drake 	SOC_ENUM("Capture Polarity", adcpol),
110b8b88b70SDaniel Drake 	SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
111b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME,
112b8b88b70SDaniel Drake 		       0, 0xc0, 1, adc_vol_tlv),
113b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN,
114b8b88b70SDaniel Drake 		       4, 10, 0, adc_pga_gain_tlv),
115b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0),
116b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0),
117b8b88b70SDaniel Drake 
118b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0),
119b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0,
120b8b88b70SDaniel Drake 		       alc_max_gain_tlv),
121b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0,
122b8b88b70SDaniel Drake 		       alc_min_gain_tlv),
1236f073429SCristian Ciocaltea 	SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 11, 0,
124b8b88b70SDaniel Drake 		       alc_target_tlv),
125b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0),
126b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0),
127b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0),
128b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG,
129b8b88b70SDaniel Drake 		   5, 1, 0),
130b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG,
131b8b88b70SDaniel Drake 		   0, 31, 0),
132b8b88b70SDaniel Drake 	SOC_ENUM("ALC Capture Noise Gate Type", ng_type),
133b8b88b70SDaniel Drake };
134b8b88b70SDaniel Drake 
135b8b88b70SDaniel Drake /* Analog Input Mux */
136b8b88b70SDaniel Drake static const char * const es8316_analog_in_txt[] = {
137b8b88b70SDaniel Drake 		"lin1-rin1",
138b8b88b70SDaniel Drake 		"lin2-rin2",
139b8b88b70SDaniel Drake 		"lin1-rin1 with 20db Boost",
140b8b88b70SDaniel Drake 		"lin2-rin2 with 20db Boost"
141b8b88b70SDaniel Drake };
142b8b88b70SDaniel Drake static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 };
143b8b88b70SDaniel Drake static const struct soc_enum es8316_analog_input_enum =
144b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3,
145b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_analog_in_txt),
146b8b88b70SDaniel Drake 			      es8316_analog_in_txt,
147b8b88b70SDaniel Drake 			      es8316_analog_in_values);
148b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_analog_in_mux_controls =
149b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_analog_input_enum);
150b8b88b70SDaniel Drake 
151b8b88b70SDaniel Drake static const char * const es8316_dmic_txt[] = {
152b8b88b70SDaniel Drake 		"dmic disable",
153b8b88b70SDaniel Drake 		"dmic data at high level",
154b8b88b70SDaniel Drake 		"dmic data at low level",
155b8b88b70SDaniel Drake };
156*d20d35d1SEdgar static const unsigned int es8316_dmic_values[] = { 0, 2, 3 };
157b8b88b70SDaniel Drake static const struct soc_enum es8316_dmic_src_enum =
158b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
159b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_dmic_txt),
160b8b88b70SDaniel Drake 			      es8316_dmic_txt,
161b8b88b70SDaniel Drake 			      es8316_dmic_values);
162b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dmic_src_controls =
163b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dmic_src_enum);
164b8b88b70SDaniel Drake 
165b8b88b70SDaniel Drake /* hp mixer mux */
166b8b88b70SDaniel Drake static const char * const es8316_hpmux_texts[] = {
167b8b88b70SDaniel Drake 	"lin1-rin1",
168b8b88b70SDaniel Drake 	"lin2-rin2",
169b8b88b70SDaniel Drake 	"lin-rin with Boost",
170b8b88b70SDaniel Drake 	"lin-rin with Boost and PGA"
171b8b88b70SDaniel Drake };
172b8b88b70SDaniel Drake 
173b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
174b8b88b70SDaniel Drake 	4, es8316_hpmux_texts);
175b8b88b70SDaniel Drake 
176b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_left_hpmux_controls =
177b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum);
178b8b88b70SDaniel Drake 
179b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL,
180b8b88b70SDaniel Drake 	0, es8316_hpmux_texts);
181b8b88b70SDaniel Drake 
182b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_right_hpmux_controls =
183b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum);
184b8b88b70SDaniel Drake 
185b8b88b70SDaniel Drake /* headphone Output Mixer */
186b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_left_mix[] = {
187b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0),
188b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
189b8b88b70SDaniel Drake };
190b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_right_mix[] = {
191b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0),
192b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
193b8b88b70SDaniel Drake };
194b8b88b70SDaniel Drake 
195b8b88b70SDaniel Drake /* DAC data source mux */
196b8b88b70SDaniel Drake static const char * const es8316_dacsrc_texts[] = {
197b8b88b70SDaniel Drake 	"LDATA TO LDAC, RDATA TO RDAC",
198b8b88b70SDaniel Drake 	"LDATA TO LDAC, LDATA TO RDAC",
199b8b88b70SDaniel Drake 	"RDATA TO LDAC, RDATA TO RDAC",
200b8b88b70SDaniel Drake 	"RDATA TO LDAC, LDATA TO RDAC",
201b8b88b70SDaniel Drake };
202b8b88b70SDaniel Drake 
203b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
204b8b88b70SDaniel Drake 	6, es8316_dacsrc_texts);
205b8b88b70SDaniel Drake 
206b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dacsrc_mux_controls =
207b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum);
208b8b88b70SDaniel Drake 
209b8b88b70SDaniel Drake static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = {
210b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0),
211b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0),
212b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0),
213b8b88b70SDaniel Drake 
214b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("DMIC"),
215b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC1"),
216b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC2"),
217b8b88b70SDaniel Drake 
218b8b88b70SDaniel Drake 	/* Input Mux */
219b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
220b8b88b70SDaniel Drake 			 &es8316_analog_in_mux_controls),
221b8b88b70SDaniel Drake 
222b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0),
223b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0),
224b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0),
225b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL,
226b8b88b70SDaniel Drake 			 7, 1, NULL, 0),
227b8b88b70SDaniel Drake 	SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1),
228b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0,
229b8b88b70SDaniel Drake 			 &es8316_dmic_src_controls),
230b8b88b70SDaniel Drake 
231b8b88b70SDaniel Drake 	/* Digital Interface */
232b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture",  1,
233b8b88b70SDaniel Drake 			     ES8316_SERDATA_ADC, 6, 1),
234b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0,
235b8b88b70SDaniel Drake 			    SND_SOC_NOPM, 0, 0),
236b8b88b70SDaniel Drake 
237b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
238b8b88b70SDaniel Drake 			 &es8316_dacsrc_mux_controls),
239b8b88b70SDaniel Drake 
240b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
241b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
242b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
243b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
244b8b88b70SDaniel Drake 
245b8b88b70SDaniel Drake 	/* Headphone Output Side */
246b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
247b8b88b70SDaniel Drake 			 &es8316_left_hpmux_controls),
248b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
249b8b88b70SDaniel Drake 			 &es8316_right_hpmux_controls),
250b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN,
251b8b88b70SDaniel Drake 			   5, 1, &es8316_out_left_mix[0],
252b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_left_mix)),
253b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN,
254b8b88b70SDaniel Drake 			   1, 1, &es8316_out_right_mix[0],
255b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_right_mix)),
256b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN,
257b8b88b70SDaniel Drake 			 4, 1, NULL, 0),
258b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN,
259b8b88b70SDaniel Drake 			 0, 1, NULL, 0),
260b8b88b70SDaniel Drake 
261b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN,
262b8b88b70SDaniel Drake 			     6, 0, NULL, 0),
263b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN,
264b8b88b70SDaniel Drake 			     2, 0, NULL, 0),
265b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2,
266b8b88b70SDaniel Drake 			    5, 1, NULL, 0),
267b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW,
268b8b88b70SDaniel Drake 			    4, 0, NULL, 0),
269b8b88b70SDaniel Drake 
270b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN,
271b8b88b70SDaniel Drake 			     5, 0, NULL, 0),
272b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN,
273b8b88b70SDaniel Drake 			     1, 0, NULL, 0),
274b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0),
275b8b88b70SDaniel Drake 
276b8b88b70SDaniel Drake 	/* pdn_Lical and pdn_Rical bits are documented as Reserved, but must
277b8b88b70SDaniel Drake 	 * be explicitly unset in order to enable HP output
278b8b88b70SDaniel Drake 	 */
279b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL,
280b8b88b70SDaniel Drake 			    7, 1, NULL, 0),
281b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL,
282b8b88b70SDaniel Drake 			    3, 1, NULL, 0),
283b8b88b70SDaniel Drake 
284b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOL"),
285b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOR"),
286b8b88b70SDaniel Drake };
287b8b88b70SDaniel Drake 
288b8b88b70SDaniel Drake static const struct snd_soc_dapm_route es8316_dapm_routes[] = {
289b8b88b70SDaniel Drake 	/* Recording */
290b8b88b70SDaniel Drake 	{"MIC1", NULL, "Mic Bias"},
291b8b88b70SDaniel Drake 	{"MIC2", NULL, "Mic Bias"},
292b8b88b70SDaniel Drake 	{"MIC1", NULL, "Bias"},
293b8b88b70SDaniel Drake 	{"MIC2", NULL, "Bias"},
294b8b88b70SDaniel Drake 	{"MIC1", NULL, "Analog power"},
295b8b88b70SDaniel Drake 	{"MIC2", NULL, "Analog power"},
296b8b88b70SDaniel Drake 
297b8b88b70SDaniel Drake 	{"Differential Mux", "lin1-rin1", "MIC1"},
298b8b88b70SDaniel Drake 	{"Differential Mux", "lin2-rin2", "MIC2"},
299b8b88b70SDaniel Drake 	{"Line input PGA", NULL, "Differential Mux"},
300b8b88b70SDaniel Drake 
301b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Clock"},
302b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Vref"},
303b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC bias"},
304b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "Line input PGA"},
305b8b88b70SDaniel Drake 
306b8b88b70SDaniel Drake 	/* It's not clear why, but to avoid recording only silence,
307b8b88b70SDaniel Drake 	 * the DAC clock must be running for the ADC to work.
308b8b88b70SDaniel Drake 	 */
309b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "DAC Clock"},
310b8b88b70SDaniel Drake 
311b8b88b70SDaniel Drake 	{"Digital Mic Mux", "dmic disable", "Mono ADC"},
312b8b88b70SDaniel Drake 
313b8b88b70SDaniel Drake 	{"I2S OUT", NULL, "Digital Mic Mux"},
314b8b88b70SDaniel Drake 
315b8b88b70SDaniel Drake 	/* Playback */
316b8b88b70SDaniel Drake 	{"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
317b8b88b70SDaniel Drake 
318b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Clock"},
319b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Clock"},
320b8b88b70SDaniel Drake 
321b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Vref"},
322b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Vref"},
323b8b88b70SDaniel Drake 
324b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Source Mux"},
325b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Source Mux"},
326b8b88b70SDaniel Drake 
327b8b88b70SDaniel Drake 	{"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
328b8b88b70SDaniel Drake 	{"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
329b8b88b70SDaniel Drake 
330b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"},
331b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
332b8b88b70SDaniel Drake 
333b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"},
334b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
335b8b88b70SDaniel Drake 
336b8b88b70SDaniel Drake 	{"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"},
337b8b88b70SDaniel Drake 	{"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"},
338b8b88b70SDaniel Drake 
339b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"},
340b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"},
341b8b88b70SDaniel Drake 
342b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"},
343b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"},
344b8b88b70SDaniel Drake 
345b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
346b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
347b8b88b70SDaniel Drake 
348b8b88b70SDaniel Drake 	{"Left Headphone Driver", NULL, "Left Headphone Charge Pump"},
349b8b88b70SDaniel Drake 	{"Right Headphone Driver", NULL, "Right Headphone Charge Pump"},
350b8b88b70SDaniel Drake 
351b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone Driver"},
352b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone Driver"},
353b8b88b70SDaniel Drake 
354b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone ical"},
355b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone ical"},
356b8b88b70SDaniel Drake 
357b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Bias"},
358b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Analog power"},
359b8b88b70SDaniel Drake 	{"HPOL", NULL, "Headphone Out"},
360b8b88b70SDaniel Drake 	{"HPOR", NULL, "Headphone Out"},
361b8b88b70SDaniel Drake };
362b8b88b70SDaniel Drake 
es8316_set_dai_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)363b8b88b70SDaniel Drake static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
364b8b88b70SDaniel Drake 				 int clk_id, unsigned int freq, int dir)
365b8b88b70SDaniel Drake {
3662ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
3672ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
3686dd567dcSKatsuhiro Suzuki 	int i, ret;
369b8b88b70SDaniel Drake 	int count = 0;
370b8b88b70SDaniel Drake 
371b8b88b70SDaniel Drake 	es8316->sysclk = freq;
372ebe02a5bSKatsuhiro Suzuki 	es8316->sysclk_constraints.list = NULL;
373ebe02a5bSKatsuhiro Suzuki 	es8316->sysclk_constraints.count = 0;
374ebe02a5bSKatsuhiro Suzuki 
37560413129SCristian Ciocaltea 	if (freq == 0)
376b8b88b70SDaniel Drake 		return 0;
377b8b88b70SDaniel Drake 
3786dd567dcSKatsuhiro Suzuki 	ret = clk_set_rate(es8316->mclk, freq);
3796dd567dcSKatsuhiro Suzuki 	if (ret)
3806dd567dcSKatsuhiro Suzuki 		return ret;
381b8b88b70SDaniel Drake 
382b8b88b70SDaniel Drake 	/* Limit supported sample rates to ones that can be autodetected
383b8b88b70SDaniel Drake 	 * by the codec running in slave mode.
384b8b88b70SDaniel Drake 	 */
385b8b88b70SDaniel Drake 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
386b8b88b70SDaniel Drake 		const unsigned int ratio = supported_mclk_lrck_ratios[i];
387b8b88b70SDaniel Drake 
388b8b88b70SDaniel Drake 		if (freq % ratio == 0)
389b8b88b70SDaniel Drake 			es8316->allowed_rates[count++] = freq / ratio;
390b8b88b70SDaniel Drake 	}
391b8b88b70SDaniel Drake 
39260413129SCristian Ciocaltea 	if (count) {
393b8b88b70SDaniel Drake 		es8316->sysclk_constraints.list = es8316->allowed_rates;
394b8b88b70SDaniel Drake 		es8316->sysclk_constraints.count = count;
39560413129SCristian Ciocaltea 	}
396b8b88b70SDaniel Drake 
397b8b88b70SDaniel Drake 	return 0;
398b8b88b70SDaniel Drake }
399b8b88b70SDaniel Drake 
es8316_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)400b8b88b70SDaniel Drake static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai,
401b8b88b70SDaniel Drake 			      unsigned int fmt)
402b8b88b70SDaniel Drake {
4032ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
404b8b88b70SDaniel Drake 	u8 serdata1 = 0;
405b8b88b70SDaniel Drake 	u8 serdata2 = 0;
406b8b88b70SDaniel Drake 	u8 clksw;
407b8b88b70SDaniel Drake 	u8 mask;
408b8b88b70SDaniel Drake 
4093684020aSZhu Ning 	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBP_CFP)
4103684020aSZhu Ning 		serdata1 |= ES8316_SERDATA1_MASTER;
411b8b88b70SDaniel Drake 
412b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
4132ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports I2S format\n");
414b8b88b70SDaniel Drake 		return -EINVAL;
415b8b88b70SDaniel Drake 	}
416b8b88b70SDaniel Drake 
417b8b88b70SDaniel Drake 	/* Clock inversion */
418b8b88b70SDaniel Drake 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
419b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_NF:
420b8b88b70SDaniel Drake 		break;
421b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_IF:
422b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
423b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
424b8b88b70SDaniel Drake 		break;
425b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_NF:
426b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
427b8b88b70SDaniel Drake 		break;
428b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_IF:
429b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
430b8b88b70SDaniel Drake 		break;
431b8b88b70SDaniel Drake 	default:
432b8b88b70SDaniel Drake 		return -EINVAL;
433b8b88b70SDaniel Drake 	}
434b8b88b70SDaniel Drake 
435b8b88b70SDaniel Drake 	mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
4362ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA1, mask, serdata1);
437b8b88b70SDaniel Drake 
438b8b88b70SDaniel Drake 	mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
4392ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, mask, serdata2);
4402ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, mask, serdata2);
441b8b88b70SDaniel Drake 
442b8b88b70SDaniel Drake 	/* Enable BCLK and MCLK inputs in slave mode */
443b8b88b70SDaniel Drake 	clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
4442ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW, clksw, clksw);
445b8b88b70SDaniel Drake 
446b8b88b70SDaniel Drake 	return 0;
447b8b88b70SDaniel Drake }
448b8b88b70SDaniel Drake 
es8316_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)449b8b88b70SDaniel Drake static int es8316_pcm_startup(struct snd_pcm_substream *substream,
450b8b88b70SDaniel Drake 			      struct snd_soc_dai *dai)
451b8b88b70SDaniel Drake {
4522ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4532ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
454b8b88b70SDaniel Drake 
455ebe02a5bSKatsuhiro Suzuki 	if (es8316->sysclk_constraints.list)
456b8b88b70SDaniel Drake 		snd_pcm_hw_constraint_list(substream->runtime, 0,
457b8b88b70SDaniel Drake 					   SNDRV_PCM_HW_PARAM_RATE,
458b8b88b70SDaniel Drake 					   &es8316->sysclk_constraints);
459b8b88b70SDaniel Drake 
460b8b88b70SDaniel Drake 	return 0;
461b8b88b70SDaniel Drake }
462b8b88b70SDaniel Drake 
es8316_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)463b8b88b70SDaniel Drake static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
464b8b88b70SDaniel Drake 				struct snd_pcm_hw_params *params,
465b8b88b70SDaniel Drake 				struct snd_soc_dai *dai)
466b8b88b70SDaniel Drake {
4672ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4682ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
469b8b88b70SDaniel Drake 	u8 wordlen = 0;
4703684020aSZhu Ning 	u8 bclk_divider;
4713684020aSZhu Ning 	u16 lrck_divider;
472ebe02a5bSKatsuhiro Suzuki 	int i;
473b8b88b70SDaniel Drake 
474ebe02a5bSKatsuhiro Suzuki 	/* Validate supported sample rates that are autodetected from MCLK */
475ebe02a5bSKatsuhiro Suzuki 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
476ebe02a5bSKatsuhiro Suzuki 		const unsigned int ratio = supported_mclk_lrck_ratios[i];
477ebe02a5bSKatsuhiro Suzuki 
478ebe02a5bSKatsuhiro Suzuki 		if (es8316->sysclk % ratio != 0)
479ebe02a5bSKatsuhiro Suzuki 			continue;
480ebe02a5bSKatsuhiro Suzuki 		if (es8316->sysclk / ratio == params_rate(params))
481ebe02a5bSKatsuhiro Suzuki 			break;
482b8b88b70SDaniel Drake 	}
483ebe02a5bSKatsuhiro Suzuki 	if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
484ebe02a5bSKatsuhiro Suzuki 		return -EINVAL;
4853684020aSZhu Ning 	lrck_divider = es8316->sysclk / params_rate(params);
4863684020aSZhu Ning 	bclk_divider = lrck_divider / 4;
487b8b88b70SDaniel Drake 	switch (params_format(params)) {
488b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S16_LE:
489b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_16;
4903684020aSZhu Ning 		bclk_divider /= 16;
491b8b88b70SDaniel Drake 		break;
492b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S20_3LE:
493b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_20;
4943684020aSZhu Ning 		bclk_divider /= 20;
495b8b88b70SDaniel Drake 		break;
496b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S24_LE:
497b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S24_3LE:
4983684020aSZhu Ning 		wordlen = ES8316_SERDATA2_LEN_24;
499b8b88b70SDaniel Drake 		bclk_divider /= 24;
500b8b88b70SDaniel Drake 		break;
501b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S32_LE:
5023684020aSZhu Ning 		wordlen = ES8316_SERDATA2_LEN_32;
503b8b88b70SDaniel Drake 		bclk_divider /= 32;
504b8b88b70SDaniel Drake 		break;
505b8b88b70SDaniel Drake 	default:
506b8b88b70SDaniel Drake 		return -EINVAL;
507b8b88b70SDaniel Drake 	}
5082ff52976SKuninori Morimoto 
509b8b88b70SDaniel Drake 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
5102ff52976SKuninori Morimoto 			    ES8316_SERDATA2_LEN_MASK, wordlen);
511b8b88b70SDaniel Drake 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
5123684020aSZhu Ning 			    ES8316_SERDATA2_LEN_MASK, wordlen);
5133684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_SERDATA1, 0x1f, bclk_divider);
5143684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_ADCDIV1, 0x0f, lrck_divider >> 8);
5153684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_ADCDIV2, 0xff, lrck_divider & 0xff);
5163684020aSZhu Ning 	snd_soc_component_update_bits(component, ES8316_CLKMGR_DACDIV1, 0x0f, lrck_divider >> 8);
517b8b88b70SDaniel Drake 	snd_soc_component_update_bits(component, ES8316_CLKMGR_DACDIV2, 0xff, lrck_divider & 0xff);
518b8b88b70SDaniel Drake 	return 0;
519b8b88b70SDaniel Drake }
5208667d948SKuninori Morimoto 
es8316_mute(struct snd_soc_dai * dai,int mute,int direction)521b8b88b70SDaniel Drake static int es8316_mute(struct snd_soc_dai *dai, int mute, int direction)
5222ff52976SKuninori Morimoto {
523b8b88b70SDaniel Drake 	snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20,
524b8b88b70SDaniel Drake 			    mute ? 0x20 : 0);
525b8b88b70SDaniel Drake 	return 0;
526b8b88b70SDaniel Drake }
527b8b88b70SDaniel Drake 
528b8b88b70SDaniel Drake #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
529b8b88b70SDaniel Drake 			SNDRV_PCM_FMTBIT_S24_LE)
530eb59d73cSArvind Yadav 
531b8b88b70SDaniel Drake static const struct snd_soc_dai_ops es8316_ops = {
532b8b88b70SDaniel Drake 	.startup = es8316_pcm_startup,
533b8b88b70SDaniel Drake 	.hw_params = es8316_pcm_hw_params,
534b8b88b70SDaniel Drake 	.set_fmt = es8316_set_dai_fmt,
5358667d948SKuninori Morimoto 	.set_sysclk = es8316_set_dai_sysclk,
5368667d948SKuninori Morimoto 	.mute_stream = es8316_mute,
537b8b88b70SDaniel Drake 	.no_capture_mute = 1,
538b8b88b70SDaniel Drake };
539b8b88b70SDaniel Drake 
540b8b88b70SDaniel Drake static struct snd_soc_dai_driver es8316_dai = {
541b8b88b70SDaniel Drake 	.name = "ES8316 HiFi",
542b8b88b70SDaniel Drake 	.playback = {
543b8b88b70SDaniel Drake 		.stream_name = "Playback",
544b8b88b70SDaniel Drake 		.channels_min = 1,
545b8b88b70SDaniel Drake 		.channels_max = 2,
546b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
547b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
548b8b88b70SDaniel Drake 	},
549b8b88b70SDaniel Drake 	.capture = {
550b8b88b70SDaniel Drake 		.stream_name = "Capture",
551b8b88b70SDaniel Drake 		.channels_min = 1,
552b8b88b70SDaniel Drake 		.channels_max = 2,
553b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
554b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
555b8b88b70SDaniel Drake 	},
5564060064eSKuninori Morimoto 	.ops = &es8316_ops,
557b8b88b70SDaniel Drake 	.symmetric_rate = 1,
558b8b88b70SDaniel Drake };
55982225766SHans de Goede 
es8316_enable_micbias_for_mic_gnd_short_detect(struct snd_soc_component * component)56082225766SHans de Goede static void es8316_enable_micbias_for_mic_gnd_short_detect(
56182225766SHans de Goede 	struct snd_soc_component *component)
56282225766SHans de Goede {
56382225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
56482225766SHans de Goede 
56582225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
56682225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias");
56782225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power");
56882225766SHans de Goede 	snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias");
56982225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
57082225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
57182225766SHans de Goede 
57282225766SHans de Goede 	msleep(20);
57382225766SHans de Goede }
57482225766SHans de Goede 
es8316_disable_micbias_for_mic_gnd_short_detect(struct snd_soc_component * component)57582225766SHans de Goede static void es8316_disable_micbias_for_mic_gnd_short_detect(
57682225766SHans de Goede 	struct snd_soc_component *component)
57782225766SHans de Goede {
57882225766SHans de Goede 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
57982225766SHans de Goede 
58082225766SHans de Goede 	snd_soc_dapm_mutex_lock(dapm);
58182225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias");
58282225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power");
58382225766SHans de Goede 	snd_soc_dapm_disable_pin_unlocked(dapm, "Bias");
58482225766SHans de Goede 	snd_soc_dapm_sync_unlocked(dapm);
58582225766SHans de Goede 	snd_soc_dapm_mutex_unlock(dapm);
58682225766SHans de Goede }
58782225766SHans de Goede 
es8316_irq(int irq,void * data)58882225766SHans de Goede static irqreturn_t es8316_irq(int irq, void *data)
58982225766SHans de Goede {
59082225766SHans de Goede 	struct es8316_priv *es8316 = data;
59182225766SHans de Goede 	struct snd_soc_component *comp = es8316->component;
59282225766SHans de Goede 	unsigned int flags;
59382225766SHans de Goede 
59482225766SHans de Goede 	mutex_lock(&es8316->lock);
59582225766SHans de Goede 
59682225766SHans de Goede 	regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
59782225766SHans de Goede 	if (flags == 0x00)
59882225766SHans de Goede 		goto out; /* Powered-down / reset */
59982225766SHans de Goede 
60082225766SHans de Goede 	/* Catch spurious IRQ before set_jack is called */
60182225766SHans de Goede 	if (!es8316->jack)
60282225766SHans de Goede 		goto out;
6030bbcedd6SPaul Cercueil 
6040bbcedd6SPaul Cercueil 	if (es8316->jd_inverted)
6050bbcedd6SPaul Cercueil 		flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
60682225766SHans de Goede 
60782225766SHans de Goede 	dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
60882225766SHans de Goede 	if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
60982225766SHans de Goede 		/* Jack removed, or spurious IRQ? */
61082225766SHans de Goede 		if (es8316->jack->status & SND_JACK_MICROPHONE)
61182225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
61282225766SHans de Goede 
61382225766SHans de Goede 		if (es8316->jack->status & SND_JACK_HEADPHONE) {
61482225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0,
61582225766SHans de Goede 					    SND_JACK_HEADSET | SND_JACK_BTN_0);
61682225766SHans de Goede 			dev_dbg(comp->dev, "jack unplugged\n");
61782225766SHans de Goede 		}
61882225766SHans de Goede 	} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
61982225766SHans de Goede 		/* Jack inserted, determine type */
62082225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(comp);
6210bbcedd6SPaul Cercueil 		regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
6220bbcedd6SPaul Cercueil 		if (es8316->jd_inverted)
62382225766SHans de Goede 			flags ^= ES8316_GPIO_FLAG_HP_NOT_INSERTED;
62482225766SHans de Goede 		dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
62582225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
62682225766SHans de Goede 			/* Jack unplugged underneath us */
62782225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
62882225766SHans de Goede 		} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
62982225766SHans de Goede 			/* Open, headset */
63082225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
63182225766SHans de Goede 					    SND_JACK_HEADSET,
63282225766SHans de Goede 					    SND_JACK_HEADSET);
63382225766SHans de Goede 			/* Keep mic-gnd-short detection on for button press */
63482225766SHans de Goede 		} else {
63582225766SHans de Goede 			/* Shorted, headphones */
63682225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
63782225766SHans de Goede 					    SND_JACK_HEADPHONE,
63882225766SHans de Goede 					    SND_JACK_HEADSET);
63982225766SHans de Goede 			/* No longer need mic-gnd-short detection */
64082225766SHans de Goede 			es8316_disable_micbias_for_mic_gnd_short_detect(comp);
64182225766SHans de Goede 		}
64282225766SHans de Goede 	} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
64382225766SHans de Goede 		/* Interrupt while jack inserted, report button state */
64482225766SHans de Goede 		if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
64582225766SHans de Goede 			/* Open, button release */
64682225766SHans de Goede 			snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
64782225766SHans de Goede 		} else {
64882225766SHans de Goede 			/* Short, button press */
64982225766SHans de Goede 			snd_soc_jack_report(es8316->jack,
65082225766SHans de Goede 					    SND_JACK_BTN_0,
65182225766SHans de Goede 					    SND_JACK_BTN_0);
65282225766SHans de Goede 		}
65382225766SHans de Goede 	}
65482225766SHans de Goede 
65582225766SHans de Goede out:
65682225766SHans de Goede 	mutex_unlock(&es8316->lock);
65782225766SHans de Goede 	return IRQ_HANDLED;
65882225766SHans de Goede }
65982225766SHans de Goede 
es8316_enable_jack_detect(struct snd_soc_component * component,struct snd_soc_jack * jack)66082225766SHans de Goede static void es8316_enable_jack_detect(struct snd_soc_component *component,
66182225766SHans de Goede 				      struct snd_soc_jack *jack)
66282225766SHans de Goede {
66382225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
6640bbcedd6SPaul Cercueil 
6650bbcedd6SPaul Cercueil 	/*
6660bbcedd6SPaul Cercueil 	 * Init es8316->jd_inverted here and not in the probe, as we cannot
6670bbcedd6SPaul Cercueil 	 * guarantee that the bytchr-es8316 driver, which might set this
6680bbcedd6SPaul Cercueil 	 * property, will probe before us.
6690bbcedd6SPaul Cercueil 	 */
6700bbcedd6SPaul Cercueil 	es8316->jd_inverted = device_property_read_bool(component->dev,
6710bbcedd6SPaul Cercueil 							"everest,jack-detect-inverted");
67282225766SHans de Goede 
67382225766SHans de Goede 	mutex_lock(&es8316->lock);
67482225766SHans de Goede 
67582225766SHans de Goede 	es8316->jack = jack;
67682225766SHans de Goede 
67782225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE)
67882225766SHans de Goede 		es8316_enable_micbias_for_mic_gnd_short_detect(component);
67982225766SHans de Goede 
68082225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
68182225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT,
68282225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT);
68382225766SHans de Goede 
68482225766SHans de Goede 	mutex_unlock(&es8316->lock);
68582225766SHans de Goede 
68682225766SHans de Goede 	/* Enable irq and sync initial jack state */
68782225766SHans de Goede 	enable_irq(es8316->irq);
68882225766SHans de Goede 	es8316_irq(es8316->irq, es8316);
68982225766SHans de Goede }
69082225766SHans de Goede 
es8316_disable_jack_detect(struct snd_soc_component * component)69182225766SHans de Goede static void es8316_disable_jack_detect(struct snd_soc_component *component)
69282225766SHans de Goede {
69382225766SHans de Goede 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
694f2973a1dSHans de Goede 
695f2973a1dSHans de Goede 	if (!es8316->jack)
696f2973a1dSHans de Goede 		return; /* Already disabled (or never enabled) */
69782225766SHans de Goede 
69882225766SHans de Goede 	disable_irq(es8316->irq);
69982225766SHans de Goede 
70082225766SHans de Goede 	mutex_lock(&es8316->lock);
70182225766SHans de Goede 
70282225766SHans de Goede 	snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
70382225766SHans de Goede 				      ES8316_GPIO_ENABLE_INTERRUPT, 0);
70482225766SHans de Goede 
70582225766SHans de Goede 	if (es8316->jack->status & SND_JACK_MICROPHONE) {
70682225766SHans de Goede 		es8316_disable_micbias_for_mic_gnd_short_detect(component);
70782225766SHans de Goede 		snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
70882225766SHans de Goede 	}
70982225766SHans de Goede 
71082225766SHans de Goede 	es8316->jack = NULL;
71182225766SHans de Goede 
71282225766SHans de Goede 	mutex_unlock(&es8316->lock);
71382225766SHans de Goede }
71482225766SHans de Goede 
es8316_set_jack(struct snd_soc_component * component,struct snd_soc_jack * jack,void * data)71582225766SHans de Goede static int es8316_set_jack(struct snd_soc_component *component,
71682225766SHans de Goede 			   struct snd_soc_jack *jack, void *data)
71782225766SHans de Goede {
71882225766SHans de Goede 	if (jack)
71982225766SHans de Goede 		es8316_enable_jack_detect(component, jack);
72082225766SHans de Goede 	else
72182225766SHans de Goede 		es8316_disable_jack_detect(component);
72282225766SHans de Goede 
72382225766SHans de Goede 	return 0;
72482225766SHans de Goede }
7252ff52976SKuninori Morimoto 
es8316_probe(struct snd_soc_component * component)726b8b88b70SDaniel Drake static int es8316_probe(struct snd_soc_component *component)
72782225766SHans de Goede {
7286dd567dcSKatsuhiro Suzuki 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
72982225766SHans de Goede 	int ret;
73082225766SHans de Goede 
73182225766SHans de Goede 	es8316->component = component;
7320db0c62cSKatsuhiro Suzuki 
7336dd567dcSKatsuhiro Suzuki 	es8316->mclk = devm_clk_get_optional(component->dev, "mclk");
7340db0c62cSKatsuhiro Suzuki 	if (IS_ERR(es8316->mclk)) {
7350db0c62cSKatsuhiro Suzuki 		dev_err(component->dev, "unable to get mclk\n");
7366dd567dcSKatsuhiro Suzuki 		return PTR_ERR(es8316->mclk);
7370db0c62cSKatsuhiro Suzuki 	}
7380db0c62cSKatsuhiro Suzuki 	if (!es8316->mclk)
7396dd567dcSKatsuhiro Suzuki 		dev_warn(component->dev, "assuming static mclk\n");
7406dd567dcSKatsuhiro Suzuki 
7416dd567dcSKatsuhiro Suzuki 	ret = clk_prepare_enable(es8316->mclk);
7420db0c62cSKatsuhiro Suzuki 	if (ret) {
7436dd567dcSKatsuhiro Suzuki 		dev_err(component->dev, "unable to enable mclk\n");
7446dd567dcSKatsuhiro Suzuki 		return ret;
7456dd567dcSKatsuhiro Suzuki 	}
746b8b88b70SDaniel Drake 
7472ff52976SKuninori Morimoto 	/* Reset codec and enable current state machine */
748b8b88b70SDaniel Drake 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
7492ff52976SKuninori Morimoto 	usleep_range(5000, 5500);
750b8b88b70SDaniel Drake 	snd_soc_component_write(component, ES8316_RESET, ES8316_RESET_CSM_ON);
751b8b88b70SDaniel Drake 	msleep(30);
752b8b88b70SDaniel Drake 
753b8b88b70SDaniel Drake 	/*
754b8b88b70SDaniel Drake 	 * Documentation is unclear, but this value from the vendor driver is
755b8b88b70SDaniel Drake 	 * needed otherwise audio output is silent.
7562ff52976SKuninori Morimoto 	 */
757b8b88b70SDaniel Drake 	snd_soc_component_write(component, ES8316_SYS_VMIDSEL, 0xff);
758b8b88b70SDaniel Drake 
759b8b88b70SDaniel Drake 	/*
760b8b88b70SDaniel Drake 	 * Documentation for this register is unclear and incomplete,
761b8b88b70SDaniel Drake 	 * but here is a vendor-provided value that improves volume
762b8b88b70SDaniel Drake 	 * and quality for Intel CHT platforms.
7632ff52976SKuninori Morimoto 	 */
764b8b88b70SDaniel Drake 	snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
765b8b88b70SDaniel Drake 
766b8b88b70SDaniel Drake 	return 0;
767b8b88b70SDaniel Drake }
7686dd567dcSKatsuhiro Suzuki 
es8316_remove(struct snd_soc_component * component)7696dd567dcSKatsuhiro Suzuki static void es8316_remove(struct snd_soc_component *component)
7706dd567dcSKatsuhiro Suzuki {
7716dd567dcSKatsuhiro Suzuki 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7726dd567dcSKatsuhiro Suzuki 
7736dd567dcSKatsuhiro Suzuki 	clk_disable_unprepare(es8316->mclk);
7746dd567dcSKatsuhiro Suzuki }
7754bac47a7SZhu Ning 
es8316_resume(struct snd_soc_component * component)7764bac47a7SZhu Ning static int es8316_resume(struct snd_soc_component *component)
7774bac47a7SZhu Ning {
7784bac47a7SZhu Ning 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7794bac47a7SZhu Ning 
7804bac47a7SZhu Ning 	regcache_cache_only(es8316->regmap, false);
7814bac47a7SZhu Ning 	regcache_sync(es8316->regmap);
7824bac47a7SZhu Ning 
7834bac47a7SZhu Ning 	return 0;
7844bac47a7SZhu Ning }
7854bac47a7SZhu Ning 
es8316_suspend(struct snd_soc_component * component)7864bac47a7SZhu Ning static int es8316_suspend(struct snd_soc_component *component)
7874bac47a7SZhu Ning {
7884bac47a7SZhu Ning 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
7894bac47a7SZhu Ning 
7904bac47a7SZhu Ning 	regcache_cache_only(es8316->regmap, true);
7914bac47a7SZhu Ning 	regcache_mark_dirty(es8316->regmap);
7924bac47a7SZhu Ning 
7934bac47a7SZhu Ning 	return 0;
7944bac47a7SZhu Ning }
7952ff52976SKuninori Morimoto 
796b8b88b70SDaniel Drake static const struct snd_soc_component_driver soc_component_dev_es8316 = {
7976dd567dcSKatsuhiro Suzuki 	.probe			= es8316_probe,
7984bac47a7SZhu Ning 	.remove			= es8316_remove,
7994bac47a7SZhu Ning 	.resume			= es8316_resume,
80082225766SHans de Goede 	.suspend		= es8316_suspend,
801b8b88b70SDaniel Drake 	.set_jack		= es8316_set_jack,
802b8b88b70SDaniel Drake 	.controls		= es8316_snd_controls,
803b8b88b70SDaniel Drake 	.num_controls		= ARRAY_SIZE(es8316_snd_controls),
804b8b88b70SDaniel Drake 	.dapm_widgets		= es8316_dapm_widgets,
805b8b88b70SDaniel Drake 	.num_dapm_widgets	= ARRAY_SIZE(es8316_dapm_widgets),
806b8b88b70SDaniel Drake 	.dapm_routes		= es8316_dapm_routes,
8072ff52976SKuninori Morimoto 	.num_dapm_routes	= ARRAY_SIZE(es8316_dapm_routes),
8082ff52976SKuninori Morimoto 	.use_pmdown_time	= 1,
809b8b88b70SDaniel Drake 	.endianness		= 1,
810b8b88b70SDaniel Drake };
8112cc3fdcdSMark Brown 
es8316_volatile_reg(struct device * dev,unsigned int reg)8122cc3fdcdSMark Brown static bool es8316_volatile_reg(struct device *dev, unsigned int reg)
8132cc3fdcdSMark Brown {
8142cc3fdcdSMark Brown 	switch (reg) {
8152cc3fdcdSMark Brown 	case ES8316_GPIO_FLAG:
8162cc3fdcdSMark Brown 		return true;
8172cc3fdcdSMark Brown 	default:
8182cc3fdcdSMark Brown 		return false;
8192cc3fdcdSMark Brown 	}
82082225766SHans de Goede }
821b8b88b70SDaniel Drake 
822b8b88b70SDaniel Drake static const struct regmap_config es8316_regmap = {
823b8b88b70SDaniel Drake 	.reg_bits = 8,
8246de0b029SPierre-Louis Bossart 	.val_bits = 8,
8256de0b029SPierre-Louis Bossart 	.use_single_read = true,
826b8b88b70SDaniel Drake 	.use_single_write = true,
8272cc3fdcdSMark Brown 	.max_register = 0x53,
8287ae8039fSMark Brown 	.volatile_reg = es8316_volatile_reg,
829b8b88b70SDaniel Drake 	.cache_type = REGCACHE_MAPLE,
830b8b88b70SDaniel Drake };
831a327bdc6SStephen Kitt 
es8316_i2c_probe(struct i2c_client * i2c_client)832b8b88b70SDaniel Drake static int es8316_i2c_probe(struct i2c_client *i2c_client)
83382225766SHans de Goede {
834b8b88b70SDaniel Drake 	struct device *dev = &i2c_client->dev;
83582225766SHans de Goede 	struct es8316_priv *es8316;
836b8b88b70SDaniel Drake 	int ret;
837b8b88b70SDaniel Drake 
838b8b88b70SDaniel Drake 	es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
839b8b88b70SDaniel Drake 			      GFP_KERNEL);
840b8b88b70SDaniel Drake 	if (es8316 == NULL)
841b8b88b70SDaniel Drake 		return -ENOMEM;
842b8b88b70SDaniel Drake 
843b8b88b70SDaniel Drake 	i2c_set_clientdata(i2c_client, es8316);
84482225766SHans de Goede 
84582225766SHans de Goede 	es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
84682225766SHans de Goede 	if (IS_ERR(es8316->regmap))
84782225766SHans de Goede 		return PTR_ERR(es8316->regmap);
84882225766SHans de Goede 
84982225766SHans de Goede 	es8316->irq = i2c_client->irq;
85082225766SHans de Goede 	mutex_init(&es8316->lock);
85139db65a0SCristian Ciocaltea 
85282225766SHans de Goede 	if (es8316->irq > 0) {
8531cf2aa66SHans de Goede 		ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq,
85482225766SHans de Goede 						IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN,
8551cf2aa66SHans de Goede 						"es8316", es8316);
85682225766SHans de Goede 		if (ret) {
85782225766SHans de Goede 			dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret);
85882225766SHans de Goede 			es8316->irq = -ENXIO;
85939db65a0SCristian Ciocaltea 		}
860b8b88b70SDaniel Drake 	}
8612ff52976SKuninori Morimoto 
8622ff52976SKuninori Morimoto 	return devm_snd_soc_register_component(&i2c_client->dev,
863b8b88b70SDaniel Drake 				      &soc_component_dev_es8316,
864b8b88b70SDaniel Drake 				      &es8316_dai, 1);
865b8b88b70SDaniel Drake }
866b8b88b70SDaniel Drake 
867b8b88b70SDaniel Drake static const struct i2c_device_id es8316_i2c_id[] = {
868b8b88b70SDaniel Drake 	{"es8316", 0 },
869b8b88b70SDaniel Drake 	{}
870b8b88b70SDaniel Drake };
871b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
87275333af4SKrzysztof Kozlowski 
873b8b88b70SDaniel Drake #ifdef CONFIG_OF
874b8b88b70SDaniel Drake static const struct of_device_id es8316_of_match[] = {
875b8b88b70SDaniel Drake 	{ .compatible = "everest,es8316", },
876b8b88b70SDaniel Drake 	{},
877b8b88b70SDaniel Drake };
87875333af4SKrzysztof Kozlowski MODULE_DEVICE_TABLE(of, es8316_of_match);
879b8b88b70SDaniel Drake #endif
88007ac6709SPierre-Louis Bossart 
881b8b88b70SDaniel Drake #ifdef CONFIG_ACPI
882b8b88b70SDaniel Drake static const struct acpi_device_id es8316_acpi_match[] = {
883986c5b0aSPierre-Louis Bossart 	{"ESSX8316", 0},
884b8b88b70SDaniel Drake 	{"ESSX8336", 0},
885b8b88b70SDaniel Drake 	{},
886b8b88b70SDaniel Drake };
88707ac6709SPierre-Louis Bossart MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
888b8b88b70SDaniel Drake #endif
889b8b88b70SDaniel Drake 
890b8b88b70SDaniel Drake static struct i2c_driver es8316_i2c_driver = {
891b8b88b70SDaniel Drake 	.driver = {
892b8b88b70SDaniel Drake 		.name			= "es8316",
893b8b88b70SDaniel Drake 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
894b8b88b70SDaniel Drake 		.of_match_table		= of_match_ptr(es8316_of_match),
8959abcd240SUwe Kleine-König 	},
896b8b88b70SDaniel Drake 	.probe		= es8316_i2c_probe,
897b8b88b70SDaniel Drake 	.id_table	= es8316_i2c_id,
898b8b88b70SDaniel Drake };
899b8b88b70SDaniel Drake module_i2c_driver(es8316_i2c_driver);
900b8b88b70SDaniel Drake 
901b8b88b70SDaniel Drake MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
902b8b88b70SDaniel Drake MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
903 MODULE_LICENSE("GPL v2");
904