x86/speculation/mds: Fix documentation typo
[linux/fpc-iii.git] / sound / soc / codecs / es8316.c
blobda2d353af5ba29a8c2018673bbddc626a56641cf
1 /*
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>
24 #include "es8316.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
35 struct es8316_priv {
36 unsigned int sysclk;
37 unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
38 struct snd_pcm_hw_constraint_list sysclk_constraints;
42 * ES8316 controls
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);
48 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0);
49 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0);
51 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv,
52 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
53 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
54 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0),
55 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0),
56 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0),
57 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0),
58 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0),
59 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0),
60 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0),
61 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0),
62 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0),
65 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv,
66 0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
67 1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
70 static const char * const ng_type_txt[] =
71 { "Constant PGA Gain", "Mute ADC Output" };
72 static const struct soc_enum ng_type =
73 SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt);
75 static const char * const adcpol_txt[] = { "Normal", "Invert" };
76 static const struct soc_enum adcpol =
77 SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt);
78 static const char *const dacpol_txt[] =
79 { "Normal", "R Invert", "L Invert", "L + R Invert" };
80 static const struct soc_enum dacpol =
81 SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt);
83 static const struct snd_kcontrol_new es8316_snd_controls[] = {
84 SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL,
85 4, 0, 3, 1, hpout_vol_tlv),
86 SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL,
87 0, 4, 7, 0, hpmixer_gain_tlv),
89 SOC_ENUM("Playback Polarity", dacpol),
90 SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
91 ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv),
92 SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
93 SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
94 SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
95 SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
96 SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
98 SOC_ENUM("Capture Polarity", adcpol),
99 SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
100 SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME,
101 0, 0xc0, 1, adc_vol_tlv),
102 SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN,
103 4, 10, 0, adc_pga_gain_tlv),
104 SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0),
105 SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0),
107 SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0),
108 SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0,
109 alc_max_gain_tlv),
110 SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0,
111 alc_min_gain_tlv),
112 SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0,
113 alc_target_tlv),
114 SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0),
115 SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0),
116 SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0),
117 SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG,
118 5, 1, 0),
119 SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG,
120 0, 31, 0),
121 SOC_ENUM("ALC Capture Noise Gate Type", ng_type),
124 /* Analog Input Mux */
125 static const char * const es8316_analog_in_txt[] = {
126 "lin1-rin1",
127 "lin2-rin2",
128 "lin1-rin1 with 20db Boost",
129 "lin2-rin2 with 20db Boost"
131 static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 };
132 static const struct soc_enum es8316_analog_input_enum =
133 SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3,
134 ARRAY_SIZE(es8316_analog_in_txt),
135 es8316_analog_in_txt,
136 es8316_analog_in_values);
137 static const struct snd_kcontrol_new es8316_analog_in_mux_controls =
138 SOC_DAPM_ENUM("Route", es8316_analog_input_enum);
140 static const char * const es8316_dmic_txt[] = {
141 "dmic disable",
142 "dmic data at high level",
143 "dmic data at low level",
145 static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
146 static const struct soc_enum es8316_dmic_src_enum =
147 SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
148 ARRAY_SIZE(es8316_dmic_txt),
149 es8316_dmic_txt,
150 es8316_dmic_values);
151 static const struct snd_kcontrol_new es8316_dmic_src_controls =
152 SOC_DAPM_ENUM("Route", es8316_dmic_src_enum);
154 /* hp mixer mux */
155 static const char * const es8316_hpmux_texts[] = {
156 "lin1-rin1",
157 "lin2-rin2",
158 "lin-rin with Boost",
159 "lin-rin with Boost and PGA"
162 static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 };
164 static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
165 4, es8316_hpmux_texts);
167 static const struct snd_kcontrol_new es8316_left_hpmux_controls =
168 SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum);
170 static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL,
171 0, es8316_hpmux_texts);
173 static const struct snd_kcontrol_new es8316_right_hpmux_controls =
174 SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum);
176 /* headphone Output Mixer */
177 static const struct snd_kcontrol_new es8316_out_left_mix[] = {
178 SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0),
179 SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
181 static const struct snd_kcontrol_new es8316_out_right_mix[] = {
182 SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0),
183 SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
186 /* DAC data source mux */
187 static const char * const es8316_dacsrc_texts[] = {
188 "LDATA TO LDAC, RDATA TO RDAC",
189 "LDATA TO LDAC, LDATA TO RDAC",
190 "RDATA TO LDAC, RDATA TO RDAC",
191 "RDATA TO LDAC, LDATA TO RDAC",
194 static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 };
196 static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
197 6, es8316_dacsrc_texts);
199 static const struct snd_kcontrol_new es8316_dacsrc_mux_controls =
200 SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum);
202 static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = {
203 SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0),
204 SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0),
205 SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0),
207 SND_SOC_DAPM_INPUT("DMIC"),
208 SND_SOC_DAPM_INPUT("MIC1"),
209 SND_SOC_DAPM_INPUT("MIC2"),
211 /* Input Mux */
212 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
213 &es8316_analog_in_mux_controls),
215 SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0),
216 SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0),
217 SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0),
218 SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL,
219 7, 1, NULL, 0),
220 SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1),
221 SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0,
222 &es8316_dmic_src_controls),
224 /* Digital Interface */
225 SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1,
226 ES8316_SERDATA_ADC, 6, 1),
227 SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0,
228 SND_SOC_NOPM, 0, 0),
230 SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
231 &es8316_dacsrc_mux_controls),
233 SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
234 SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
235 SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
236 SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
238 /* Headphone Output Side */
239 SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
240 &es8316_left_hpmux_controls),
241 SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
242 &es8316_right_hpmux_controls),
243 SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN,
244 5, 1, &es8316_out_left_mix[0],
245 ARRAY_SIZE(es8316_out_left_mix)),
246 SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN,
247 1, 1, &es8316_out_right_mix[0],
248 ARRAY_SIZE(es8316_out_right_mix)),
249 SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN,
250 4, 1, NULL, 0),
251 SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN,
252 0, 1, NULL, 0),
254 SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN,
255 6, 0, NULL, 0),
256 SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN,
257 2, 0, NULL, 0),
258 SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2,
259 5, 1, NULL, 0),
260 SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW,
261 4, 0, NULL, 0),
263 SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN,
264 5, 0, NULL, 0),
265 SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN,
266 1, 0, NULL, 0),
267 SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0),
269 /* pdn_Lical and pdn_Rical bits are documented as Reserved, but must
270 * be explicitly unset in order to enable HP output
272 SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL,
273 7, 1, NULL, 0),
274 SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL,
275 3, 1, NULL, 0),
277 SND_SOC_DAPM_OUTPUT("HPOL"),
278 SND_SOC_DAPM_OUTPUT("HPOR"),
281 static const struct snd_soc_dapm_route es8316_dapm_routes[] = {
282 /* Recording */
283 {"MIC1", NULL, "Mic Bias"},
284 {"MIC2", NULL, "Mic Bias"},
285 {"MIC1", NULL, "Bias"},
286 {"MIC2", NULL, "Bias"},
287 {"MIC1", NULL, "Analog power"},
288 {"MIC2", NULL, "Analog power"},
290 {"Differential Mux", "lin1-rin1", "MIC1"},
291 {"Differential Mux", "lin2-rin2", "MIC2"},
292 {"Line input PGA", NULL, "Differential Mux"},
294 {"Mono ADC", NULL, "ADC Clock"},
295 {"Mono ADC", NULL, "ADC Vref"},
296 {"Mono ADC", NULL, "ADC bias"},
297 {"Mono ADC", NULL, "Line input PGA"},
299 /* It's not clear why, but to avoid recording only silence,
300 * the DAC clock must be running for the ADC to work.
302 {"Mono ADC", NULL, "DAC Clock"},
304 {"Digital Mic Mux", "dmic disable", "Mono ADC"},
306 {"I2S OUT", NULL, "Digital Mic Mux"},
308 /* Playback */
309 {"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
311 {"Left DAC", NULL, "DAC Clock"},
312 {"Right DAC", NULL, "DAC Clock"},
314 {"Left DAC", NULL, "DAC Vref"},
315 {"Right DAC", NULL, "DAC Vref"},
317 {"Left DAC", NULL, "DAC Source Mux"},
318 {"Right DAC", NULL, "DAC Source Mux"},
320 {"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
321 {"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
323 {"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"},
324 {"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
326 {"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"},
327 {"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
329 {"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"},
330 {"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"},
332 {"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"},
333 {"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"},
335 {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"},
336 {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"},
338 {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
339 {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"},
341 {"Left Headphone Driver", NULL, "Left Headphone Charge Pump"},
342 {"Right Headphone Driver", NULL, "Right Headphone Charge Pump"},
344 {"HPOL", NULL, "Left Headphone Driver"},
345 {"HPOR", NULL, "Right Headphone Driver"},
347 {"HPOL", NULL, "Left Headphone ical"},
348 {"HPOR", NULL, "Right Headphone ical"},
350 {"Headphone Out", NULL, "Bias"},
351 {"Headphone Out", NULL, "Analog power"},
352 {"HPOL", NULL, "Headphone Out"},
353 {"HPOR", NULL, "Headphone Out"},
356 static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai,
357 int clk_id, unsigned int freq, int dir)
359 struct snd_soc_codec *codec = codec_dai->codec;
360 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
361 int i;
362 int count = 0;
364 es8316->sysclk = freq;
366 if (freq == 0)
367 return 0;
369 /* Limit supported sample rates to ones that can be autodetected
370 * by the codec running in slave mode.
372 for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
373 const unsigned int ratio = supported_mclk_lrck_ratios[i];
375 if (freq % ratio == 0)
376 es8316->allowed_rates[count++] = freq / ratio;
379 es8316->sysclk_constraints.list = es8316->allowed_rates;
380 es8316->sysclk_constraints.count = count;
382 return 0;
385 static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai,
386 unsigned int fmt)
388 struct snd_soc_codec *codec = codec_dai->codec;
389 u8 serdata1 = 0;
390 u8 serdata2 = 0;
391 u8 clksw;
392 u8 mask;
394 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
395 dev_err(codec->dev, "Codec driver only supports slave mode\n");
396 return -EINVAL;
399 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) {
400 dev_err(codec->dev, "Codec driver only supports I2S format\n");
401 return -EINVAL;
404 /* Clock inversion */
405 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
406 case SND_SOC_DAIFMT_NB_NF:
407 break;
408 case SND_SOC_DAIFMT_IB_IF:
409 serdata1 |= ES8316_SERDATA1_BCLK_INV;
410 serdata2 |= ES8316_SERDATA2_ADCLRP;
411 break;
412 case SND_SOC_DAIFMT_IB_NF:
413 serdata1 |= ES8316_SERDATA1_BCLK_INV;
414 break;
415 case SND_SOC_DAIFMT_NB_IF:
416 serdata2 |= ES8316_SERDATA2_ADCLRP;
417 break;
418 default:
419 return -EINVAL;
422 mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV;
423 snd_soc_update_bits(codec, ES8316_SERDATA1, mask, serdata1);
425 mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP;
426 snd_soc_update_bits(codec, ES8316_SERDATA_ADC, mask, serdata2);
427 snd_soc_update_bits(codec, ES8316_SERDATA_DAC, mask, serdata2);
429 /* Enable BCLK and MCLK inputs in slave mode */
430 clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON;
431 snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW, clksw, clksw);
433 return 0;
436 static int es8316_pcm_startup(struct snd_pcm_substream *substream,
437 struct snd_soc_dai *dai)
439 struct snd_soc_codec *codec = dai->codec;
440 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
442 if (es8316->sysclk == 0) {
443 dev_err(codec->dev, "No sysclk provided\n");
444 return -EINVAL;
447 /* The set of sample rates that can be supported depends on the
448 * MCLK supplied to the CODEC.
450 snd_pcm_hw_constraint_list(substream->runtime, 0,
451 SNDRV_PCM_HW_PARAM_RATE,
452 &es8316->sysclk_constraints);
454 return 0;
457 static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
458 struct snd_pcm_hw_params *params,
459 struct snd_soc_dai *dai)
461 struct snd_soc_pcm_runtime *rtd = substream->private_data;
462 struct snd_soc_codec *codec = rtd->codec;
463 struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec);
464 u8 wordlen = 0;
466 if (!es8316->sysclk) {
467 dev_err(codec->dev, "No MCLK configured\n");
468 return -EINVAL;
471 switch (params_format(params)) {
472 case SNDRV_PCM_FORMAT_S16_LE:
473 wordlen = ES8316_SERDATA2_LEN_16;
474 break;
475 case SNDRV_PCM_FORMAT_S20_3LE:
476 wordlen = ES8316_SERDATA2_LEN_20;
477 break;
478 case SNDRV_PCM_FORMAT_S24_LE:
479 wordlen = ES8316_SERDATA2_LEN_24;
480 break;
481 case SNDRV_PCM_FORMAT_S32_LE:
482 wordlen = ES8316_SERDATA2_LEN_32;
483 break;
484 default:
485 return -EINVAL;
488 snd_soc_update_bits(codec, ES8316_SERDATA_DAC,
489 ES8316_SERDATA2_LEN_MASK, wordlen);
490 snd_soc_update_bits(codec, ES8316_SERDATA_ADC,
491 ES8316_SERDATA2_LEN_MASK, wordlen);
492 return 0;
495 static int es8316_mute(struct snd_soc_dai *dai, int mute)
497 snd_soc_update_bits(dai->codec, ES8316_DAC_SET1, 0x20,
498 mute ? 0x20 : 0);
499 return 0;
502 #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
503 SNDRV_PCM_FMTBIT_S24_LE)
505 static const struct snd_soc_dai_ops es8316_ops = {
506 .startup = es8316_pcm_startup,
507 .hw_params = es8316_pcm_hw_params,
508 .set_fmt = es8316_set_dai_fmt,
509 .set_sysclk = es8316_set_dai_sysclk,
510 .digital_mute = es8316_mute,
513 static struct snd_soc_dai_driver es8316_dai = {
514 .name = "ES8316 HiFi",
515 .playback = {
516 .stream_name = "Playback",
517 .channels_min = 1,
518 .channels_max = 2,
519 .rates = SNDRV_PCM_RATE_8000_48000,
520 .formats = ES8316_FORMATS,
522 .capture = {
523 .stream_name = "Capture",
524 .channels_min = 1,
525 .channels_max = 2,
526 .rates = SNDRV_PCM_RATE_8000_48000,
527 .formats = ES8316_FORMATS,
529 .ops = &es8316_ops,
530 .symmetric_rates = 1,
533 static int es8316_probe(struct snd_soc_codec *codec)
535 /* Reset codec and enable current state machine */
536 snd_soc_write(codec, ES8316_RESET, 0x3f);
537 usleep_range(5000, 5500);
538 snd_soc_write(codec, ES8316_RESET, ES8316_RESET_CSM_ON);
539 msleep(30);
542 * Documentation is unclear, but this value from the vendor driver is
543 * needed otherwise audio output is silent.
545 snd_soc_write(codec, ES8316_SYS_VMIDSEL, 0xff);
548 * Documentation for this register is unclear and incomplete,
549 * but here is a vendor-provided value that improves volume
550 * and quality for Intel CHT platforms.
552 snd_soc_write(codec, ES8316_CLKMGR_ADCOSR, 0x32);
554 return 0;
557 static const struct snd_soc_codec_driver soc_codec_dev_es8316 = {
558 .probe = es8316_probe,
559 .idle_bias_off = true,
561 .component_driver = {
562 .controls = es8316_snd_controls,
563 .num_controls = ARRAY_SIZE(es8316_snd_controls),
564 .dapm_widgets = es8316_dapm_widgets,
565 .num_dapm_widgets = ARRAY_SIZE(es8316_dapm_widgets),
566 .dapm_routes = es8316_dapm_routes,
567 .num_dapm_routes = ARRAY_SIZE(es8316_dapm_routes),
571 static const struct regmap_config es8316_regmap = {
572 .reg_bits = 8,
573 .val_bits = 8,
574 .max_register = 0x53,
575 .cache_type = REGCACHE_RBTREE,
578 static int es8316_i2c_probe(struct i2c_client *i2c_client,
579 const struct i2c_device_id *id)
581 struct es8316_priv *es8316;
582 struct regmap *regmap;
584 es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
585 GFP_KERNEL);
586 if (es8316 == NULL)
587 return -ENOMEM;
589 i2c_set_clientdata(i2c_client, es8316);
591 regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
592 if (IS_ERR(regmap))
593 return PTR_ERR(regmap);
595 return snd_soc_register_codec(&i2c_client->dev, &soc_codec_dev_es8316,
596 &es8316_dai, 1);
599 static int es8316_i2c_remove(struct i2c_client *client)
601 snd_soc_unregister_codec(&client->dev);
602 return 0;
605 static const struct i2c_device_id es8316_i2c_id[] = {
606 {"es8316", 0 },
609 MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
611 static const struct of_device_id es8316_of_match[] = {
612 { .compatible = "everest,es8316", },
615 MODULE_DEVICE_TABLE(of, es8316_of_match);
617 static const struct acpi_device_id es8316_acpi_match[] = {
618 {"ESSX8316", 0},
621 MODULE_DEVICE_TABLE(acpi, es8316_acpi_match);
623 static struct i2c_driver es8316_i2c_driver = {
624 .driver = {
625 .name = "es8316",
626 .acpi_match_table = ACPI_PTR(es8316_acpi_match),
627 .of_match_table = of_match_ptr(es8316_of_match),
629 .probe = es8316_i2c_probe,
630 .remove = es8316_i2c_remove,
631 .id_table = es8316_i2c_id,
633 module_i2c_driver(es8316_i2c_driver);
635 MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver");
636 MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
637 MODULE_LICENSE("GPL v2");