2 * es8316.c -- es8316 ALSA SoC audio driver
3 * Copyright Everest Semiconductor Co.,Ltd
5 * Authors: David Yang <yangxiaohua@everest-semi.com>,
6 * Daniel Drake <drake@endlessm.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/acpi.h>
15 #include <linux/delay.h>
16 #include <linux/i2c.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/regmap.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/soc-dapm.h>
23 #include <sound/tlv.h>
26 /* In slave mode at single speed, the codec is documented as accepting 5
27 * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
28 * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
30 #define NR_SUPPORTED_MCLK_LRCK_RATIOS 6
31 static const unsigned int supported_mclk_lrck_ratios[] = {
32 256, 384, 400, 512, 768, 1024
37 unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
38 struct snd_pcm_hw_constraint_list sysclk_constraints;
44 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
45 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
46 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
47 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
49 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(alc_target_tlv,
50 0, 10, TLV_DB_SCALE_ITEM(-1650, 150, 0),
51 11, 11, TLV_DB_SCALE_ITEM(-150, 0, 0),
54 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv,
55 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
56 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
59 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
60 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
61 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
62 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
63 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
64 4, 7, TLV_DB_SCALE_ITEM(700, 300, 0),
65 8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0),
68 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
69 0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
70 1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
73 static const char * const ng_type_txt[] =
74 { "Constant PGA Gain", "Mute ADC Output" };
75 static const struct soc_enum ng_type =
76 SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt);
78 static const char * const adcpol_txt[] = { "Normal", "Invert" };
79 static const struct soc_enum adcpol =
80 SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt);
81 static const char *const dacpol_txt[] =
82 { "Normal", "R Invert", "L Invert", "L + R Invert" };
83 static const struct soc_enum dacpol =
84 SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt);
86 static const struct snd_kcontrol_new es8316_snd_controls[] = {
87 SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
88 4, 0, 3, 1, hpout_vol_tlv),
89 SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
90 0, 4, 11, 0, hpmixer_gain_tlv),
92 SOC_ENUM("Playback Polarity", dacpol),
93 SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
94 ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv),
95 SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
96 SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
97 SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
98 SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
99 SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
101 SOC_ENUM("Capture Polarity", adcpol),
102 SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
103 SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME,
104 0, 0xc0, 1, adc_vol_tlv),
105 SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN,
106 4, 10, 0, adc_pga_gain_tlv),
107 SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0),
108 SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0),
110 SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0),
111 SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0,
113 SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0,
115 SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 11, 0,
117 SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0),
118 SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0),
119 SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0),
120 SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG,
122 SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG,
124 SOC_ENUM("ALC Capture Noise Gate Type", ng_type),
127 /* Analog Input Mux */
128 static const char * const es8316_analog_in_txt[] = {
131 "lin1-rin1 with 20db Boost",
132 "lin2-rin2 with 20db Boost"
134 static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 };
135 static const struct soc_enum es8316_analog_input_enum =
136 SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3,
137 ARRAY_SIZE(es8316_analog_in_txt),
138 es8316_analog_in_txt,
139 es8316_analog_in_values);
140 static const struct snd_kcontrol_new es8316_analog_in_mux_controls =
141 SOC_DAPM_ENUM("Route", es8316_analog_input_enum);
143 static const char * const es8316_dmic_txt[] = {
145 "dmic data at high level",
146 "dmic data at low level",
148 static const unsigned int es8316_dmic_values[] = { 0, 2, 3 };
149 static const struct soc_enum es8316_dmic_src_enum =
150 SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
151 ARRAY_SIZE(es8316_dmic_txt),
154 static const struct snd_kcontrol_new es8316_dmic_src_controls =
155 SOC_DAPM_ENUM("Route", es8316_dmic_src_enum);
158 static const char * const es8316_hpmux_texts[] = {
161 "lin-rin with Boost",
162 "lin-rin with Boost and PGA"
165 static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 };
167 static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
168 4, es8316_hpmux_texts);
170 static const struct snd_kcontrol_new es8316_left_hpmux_controls =
171 SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum);
173 static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL,
174 0, es8316_hpmux_texts);
176 static const struct snd_kcontrol_new es8316_right_hpmux_controls =
177 SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum);
179 /* headphone Output Mixer */
180 static const struct snd_kcontrol_new es8316_out_left_mix[] = {
181 SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0),
182 SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
184 static const struct snd_kcontrol_new es8316_out_right_mix[] = {
185 SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0),
186 SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
189 /* DAC data source mux */
190 static const char * const es8316_dacsrc_texts[] = {
191 "LDATA TO LDAC, RDATA TO RDAC",
192 "LDATA TO LDAC, LDATA TO RDAC",
193 "RDATA TO LDAC, RDATA TO RDAC",
194 "RDATA TO LDAC, LDATA TO RDAC",
197 static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 };
199 static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
200 6, es8316_dacsrc_texts);
202 static const struct snd_kcontrol_new es8316_dacsrc_mux_controls =
203 SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum);
205 static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = {
206 SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0),
207 SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0),
208 SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0),
210 SND_SOC_DAPM_INPUT("DMIC"),
211 SND_SOC_DAPM_INPUT("MIC1"),
212 SND_SOC_DAPM_INPUT("MIC2"),
215 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
216 &es8316_analog_in_mux_controls),
218 SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0),
219 SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0),
220 SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0),
221 SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL,
223 SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1),
224 SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0,
225 &es8316_dmic_src_controls),
227 /* Digital Interface */
228 SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1,
229 ES8316_SERDATA_ADC, 6, 1),
230 SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0,
233 SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
234 &es8316_dacsrc_mux_controls),
236 SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
237 SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
238 SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
239 SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
241 /* Headphone Output Side */
242 SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
243 &es8316_left_hpmux_controls),
244 SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
245 &es8316_right_hpmux_controls),
246 SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN,
247 5, 1, &es8316_out_left_mix[0],
248 ARRAY_SIZE(es8316_out_left_mix)),
249 SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN,
250 1, 1, &es8316_out_right_mix[0],
251 ARRAY_SIZE(es8316_out_right_mix)),
252 SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN,
254 SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN,
257 SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN,
259 SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN,
261 SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2,
263 SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW,
266 SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN,
268 SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN,
270 SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0),
272 /* pdn_Lical and pdn_Rical bits are documented as Reserved, but must
273 * be explicitly unset in order to enable HP output
275 SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL,
277 SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL,
280 SND_SOC_DAPM_OUTPUT("HPOL"),
281 SND_SOC_DAPM_OUTPUT("HPOR"),
284 static const struct snd_soc_dapm_route es8316_dapm_routes[] = {
286 {"MIC1", NULL, "Mic Bias"},
287 {"MIC2", NULL, "Mic Bias"},
288 {"MIC1", NULL, "Bias"},
289 {"MIC2", NULL, "Bias"},
290 {"MIC1", NULL, "Analog power"},
291 {"MIC2", NULL, "Analog power"},
293 {"Differential Mux", "lin1-rin1", "MIC1"},
294 {"Differential Mux", "lin2-rin2", "MIC2"},
295 {"Line input PGA", NULL, "Differential Mux"},
297 {"Mono ADC", NULL, "ADC Clock"},
298 {"Mono ADC", NULL, "ADC Vref"},
299 {"Mono ADC", NULL, "ADC bias"},
300 {"Mono ADC", NULL, "Line input PGA"},
302 /* It's not clear why, but to avoid recording only silence,
303 * the DAC clock must be running for the ADC to work.
305 {"Mono ADC", NULL, "DAC Clock"},
307 {"Digital Mic Mux", "dmic disable", "Mono ADC"},
309 {"I2S OUT", NULL, "Digital Mic Mux"},
312 {"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
314 {"Left DAC", NULL, "DAC Clock"},
315 {"Right DAC", NULL, "DAC Clock"},
317 {"Left DAC", NULL, "DAC Vref"},
318 {"Right DAC", NULL, "DAC Vref"},
320 {"Left DAC", NULL, "DAC Source Mux"},
321 {"Right DAC", NULL, "DAC Source Mux"},
323 {"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
324 {"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
326 {"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"},
327 {"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
329 {"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"},
330 {"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
332 {"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"},
333 {"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"},
335 {"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"},
336 {"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"},
338 {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"},
339 {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"},
341 {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
342 {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
344 {"Left Headphone Driver", NULL, "Left Headphone Charge Pump"},
345 {"Right Headphone Driver", NULL, "Right Headphone Charge Pump"},
347 {"HPOL", NULL, "Left Headphone Driver"},
348 {"HPOR", NULL, "Right Headphone Driver"},
350 {"HPOL", NULL, "Left Headphone ical"},
351 {"HPOR", NULL, "Right Headphone ical"},
353 {"Headphone Out", NULL, "Bias"},
354 {"Headphone Out", NULL, "Analog power"},
355 {"HPOL", NULL, "Headphone Out"},
356 {"HPOR", NULL, "Headphone Out"},
359 static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
360 int clk_id, unsigned int freq, int dir)
362 struct snd_soc_codec *codec = codec_dai->codec;
363 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
367 es8316->sysclk = freq;
372 /* Limit supported sample rates to ones that can be autodetected
373 * by the codec running in slave mode.
375 for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
376 const unsigned int ratio = supported_mclk_lrck_ratios[i];
378 if (freq % ratio == 0)
379 es8316->allowed_rates[count++] = freq / ratio;
382 es8316->sysclk_constraints.list = es8316->allowed_rates;
383 es8316->sysclk_constraints.count = count;
388 static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai,
391 struct snd_soc_codec *codec = codec_dai->codec;
397 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
398 dev_err(codec->dev, "Codec driver only supports slave mode\n");
402 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
403 dev_err(codec->dev, "Codec driver only supports I2S format\n");
407 /* Clock inversion */
408 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
409 case SND_SOC_DAIFMT_NB_NF:
411 case SND_SOC_DAIFMT_IB_IF:
412 serdata1 |= ES8316_SERDATA1_BCLK_INV;
413 serdata2 |= ES8316_SERDATA2_ADCLRP;
415 case SND_SOC_DAIFMT_IB_NF:
416 serdata1 |= ES8316_SERDATA1_BCLK_INV;
418 case SND_SOC_DAIFMT_NB_IF:
419 serdata2 |= ES8316_SERDATA2_ADCLRP;
425 mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
426 snd_soc_update_bits(codec, ES8316_SERDATA1, mask, serdata1);
428 mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
429 snd_soc_update_bits(codec, ES8316_SERDATA_ADC, mask, serdata2);
430 snd_soc_update_bits(codec, ES8316_SERDATA_DAC, mask, serdata2);
432 /* Enable BCLK and MCLK inputs in slave mode */
433 clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
434 snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW, clksw, clksw);
439 static int es8316_pcm_startup(struct snd_pcm_substream *substream,
440 struct snd_soc_dai *dai)
442 struct snd_soc_codec *codec = dai->codec;
443 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
445 if (es8316->sysclk == 0) {
446 dev_err(codec->dev, "No sysclk provided\n");
450 /* The set of sample rates that can be supported depends on the
451 * MCLK supplied to the CODEC.
453 snd_pcm_hw_constraint_list(substream->runtime, 0,
454 SNDRV_PCM_HW_PARAM_RATE,
455 &es8316->sysclk_constraints);
460 static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
461 struct snd_pcm_hw_params *params,
462 struct snd_soc_dai *dai)
464 struct snd_soc_pcm_runtime *rtd = substream->private_data;
465 struct snd_soc_codec *codec = rtd->codec;
466 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
469 if (!es8316->sysclk) {
470 dev_err(codec->dev, "No MCLK configured\n");
474 switch (params_format(params)) {
475 case SNDRV_PCM_FORMAT_S16_LE:
476 wordlen = ES8316_SERDATA2_LEN_16;
478 case SNDRV_PCM_FORMAT_S20_3LE:
479 wordlen = ES8316_SERDATA2_LEN_20;
481 case SNDRV_PCM_FORMAT_S24_LE:
482 wordlen = ES8316_SERDATA2_LEN_24;
484 case SNDRV_PCM_FORMAT_S32_LE:
485 wordlen = ES8316_SERDATA2_LEN_32;
491 snd_soc_update_bits(codec, ES8316_SERDATA_DAC,
492 ES8316_SERDATA2_LEN_MASK, wordlen);
493 snd_soc_update_bits(codec, ES8316_SERDATA_ADC,
494 ES8316_SERDATA2_LEN_MASK, wordlen);
498 static int es8316_mute(struct snd_soc_dai *dai, int mute)
500 snd_soc_update_bits(dai->codec, ES8316_DAC_SET1, 0x20,
505 #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
506 SNDRV_PCM_FMTBIT_S24_LE)
508 static const struct snd_soc_dai_ops es8316_ops = {
509 .startup = es8316_pcm_startup,
510 .hw_params = es8316_pcm_hw_params,
511 .set_fmt = es8316_set_dai_fmt,
512 .set_sysclk = es8316_set_dai_sysclk,
513 .digital_mute = es8316_mute,
516 static struct snd_soc_dai_driver es8316_dai = {
517 .name = "ES8316 HiFi",
519 .stream_name = "Playback",
522 .rates = SNDRV_PCM_RATE_8000_48000,
523 .formats = ES8316_FORMATS,
526 .stream_name = "Capture",
529 .rates = SNDRV_PCM_RATE_8000_48000,
530 .formats = ES8316_FORMATS,
533 .symmetric_rates = 1,
536 static int es8316_probe(struct snd_soc_codec *codec)
538 /* Reset codec and enable current state machine */
539 snd_soc_write(codec, ES8316_RESET, 0x3f);
540 usleep_range(5000, 5500);
541 snd_soc_write(codec, ES8316_RESET, ES8316_RESET_CSM_ON);
545 * Documentation is unclear, but this value from the vendor driver is
546 * needed otherwise audio output is silent.
548 snd_soc_write(codec, ES8316_SYS_VMIDSEL, 0xff);
551 * Documentation for this register is unclear and incomplete,
552 * but here is a vendor-provided value that improves volume
553 * and quality for Intel CHT platforms.
555 snd_soc_write(codec, ES8316_CLKMGR_ADCOSR, 0x32);
560 static const struct snd_soc_codec_driver soc_codec_dev_es8316 = {
561 .probe = es8316_probe,
562 .idle_bias_off = true,
564 .component_driver = {
565 .controls = es8316_snd_controls,
566 .num_controls = ARRAY_SIZE(es8316_snd_controls),
567 .dapm_widgets = es8316_dapm_widgets,
568 .num_dapm_widgets = ARRAY_SIZE(es8316_dapm_widgets),
569 .dapm_routes = es8316_dapm_routes,
570 .num_dapm_routes = ARRAY_SIZE(es8316_dapm_routes),
574 static const struct regmap_config es8316_regmap = {
577 .max_register = 0x53,
578 .cache_type = REGCACHE_RBTREE,
581 static int es8316_i2c_probe(struct i2c_client *i2c_client,
582 const struct i2c_device_id *id)
584 struct es8316_priv *es8316;
585 struct regmap *regmap;
587 es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
592 i2c_set_clientdata(i2c_client, es8316);
594 regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
596 return PTR_ERR(regmap);
598 return snd_soc_register_codec(&i2c_client->dev, &soc_codec_dev_es8316,
602 static int es8316_i2c_remove(struct i2c_client *client)
604 snd_soc_unregister_codec(&client->dev);
608 static const struct i2c_device_id es8316_i2c_id[] = {
612 MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
614 static const struct of_device_id es8316_of_match[] = {
615 { .compatible = "everest,es8316", },
618 MODULE_DEVICE_TABLE(of, es8316_of_match);
620 static const struct acpi_device_id es8316_acpi_match[] = {
624 MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
626 static struct i2c_driver es8316_i2c_driver = {
629 .acpi_match_table = ACPI_PTR(es8316_acpi_match),
630 .of_match_table = of_match_ptr(es8316_of_match),
632 .probe = es8316_i2c_probe,
633 .remove = es8316_i2c_remove,
634 .id_table = es8316_i2c_id,
636 module_i2c_driver(es8316_i2c_driver);
638 MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
639 MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
640 MODULE_LICENSE("GPL v2");