xref: /openbmc/linux/sound/soc/codecs/es8316.c (revision 2ff52976)
1b8b88b70SDaniel Drake /*
2b8b88b70SDaniel Drake  * es8316.c -- es8316 ALSA SoC audio driver
3b8b88b70SDaniel Drake  * Copyright Everest Semiconductor Co.,Ltd
4b8b88b70SDaniel Drake  *
5b8b88b70SDaniel Drake  * Authors: David Yang <yangxiaohua@everest-semi.com>,
6b8b88b70SDaniel Drake  *          Daniel Drake <drake@endlessm.com>
7b8b88b70SDaniel Drake  *
8b8b88b70SDaniel Drake  * This program is free software; you can redistribute it and/or modify
9b8b88b70SDaniel Drake  * it under the terms of the GNU General Public License version 2 as
10b8b88b70SDaniel Drake  * published by the Free Software Foundation.
11b8b88b70SDaniel Drake  */
12b8b88b70SDaniel Drake 
13b8b88b70SDaniel Drake #include <linux/module.h>
14b8b88b70SDaniel Drake #include <linux/acpi.h>
15b8b88b70SDaniel Drake #include <linux/delay.h>
16b8b88b70SDaniel Drake #include <linux/i2c.h>
17b8b88b70SDaniel Drake #include <linux/mod_devicetable.h>
18b8b88b70SDaniel Drake #include <linux/regmap.h>
19b8b88b70SDaniel Drake #include <sound/pcm.h>
20b8b88b70SDaniel Drake #include <sound/pcm_params.h>
21b8b88b70SDaniel Drake #include <sound/soc.h>
22b8b88b70SDaniel Drake #include <sound/soc-dapm.h>
23b8b88b70SDaniel Drake #include <sound/tlv.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 {
36b8b88b70SDaniel Drake 	unsigned int sysclk;
37b8b88b70SDaniel Drake 	unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
38b8b88b70SDaniel Drake 	struct snd_pcm_hw_constraint_list sysclk_constraints;
39b8b88b70SDaniel Drake };
40b8b88b70SDaniel Drake 
41b8b88b70SDaniel Drake /*
42b8b88b70SDaniel Drake  * ES8316 controls
43b8b88b70SDaniel Drake  */
44b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
45b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
46b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
47b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
48b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
49b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
50b8b88b70SDaniel Drake 
51b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
52b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
53b8b88b70SDaniel Drake 	1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
54b8b88b70SDaniel Drake 	2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
55b8b88b70SDaniel Drake 	3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
56b8b88b70SDaniel Drake 	4, 4, TLV_DB_SCALE_ITEM(700, 0, 0),
57b8b88b70SDaniel Drake 	5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0),
58b8b88b70SDaniel Drake 	6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0),
59b8b88b70SDaniel Drake 	7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0),
60b8b88b70SDaniel Drake 	8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0),
61b8b88b70SDaniel Drake 	9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0),
62b8b88b70SDaniel Drake 	10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0),
63b8b88b70SDaniel Drake );
64b8b88b70SDaniel Drake 
65b8b88b70SDaniel Drake static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
66b8b88b70SDaniel Drake 	0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
67b8b88b70SDaniel Drake 	1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
68b8b88b70SDaniel Drake );
69b8b88b70SDaniel Drake 
70b8b88b70SDaniel Drake static const char * const ng_type_txt[] =
71b8b88b70SDaniel Drake 	{ "Constant PGA Gain", "Mute ADC Output" };
72b8b88b70SDaniel Drake static const struct soc_enum ng_type =
73b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt);
74b8b88b70SDaniel Drake 
75b8b88b70SDaniel Drake static const char * const adcpol_txt[] = { "Normal", "Invert" };
76b8b88b70SDaniel Drake static const struct soc_enum adcpol =
77b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt);
78b8b88b70SDaniel Drake static const char *const dacpol_txt[] =
79b8b88b70SDaniel Drake 	{ "Normal", "R Invert", "L Invert", "L + R Invert" };
80b8b88b70SDaniel Drake static const struct soc_enum dacpol =
81b8b88b70SDaniel Drake 	SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt);
82b8b88b70SDaniel Drake 
83b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_snd_controls[] = {
84b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
85b8b88b70SDaniel Drake 		       4, 0, 3, 1, hpout_vol_tlv),
86b8b88b70SDaniel Drake 	SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
87b8b88b70SDaniel Drake 		       0, 4, 7, 0, hpmixer_gain_tlv),
88b8b88b70SDaniel Drake 
89b8b88b70SDaniel Drake 	SOC_ENUM("Playback Polarity", dacpol),
90b8b88b70SDaniel Drake 	SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
91b8b88b70SDaniel Drake 			 ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv),
92b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
93b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
94b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
95b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
96b8b88b70SDaniel Drake 	SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
97b8b88b70SDaniel Drake 
98b8b88b70SDaniel Drake 	SOC_ENUM("Capture Polarity", adcpol),
99b8b88b70SDaniel Drake 	SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
100b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME,
101b8b88b70SDaniel Drake 		       0, 0xc0, 1, adc_vol_tlv),
102b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN,
103b8b88b70SDaniel Drake 		       4, 10, 0, adc_pga_gain_tlv),
104b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0),
105b8b88b70SDaniel Drake 	SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0),
106b8b88b70SDaniel Drake 
107b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0),
108b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0,
109b8b88b70SDaniel Drake 		       alc_max_gain_tlv),
110b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0,
111b8b88b70SDaniel Drake 		       alc_min_gain_tlv),
112b8b88b70SDaniel Drake 	SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0,
113b8b88b70SDaniel Drake 		       alc_target_tlv),
114b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0),
115b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0),
116b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0),
117b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG,
118b8b88b70SDaniel Drake 		   5, 1, 0),
119b8b88b70SDaniel Drake 	SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG,
120b8b88b70SDaniel Drake 		   0, 31, 0),
121b8b88b70SDaniel Drake 	SOC_ENUM("ALC Capture Noise Gate Type", ng_type),
122b8b88b70SDaniel Drake };
123b8b88b70SDaniel Drake 
124b8b88b70SDaniel Drake /* Analog Input Mux */
125b8b88b70SDaniel Drake static const char * const es8316_analog_in_txt[] = {
126b8b88b70SDaniel Drake 		"lin1-rin1",
127b8b88b70SDaniel Drake 		"lin2-rin2",
128b8b88b70SDaniel Drake 		"lin1-rin1 with 20db Boost",
129b8b88b70SDaniel Drake 		"lin2-rin2 with 20db Boost"
130b8b88b70SDaniel Drake };
131b8b88b70SDaniel Drake static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 };
132b8b88b70SDaniel Drake static const struct soc_enum es8316_analog_input_enum =
133b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3,
134b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_analog_in_txt),
135b8b88b70SDaniel Drake 			      es8316_analog_in_txt,
136b8b88b70SDaniel Drake 			      es8316_analog_in_values);
137b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_analog_in_mux_controls =
138b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_analog_input_enum);
139b8b88b70SDaniel Drake 
140b8b88b70SDaniel Drake static const char * const es8316_dmic_txt[] = {
141b8b88b70SDaniel Drake 		"dmic disable",
142b8b88b70SDaniel Drake 		"dmic data at high level",
143b8b88b70SDaniel Drake 		"dmic data at low level",
144b8b88b70SDaniel Drake };
145b8b88b70SDaniel Drake static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
146b8b88b70SDaniel Drake static const struct soc_enum es8316_dmic_src_enum =
147b8b88b70SDaniel Drake 	SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
148b8b88b70SDaniel Drake 			      ARRAY_SIZE(es8316_dmic_txt),
149b8b88b70SDaniel Drake 			      es8316_dmic_txt,
150b8b88b70SDaniel Drake 			      es8316_dmic_values);
151b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dmic_src_controls =
152b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dmic_src_enum);
153b8b88b70SDaniel Drake 
154b8b88b70SDaniel Drake /* hp mixer mux */
155b8b88b70SDaniel Drake static const char * const es8316_hpmux_texts[] = {
156b8b88b70SDaniel Drake 	"lin1-rin1",
157b8b88b70SDaniel Drake 	"lin2-rin2",
158b8b88b70SDaniel Drake 	"lin-rin with Boost",
159b8b88b70SDaniel Drake 	"lin-rin with Boost and PGA"
160b8b88b70SDaniel Drake };
161b8b88b70SDaniel Drake 
162b8b88b70SDaniel Drake static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 };
163b8b88b70SDaniel Drake 
164b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
165b8b88b70SDaniel Drake 	4, es8316_hpmux_texts);
166b8b88b70SDaniel Drake 
167b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_left_hpmux_controls =
168b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum);
169b8b88b70SDaniel Drake 
170b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL,
171b8b88b70SDaniel Drake 	0, es8316_hpmux_texts);
172b8b88b70SDaniel Drake 
173b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_right_hpmux_controls =
174b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum);
175b8b88b70SDaniel Drake 
176b8b88b70SDaniel Drake /* headphone Output Mixer */
177b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_left_mix[] = {
178b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0),
179b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
180b8b88b70SDaniel Drake };
181b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_out_right_mix[] = {
182b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0),
183b8b88b70SDaniel Drake 	SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
184b8b88b70SDaniel Drake };
185b8b88b70SDaniel Drake 
186b8b88b70SDaniel Drake /* DAC data source mux */
187b8b88b70SDaniel Drake static const char * const es8316_dacsrc_texts[] = {
188b8b88b70SDaniel Drake 	"LDATA TO LDAC, RDATA TO RDAC",
189b8b88b70SDaniel Drake 	"LDATA TO LDAC, LDATA TO RDAC",
190b8b88b70SDaniel Drake 	"RDATA TO LDAC, RDATA TO RDAC",
191b8b88b70SDaniel Drake 	"RDATA TO LDAC, LDATA TO RDAC",
192b8b88b70SDaniel Drake };
193b8b88b70SDaniel Drake 
194b8b88b70SDaniel Drake static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 };
195b8b88b70SDaniel Drake 
196b8b88b70SDaniel Drake static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
197b8b88b70SDaniel Drake 	6, es8316_dacsrc_texts);
198b8b88b70SDaniel Drake 
199b8b88b70SDaniel Drake static const struct snd_kcontrol_new es8316_dacsrc_mux_controls =
200b8b88b70SDaniel Drake 	SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum);
201b8b88b70SDaniel Drake 
202b8b88b70SDaniel Drake static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = {
203b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0),
204b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0),
205b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0),
206b8b88b70SDaniel Drake 
207b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("DMIC"),
208b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC1"),
209b8b88b70SDaniel Drake 	SND_SOC_DAPM_INPUT("MIC2"),
210b8b88b70SDaniel Drake 
211b8b88b70SDaniel Drake 	/* Input Mux */
212b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
213b8b88b70SDaniel Drake 			 &es8316_analog_in_mux_controls),
214b8b88b70SDaniel Drake 
215b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0),
216b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0),
217b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0),
218b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL,
219b8b88b70SDaniel Drake 			 7, 1, NULL, 0),
220b8b88b70SDaniel Drake 	SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1),
221b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0,
222b8b88b70SDaniel Drake 			 &es8316_dmic_src_controls),
223b8b88b70SDaniel Drake 
224b8b88b70SDaniel Drake 	/* Digital Interface */
225b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture",  1,
226b8b88b70SDaniel Drake 			     ES8316_SERDATA_ADC, 6, 1),
227b8b88b70SDaniel Drake 	SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0,
228b8b88b70SDaniel Drake 			    SND_SOC_NOPM, 0, 0),
229b8b88b70SDaniel Drake 
230b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
231b8b88b70SDaniel Drake 			 &es8316_dacsrc_mux_controls),
232b8b88b70SDaniel Drake 
233b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
234b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
235b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
236b8b88b70SDaniel Drake 	SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
237b8b88b70SDaniel Drake 
238b8b88b70SDaniel Drake 	/* Headphone Output Side */
239b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
240b8b88b70SDaniel Drake 			 &es8316_left_hpmux_controls),
241b8b88b70SDaniel Drake 	SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
242b8b88b70SDaniel Drake 			 &es8316_right_hpmux_controls),
243b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN,
244b8b88b70SDaniel Drake 			   5, 1, &es8316_out_left_mix[0],
245b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_left_mix)),
246b8b88b70SDaniel Drake 	SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN,
247b8b88b70SDaniel Drake 			   1, 1, &es8316_out_right_mix[0],
248b8b88b70SDaniel Drake 			   ARRAY_SIZE(es8316_out_right_mix)),
249b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN,
250b8b88b70SDaniel Drake 			 4, 1, NULL, 0),
251b8b88b70SDaniel Drake 	SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN,
252b8b88b70SDaniel Drake 			 0, 1, NULL, 0),
253b8b88b70SDaniel Drake 
254b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN,
255b8b88b70SDaniel Drake 			     6, 0, NULL, 0),
256b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN,
257b8b88b70SDaniel Drake 			     2, 0, NULL, 0),
258b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2,
259b8b88b70SDaniel Drake 			    5, 1, NULL, 0),
260b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW,
261b8b88b70SDaniel Drake 			    4, 0, NULL, 0),
262b8b88b70SDaniel Drake 
263b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN,
264b8b88b70SDaniel Drake 			     5, 0, NULL, 0),
265b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN,
266b8b88b70SDaniel Drake 			     1, 0, NULL, 0),
267b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0),
268b8b88b70SDaniel Drake 
269b8b88b70SDaniel Drake 	/* pdn_Lical and pdn_Rical bits are documented as Reserved, but must
270b8b88b70SDaniel Drake 	 * be explicitly unset in order to enable HP output
271b8b88b70SDaniel Drake 	 */
272b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL,
273b8b88b70SDaniel Drake 			    7, 1, NULL, 0),
274b8b88b70SDaniel Drake 	SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL,
275b8b88b70SDaniel Drake 			    3, 1, NULL, 0),
276b8b88b70SDaniel Drake 
277b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOL"),
278b8b88b70SDaniel Drake 	SND_SOC_DAPM_OUTPUT("HPOR"),
279b8b88b70SDaniel Drake };
280b8b88b70SDaniel Drake 
281b8b88b70SDaniel Drake static const struct snd_soc_dapm_route es8316_dapm_routes[] = {
282b8b88b70SDaniel Drake 	/* Recording */
283b8b88b70SDaniel Drake 	{"MIC1", NULL, "Mic Bias"},
284b8b88b70SDaniel Drake 	{"MIC2", NULL, "Mic Bias"},
285b8b88b70SDaniel Drake 	{"MIC1", NULL, "Bias"},
286b8b88b70SDaniel Drake 	{"MIC2", NULL, "Bias"},
287b8b88b70SDaniel Drake 	{"MIC1", NULL, "Analog power"},
288b8b88b70SDaniel Drake 	{"MIC2", NULL, "Analog power"},
289b8b88b70SDaniel Drake 
290b8b88b70SDaniel Drake 	{"Differential Mux", "lin1-rin1", "MIC1"},
291b8b88b70SDaniel Drake 	{"Differential Mux", "lin2-rin2", "MIC2"},
292b8b88b70SDaniel Drake 	{"Line input PGA", NULL, "Differential Mux"},
293b8b88b70SDaniel Drake 
294b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Clock"},
295b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC Vref"},
296b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "ADC bias"},
297b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "Line input PGA"},
298b8b88b70SDaniel Drake 
299b8b88b70SDaniel Drake 	/* It's not clear why, but to avoid recording only silence,
300b8b88b70SDaniel Drake 	 * the DAC clock must be running for the ADC to work.
301b8b88b70SDaniel Drake 	 */
302b8b88b70SDaniel Drake 	{"Mono ADC", NULL, "DAC Clock"},
303b8b88b70SDaniel Drake 
304b8b88b70SDaniel Drake 	{"Digital Mic Mux", "dmic disable", "Mono ADC"},
305b8b88b70SDaniel Drake 
306b8b88b70SDaniel Drake 	{"I2S OUT", NULL, "Digital Mic Mux"},
307b8b88b70SDaniel Drake 
308b8b88b70SDaniel Drake 	/* Playback */
309b8b88b70SDaniel Drake 	{"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
310b8b88b70SDaniel Drake 
311b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Clock"},
312b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Clock"},
313b8b88b70SDaniel Drake 
314b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Vref"},
315b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Vref"},
316b8b88b70SDaniel Drake 
317b8b88b70SDaniel Drake 	{"Left DAC", NULL, "DAC Source Mux"},
318b8b88b70SDaniel Drake 	{"Right DAC", NULL, "DAC Source Mux"},
319b8b88b70SDaniel Drake 
320b8b88b70SDaniel Drake 	{"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
321b8b88b70SDaniel Drake 	{"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
322b8b88b70SDaniel Drake 
323b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"},
324b8b88b70SDaniel Drake 	{"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
325b8b88b70SDaniel Drake 
326b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"},
327b8b88b70SDaniel Drake 	{"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
328b8b88b70SDaniel Drake 
329b8b88b70SDaniel Drake 	{"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"},
330b8b88b70SDaniel Drake 	{"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"},
331b8b88b70SDaniel Drake 
332b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"},
333b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"},
334b8b88b70SDaniel Drake 
335b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"},
336b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"},
337b8b88b70SDaniel Drake 
338b8b88b70SDaniel Drake 	{"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
339b8b88b70SDaniel Drake 	{"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
340b8b88b70SDaniel Drake 
341b8b88b70SDaniel Drake 	{"Left Headphone Driver", NULL, "Left Headphone Charge Pump"},
342b8b88b70SDaniel Drake 	{"Right Headphone Driver", NULL, "Right Headphone Charge Pump"},
343b8b88b70SDaniel Drake 
344b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone Driver"},
345b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone Driver"},
346b8b88b70SDaniel Drake 
347b8b88b70SDaniel Drake 	{"HPOL", NULL, "Left Headphone ical"},
348b8b88b70SDaniel Drake 	{"HPOR", NULL, "Right Headphone ical"},
349b8b88b70SDaniel Drake 
350b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Bias"},
351b8b88b70SDaniel Drake 	{"Headphone Out", NULL, "Analog power"},
352b8b88b70SDaniel Drake 	{"HPOL", NULL, "Headphone Out"},
353b8b88b70SDaniel Drake 	{"HPOR", NULL, "Headphone Out"},
354b8b88b70SDaniel Drake };
355b8b88b70SDaniel Drake 
356b8b88b70SDaniel Drake static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
357b8b88b70SDaniel Drake 				 int clk_id, unsigned int freq, int dir)
358b8b88b70SDaniel Drake {
3592ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
3602ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
361b8b88b70SDaniel Drake 	int i;
362b8b88b70SDaniel Drake 	int count = 0;
363b8b88b70SDaniel Drake 
364b8b88b70SDaniel Drake 	es8316->sysclk = freq;
365b8b88b70SDaniel Drake 
366b8b88b70SDaniel Drake 	if (freq == 0)
367b8b88b70SDaniel Drake 		return 0;
368b8b88b70SDaniel Drake 
369b8b88b70SDaniel Drake 	/* Limit supported sample rates to ones that can be autodetected
370b8b88b70SDaniel Drake 	 * by the codec running in slave mode.
371b8b88b70SDaniel Drake 	 */
372b8b88b70SDaniel Drake 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
373b8b88b70SDaniel Drake 		const unsigned int ratio = supported_mclk_lrck_ratios[i];
374b8b88b70SDaniel Drake 
375b8b88b70SDaniel Drake 		if (freq % ratio == 0)
376b8b88b70SDaniel Drake 			es8316->allowed_rates[count++] = freq / ratio;
377b8b88b70SDaniel Drake 	}
378b8b88b70SDaniel Drake 
379b8b88b70SDaniel Drake 	es8316->sysclk_constraints.list = es8316->allowed_rates;
380b8b88b70SDaniel Drake 	es8316->sysclk_constraints.count = count;
381b8b88b70SDaniel Drake 
382b8b88b70SDaniel Drake 	return 0;
383b8b88b70SDaniel Drake }
384b8b88b70SDaniel Drake 
385b8b88b70SDaniel Drake static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai,
386b8b88b70SDaniel Drake 			      unsigned int fmt)
387b8b88b70SDaniel Drake {
3882ff52976SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
389b8b88b70SDaniel Drake 	u8 serdata1 = 0;
390b8b88b70SDaniel Drake 	u8 serdata2 = 0;
391b8b88b70SDaniel Drake 	u8 clksw;
392b8b88b70SDaniel Drake 	u8 mask;
393b8b88b70SDaniel Drake 
394b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
3952ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports slave mode\n");
396b8b88b70SDaniel Drake 		return -EINVAL;
397b8b88b70SDaniel Drake 	}
398b8b88b70SDaniel Drake 
399b8b88b70SDaniel Drake 	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
4002ff52976SKuninori Morimoto 		dev_err(component->dev, "Codec driver only supports I2S format\n");
401b8b88b70SDaniel Drake 		return -EINVAL;
402b8b88b70SDaniel Drake 	}
403b8b88b70SDaniel Drake 
404b8b88b70SDaniel Drake 	/* Clock inversion */
405b8b88b70SDaniel Drake 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
406b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_NF:
407b8b88b70SDaniel Drake 		break;
408b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_IF:
409b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
410b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
411b8b88b70SDaniel Drake 		break;
412b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_IB_NF:
413b8b88b70SDaniel Drake 		serdata1 |= ES8316_SERDATA1_BCLK_INV;
414b8b88b70SDaniel Drake 		break;
415b8b88b70SDaniel Drake 	case SND_SOC_DAIFMT_NB_IF:
416b8b88b70SDaniel Drake 		serdata2 |= ES8316_SERDATA2_ADCLRP;
417b8b88b70SDaniel Drake 		break;
418b8b88b70SDaniel Drake 	default:
419b8b88b70SDaniel Drake 		return -EINVAL;
420b8b88b70SDaniel Drake 	}
421b8b88b70SDaniel Drake 
422b8b88b70SDaniel Drake 	mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
4232ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA1, mask, serdata1);
424b8b88b70SDaniel Drake 
425b8b88b70SDaniel Drake 	mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
4262ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC, mask, serdata2);
4272ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC, mask, serdata2);
428b8b88b70SDaniel Drake 
429b8b88b70SDaniel Drake 	/* Enable BCLK and MCLK inputs in slave mode */
430b8b88b70SDaniel Drake 	clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
4312ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW, clksw, clksw);
432b8b88b70SDaniel Drake 
433b8b88b70SDaniel Drake 	return 0;
434b8b88b70SDaniel Drake }
435b8b88b70SDaniel Drake 
436b8b88b70SDaniel Drake static int es8316_pcm_startup(struct snd_pcm_substream *substream,
437b8b88b70SDaniel Drake 			      struct snd_soc_dai *dai)
438b8b88b70SDaniel Drake {
4392ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4402ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
441b8b88b70SDaniel Drake 
442b8b88b70SDaniel Drake 	if (es8316->sysclk == 0) {
4432ff52976SKuninori Morimoto 		dev_err(component->dev, "No sysclk provided\n");
444b8b88b70SDaniel Drake 		return -EINVAL;
445b8b88b70SDaniel Drake 	}
446b8b88b70SDaniel Drake 
447b8b88b70SDaniel Drake 	/* The set of sample rates that can be supported depends on the
448b8b88b70SDaniel Drake 	 * MCLK supplied to the CODEC.
449b8b88b70SDaniel Drake 	 */
450b8b88b70SDaniel Drake 	snd_pcm_hw_constraint_list(substream->runtime, 0,
451b8b88b70SDaniel Drake 				   SNDRV_PCM_HW_PARAM_RATE,
452b8b88b70SDaniel Drake 				   &es8316->sysclk_constraints);
453b8b88b70SDaniel Drake 
454b8b88b70SDaniel Drake 	return 0;
455b8b88b70SDaniel Drake }
456b8b88b70SDaniel Drake 
457b8b88b70SDaniel Drake static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
458b8b88b70SDaniel Drake 				struct snd_pcm_hw_params *params,
459b8b88b70SDaniel Drake 				struct snd_soc_dai *dai)
460b8b88b70SDaniel Drake {
4612ff52976SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
4622ff52976SKuninori Morimoto 	struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
463b8b88b70SDaniel Drake 	u8 wordlen = 0;
464b8b88b70SDaniel Drake 
465b8b88b70SDaniel Drake 	if (!es8316->sysclk) {
4662ff52976SKuninori Morimoto 		dev_err(component->dev, "No MCLK configured\n");
467b8b88b70SDaniel Drake 		return -EINVAL;
468b8b88b70SDaniel Drake 	}
469b8b88b70SDaniel Drake 
470b8b88b70SDaniel Drake 	switch (params_format(params)) {
471b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S16_LE:
472b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_16;
473b8b88b70SDaniel Drake 		break;
474b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S20_3LE:
475b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_20;
476b8b88b70SDaniel Drake 		break;
477b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S24_LE:
478b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_24;
479b8b88b70SDaniel Drake 		break;
480b8b88b70SDaniel Drake 	case SNDRV_PCM_FORMAT_S32_LE:
481b8b88b70SDaniel Drake 		wordlen = ES8316_SERDATA2_LEN_32;
482b8b88b70SDaniel Drake 		break;
483b8b88b70SDaniel Drake 	default:
484b8b88b70SDaniel Drake 		return -EINVAL;
485b8b88b70SDaniel Drake 	}
486b8b88b70SDaniel Drake 
4872ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_DAC,
488b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
4892ff52976SKuninori Morimoto 	snd_soc_component_update_bits(component, ES8316_SERDATA_ADC,
490b8b88b70SDaniel Drake 			    ES8316_SERDATA2_LEN_MASK, wordlen);
491b8b88b70SDaniel Drake 	return 0;
492b8b88b70SDaniel Drake }
493b8b88b70SDaniel Drake 
494b8b88b70SDaniel Drake static int es8316_mute(struct snd_soc_dai *dai, int mute)
495b8b88b70SDaniel Drake {
4962ff52976SKuninori Morimoto 	snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20,
497b8b88b70SDaniel Drake 			    mute ? 0x20 : 0);
498b8b88b70SDaniel Drake 	return 0;
499b8b88b70SDaniel Drake }
500b8b88b70SDaniel Drake 
501b8b88b70SDaniel Drake #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
502b8b88b70SDaniel Drake 			SNDRV_PCM_FMTBIT_S24_LE)
503b8b88b70SDaniel Drake 
504eb59d73cSArvind Yadav static const struct snd_soc_dai_ops es8316_ops = {
505b8b88b70SDaniel Drake 	.startup = es8316_pcm_startup,
506b8b88b70SDaniel Drake 	.hw_params = es8316_pcm_hw_params,
507b8b88b70SDaniel Drake 	.set_fmt = es8316_set_dai_fmt,
508b8b88b70SDaniel Drake 	.set_sysclk = es8316_set_dai_sysclk,
509b8b88b70SDaniel Drake 	.digital_mute = es8316_mute,
510b8b88b70SDaniel Drake };
511b8b88b70SDaniel Drake 
512b8b88b70SDaniel Drake static struct snd_soc_dai_driver es8316_dai = {
513b8b88b70SDaniel Drake 	.name = "ES8316 HiFi",
514b8b88b70SDaniel Drake 	.playback = {
515b8b88b70SDaniel Drake 		.stream_name = "Playback",
516b8b88b70SDaniel Drake 		.channels_min = 1,
517b8b88b70SDaniel Drake 		.channels_max = 2,
518b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
519b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
520b8b88b70SDaniel Drake 	},
521b8b88b70SDaniel Drake 	.capture = {
522b8b88b70SDaniel Drake 		.stream_name = "Capture",
523b8b88b70SDaniel Drake 		.channels_min = 1,
524b8b88b70SDaniel Drake 		.channels_max = 2,
525b8b88b70SDaniel Drake 		.rates = SNDRV_PCM_RATE_8000_48000,
526b8b88b70SDaniel Drake 		.formats = ES8316_FORMATS,
527b8b88b70SDaniel Drake 	},
528b8b88b70SDaniel Drake 	.ops = &es8316_ops,
529b8b88b70SDaniel Drake 	.symmetric_rates = 1,
530b8b88b70SDaniel Drake };
531b8b88b70SDaniel Drake 
5322ff52976SKuninori Morimoto static int es8316_probe(struct snd_soc_component *component)
533b8b88b70SDaniel Drake {
534b8b88b70SDaniel Drake 	/* Reset codec and enable current state machine */
5352ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, 0x3f);
536b8b88b70SDaniel Drake 	usleep_range(5000, 5500);
5372ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_RESET, ES8316_RESET_CSM_ON);
538b8b88b70SDaniel Drake 	msleep(30);
539b8b88b70SDaniel Drake 
540b8b88b70SDaniel Drake 	/*
541b8b88b70SDaniel Drake 	 * Documentation is unclear, but this value from the vendor driver is
542b8b88b70SDaniel Drake 	 * needed otherwise audio output is silent.
543b8b88b70SDaniel Drake 	 */
5442ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_SYS_VMIDSEL, 0xff);
545b8b88b70SDaniel Drake 
546b8b88b70SDaniel Drake 	/*
547b8b88b70SDaniel Drake 	 * Documentation for this register is unclear and incomplete,
548b8b88b70SDaniel Drake 	 * but here is a vendor-provided value that improves volume
549b8b88b70SDaniel Drake 	 * and quality for Intel CHT platforms.
550b8b88b70SDaniel Drake 	 */
5512ff52976SKuninori Morimoto 	snd_soc_component_write(component, ES8316_CLKMGR_ADCOSR, 0x32);
552b8b88b70SDaniel Drake 
553b8b88b70SDaniel Drake 	return 0;
554b8b88b70SDaniel Drake }
555b8b88b70SDaniel Drake 
5562ff52976SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_es8316 = {
557b8b88b70SDaniel Drake 	.probe			= es8316_probe,
558b8b88b70SDaniel Drake 	.controls		= es8316_snd_controls,
559b8b88b70SDaniel Drake 	.num_controls		= ARRAY_SIZE(es8316_snd_controls),
560b8b88b70SDaniel Drake 	.dapm_widgets		= es8316_dapm_widgets,
561b8b88b70SDaniel Drake 	.num_dapm_widgets	= ARRAY_SIZE(es8316_dapm_widgets),
562b8b88b70SDaniel Drake 	.dapm_routes		= es8316_dapm_routes,
563b8b88b70SDaniel Drake 	.num_dapm_routes	= ARRAY_SIZE(es8316_dapm_routes),
5642ff52976SKuninori Morimoto 	.use_pmdown_time	= 1,
5652ff52976SKuninori Morimoto 	.endianness		= 1,
5662ff52976SKuninori Morimoto 	.non_legacy_dai_naming	= 1,
567b8b88b70SDaniel Drake };
568b8b88b70SDaniel Drake 
569b8b88b70SDaniel Drake static const struct regmap_config es8316_regmap = {
570b8b88b70SDaniel Drake 	.reg_bits = 8,
571b8b88b70SDaniel Drake 	.val_bits = 8,
572b8b88b70SDaniel Drake 	.max_register = 0x53,
573b8b88b70SDaniel Drake 	.cache_type = REGCACHE_RBTREE,
574b8b88b70SDaniel Drake };
575b8b88b70SDaniel Drake 
576b8b88b70SDaniel Drake static int es8316_i2c_probe(struct i2c_client *i2c_client,
577b8b88b70SDaniel Drake 			    const struct i2c_device_id *id)
578b8b88b70SDaniel Drake {
579b8b88b70SDaniel Drake 	struct es8316_priv *es8316;
580b8b88b70SDaniel Drake 	struct regmap *regmap;
581b8b88b70SDaniel Drake 
582b8b88b70SDaniel Drake 	es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
583b8b88b70SDaniel Drake 			      GFP_KERNEL);
584b8b88b70SDaniel Drake 	if (es8316 == NULL)
585b8b88b70SDaniel Drake 		return -ENOMEM;
586b8b88b70SDaniel Drake 
587b8b88b70SDaniel Drake 	i2c_set_clientdata(i2c_client, es8316);
588b8b88b70SDaniel Drake 
589b8b88b70SDaniel Drake 	regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
590b8b88b70SDaniel Drake 	if (IS_ERR(regmap))
591b8b88b70SDaniel Drake 		return PTR_ERR(regmap);
592b8b88b70SDaniel Drake 
5932ff52976SKuninori Morimoto 	return devm_snd_soc_register_component(&i2c_client->dev,
5942ff52976SKuninori Morimoto 				      &soc_component_dev_es8316,
595b8b88b70SDaniel Drake 				      &es8316_dai, 1);
596b8b88b70SDaniel Drake }
597b8b88b70SDaniel Drake 
598b8b88b70SDaniel Drake static const struct i2c_device_id es8316_i2c_id[] = {
599b8b88b70SDaniel Drake 	{"es8316", 0 },
600b8b88b70SDaniel Drake 	{}
601b8b88b70SDaniel Drake };
602b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
603b8b88b70SDaniel Drake 
604b8b88b70SDaniel Drake static const struct of_device_id es8316_of_match[] = {
605b8b88b70SDaniel Drake 	{ .compatible = "everest,es8316", },
606b8b88b70SDaniel Drake 	{},
607b8b88b70SDaniel Drake };
608b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(of, es8316_of_match);
609b8b88b70SDaniel Drake 
610b8b88b70SDaniel Drake static const struct acpi_device_id es8316_acpi_match[] = {
611b8b88b70SDaniel Drake 	{"ESSX8316", 0},
612b8b88b70SDaniel Drake 	{},
613b8b88b70SDaniel Drake };
614b8b88b70SDaniel Drake MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
615b8b88b70SDaniel Drake 
616b8b88b70SDaniel Drake static struct i2c_driver es8316_i2c_driver = {
617b8b88b70SDaniel Drake 	.driver = {
618b8b88b70SDaniel Drake 		.name			= "es8316",
619b8b88b70SDaniel Drake 		.acpi_match_table	= ACPI_PTR(es8316_acpi_match),
620b8b88b70SDaniel Drake 		.of_match_table		= of_match_ptr(es8316_of_match),
621b8b88b70SDaniel Drake 	},
622b8b88b70SDaniel Drake 	.probe		= es8316_i2c_probe,
623b8b88b70SDaniel Drake 	.id_table	= es8316_i2c_id,
624b8b88b70SDaniel Drake };
625b8b88b70SDaniel Drake module_i2c_driver(es8316_i2c_driver);
626b8b88b70SDaniel Drake 
627b8b88b70SDaniel Drake MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
628b8b88b70SDaniel Drake MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
629b8b88b70SDaniel Drake MODULE_LICENSE("GPL v2");
630