1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2567e4f98SSean Cross /*
3567e4f98SSean Cross * es8328.c -- ES8328 ALSA SoC Audio driver
4567e4f98SSean Cross *
5567e4f98SSean Cross * Copyright 2014 Sutajio Ko-Usagi PTE LTD
6567e4f98SSean Cross *
7567e4f98SSean Cross * Author: Sean Cross <xobs@kosagi.com>
8567e4f98SSean Cross */
9567e4f98SSean Cross
10567e4f98SSean Cross #include <linux/clk.h>
11567e4f98SSean Cross #include <linux/delay.h>
12567e4f98SSean Cross #include <linux/of_device.h>
13567e4f98SSean Cross #include <linux/module.h>
14567e4f98SSean Cross #include <linux/pm.h>
15567e4f98SSean Cross #include <linux/regmap.h>
16567e4f98SSean Cross #include <linux/slab.h>
17567e4f98SSean Cross #include <linux/regulator/consumer.h>
18567e4f98SSean Cross #include <sound/core.h>
19567e4f98SSean Cross #include <sound/initval.h>
20567e4f98SSean Cross #include <sound/pcm.h>
21567e4f98SSean Cross #include <sound/pcm_params.h>
22567e4f98SSean Cross #include <sound/soc.h>
23567e4f98SSean Cross #include <sound/tlv.h>
24567e4f98SSean Cross #include "es8328.h"
25567e4f98SSean Cross
2645749c91SJohn Keeping static const unsigned int rates_12288[] = {
2745749c91SJohn Keeping 8000, 12000, 16000, 24000, 32000, 48000, 96000,
2845749c91SJohn Keeping };
29567e4f98SSean Cross
3045749c91SJohn Keeping static const int ratios_12288[] = {
3145749c91SJohn Keeping 10, 7, 6, 4, 3, 2, 0,
3245749c91SJohn Keeping };
3345749c91SJohn Keeping
3445749c91SJohn Keeping static const struct snd_pcm_hw_constraint_list constraints_12288 = {
3545749c91SJohn Keeping .count = ARRAY_SIZE(rates_12288),
3645749c91SJohn Keeping .list = rates_12288,
3745749c91SJohn Keeping };
3845749c91SJohn Keeping
3945749c91SJohn Keeping static const unsigned int rates_11289[] = {
4045749c91SJohn Keeping 8018, 11025, 22050, 44100, 88200,
4145749c91SJohn Keeping };
4245749c91SJohn Keeping
4345749c91SJohn Keeping static const int ratios_11289[] = {
4445749c91SJohn Keeping 9, 7, 4, 2, 0,
4545749c91SJohn Keeping };
4645749c91SJohn Keeping
4745749c91SJohn Keeping static const struct snd_pcm_hw_constraint_list constraints_11289 = {
4845749c91SJohn Keeping .count = ARRAY_SIZE(rates_11289),
4945749c91SJohn Keeping .list = rates_11289,
50567e4f98SSean Cross };
51567e4f98SSean Cross
52567e4f98SSean Cross /* regulator supplies for sgtl5000, VDDD is an optional external supply */
53567e4f98SSean Cross enum sgtl5000_regulator_supplies {
54567e4f98SSean Cross DVDD,
55567e4f98SSean Cross AVDD,
56567e4f98SSean Cross PVDD,
57567e4f98SSean Cross HPVDD,
58567e4f98SSean Cross ES8328_SUPPLY_NUM
59567e4f98SSean Cross };
60567e4f98SSean Cross
61567e4f98SSean Cross /* vddd is optional supply */
62567e4f98SSean Cross static const char * const supply_names[ES8328_SUPPLY_NUM] = {
63567e4f98SSean Cross "DVDD",
64567e4f98SSean Cross "AVDD",
65567e4f98SSean Cross "PVDD",
66567e4f98SSean Cross "HPVDD",
67567e4f98SSean Cross };
68567e4f98SSean Cross
69404785f9SRomain Perier #define ES8328_RATES (SNDRV_PCM_RATE_192000 | \
70404785f9SRomain Perier SNDRV_PCM_RATE_96000 | \
71c7ad841eSRomain Perier SNDRV_PCM_RATE_88200 | \
72c7ad841eSRomain Perier SNDRV_PCM_RATE_8000_48000)
73779e86a3SJohn Keeping #define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
74779e86a3SJohn Keeping SNDRV_PCM_FMTBIT_S18_3LE | \
75779e86a3SJohn Keeping SNDRV_PCM_FMTBIT_S20_3LE | \
76779e86a3SJohn Keeping SNDRV_PCM_FMTBIT_S24_LE | \
77779e86a3SJohn Keeping SNDRV_PCM_FMTBIT_S32_LE)
78567e4f98SSean Cross
79567e4f98SSean Cross struct es8328_priv {
80567e4f98SSean Cross struct regmap *regmap;
81567e4f98SSean Cross struct clk *clk;
82567e4f98SSean Cross int playback_fs;
83567e4f98SSean Cross bool deemph;
8445749c91SJohn Keeping int mclkdiv2;
8545749c91SJohn Keeping const struct snd_pcm_hw_constraint_list *sysclk_constraints;
8645749c91SJohn Keeping const int *mclk_ratios;
876d260880SMark Brown bool provider;
88567e4f98SSean Cross struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM];
89567e4f98SSean Cross };
90567e4f98SSean Cross
91567e4f98SSean Cross /*
92567e4f98SSean Cross * ES8328 Controls
93567e4f98SSean Cross */
94567e4f98SSean Cross
95567e4f98SSean Cross static const char * const adcpol_txt[] = {"Normal", "L Invert", "R Invert",
96567e4f98SSean Cross "L + R Invert"};
97567e4f98SSean Cross static SOC_ENUM_SINGLE_DECL(adcpol,
98567e4f98SSean Cross ES8328_ADCCONTROL6, 6, adcpol_txt);
99567e4f98SSean Cross
100567e4f98SSean Cross static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
101567e4f98SSean Cross static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0);
102567e4f98SSean Cross static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
103567e4f98SSean Cross static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);
104567e4f98SSean Cross
10584ebac4dSJohn Keeping static const struct {
10684ebac4dSJohn Keeping int rate;
10784ebac4dSJohn Keeping unsigned int val;
10884ebac4dSJohn Keeping } deemph_settings[] = {
10984ebac4dSJohn Keeping { 0, ES8328_DACCONTROL6_DEEMPH_OFF },
11084ebac4dSJohn Keeping { 32000, ES8328_DACCONTROL6_DEEMPH_32k },
11184ebac4dSJohn Keeping { 44100, ES8328_DACCONTROL6_DEEMPH_44_1k },
11284ebac4dSJohn Keeping { 48000, ES8328_DACCONTROL6_DEEMPH_48k },
11384ebac4dSJohn Keeping };
114567e4f98SSean Cross
es8328_set_deemph(struct snd_soc_component * component)115da4ce560SKuninori Morimoto static int es8328_set_deemph(struct snd_soc_component *component)
116567e4f98SSean Cross {
117da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
118567e4f98SSean Cross int val, i, best;
119567e4f98SSean Cross
120567e4f98SSean Cross /*
121567e4f98SSean Cross * If we're using deemphasis select the nearest available sample
122567e4f98SSean Cross * rate.
123567e4f98SSean Cross */
124567e4f98SSean Cross if (es8328->deemph) {
12584ebac4dSJohn Keeping best = 0;
12684ebac4dSJohn Keeping for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) {
12784ebac4dSJohn Keeping if (abs(deemph_settings[i].rate - es8328->playback_fs) <
12884ebac4dSJohn Keeping abs(deemph_settings[best].rate - es8328->playback_fs))
129567e4f98SSean Cross best = i;
130567e4f98SSean Cross }
131567e4f98SSean Cross
13284ebac4dSJohn Keeping val = deemph_settings[best].val;
133567e4f98SSean Cross } else {
13484ebac4dSJohn Keeping val = ES8328_DACCONTROL6_DEEMPH_OFF;
135567e4f98SSean Cross }
136567e4f98SSean Cross
137da4ce560SKuninori Morimoto dev_dbg(component->dev, "Set deemphasis %d\n", val);
138567e4f98SSean Cross
139da4ce560SKuninori Morimoto return snd_soc_component_update_bits(component, ES8328_DACCONTROL6,
14084ebac4dSJohn Keeping ES8328_DACCONTROL6_DEEMPH_MASK, val);
141567e4f98SSean Cross }
142567e4f98SSean Cross
es8328_get_deemph(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)143567e4f98SSean Cross static int es8328_get_deemph(struct snd_kcontrol *kcontrol,
144567e4f98SSean Cross struct snd_ctl_elem_value *ucontrol)
145567e4f98SSean Cross {
146da4ce560SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
147da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
148567e4f98SSean Cross
149d223b0e7STakashi Iwai ucontrol->value.integer.value[0] = es8328->deemph;
150567e4f98SSean Cross return 0;
151567e4f98SSean Cross }
152567e4f98SSean Cross
es8328_put_deemph(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)153567e4f98SSean Cross static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
154567e4f98SSean Cross struct snd_ctl_elem_value *ucontrol)
155567e4f98SSean Cross {
156da4ce560SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
157da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
1587ab8a54eSDan Carpenter unsigned int deemph = ucontrol->value.integer.value[0];
159567e4f98SSean Cross int ret;
160567e4f98SSean Cross
161567e4f98SSean Cross if (deemph > 1)
162567e4f98SSean Cross return -EINVAL;
163567e4f98SSean Cross
1648259610cSMark Brown if (es8328->deemph == deemph)
1658259610cSMark Brown return 0;
1668259610cSMark Brown
167da4ce560SKuninori Morimoto ret = es8328_set_deemph(component);
168567e4f98SSean Cross if (ret < 0)
169567e4f98SSean Cross return ret;
170567e4f98SSean Cross
171567e4f98SSean Cross es8328->deemph = deemph;
172567e4f98SSean Cross
1738259610cSMark Brown return 1;
174567e4f98SSean Cross }
175567e4f98SSean Cross
176567e4f98SSean Cross
177567e4f98SSean Cross
178567e4f98SSean Cross static const struct snd_kcontrol_new es8328_snd_controls[] = {
179567e4f98SSean Cross SOC_DOUBLE_R_TLV("Capture Digital Volume",
180567e4f98SSean Cross ES8328_ADCCONTROL8, ES8328_ADCCONTROL9,
181567e4f98SSean Cross 0, 0xc0, 1, dac_adc_tlv),
182567e4f98SSean Cross SOC_SINGLE("Capture ZC Switch", ES8328_ADCCONTROL7, 6, 1, 0),
183567e4f98SSean Cross
184567e4f98SSean Cross SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,
185567e4f98SSean Cross es8328_get_deemph, es8328_put_deemph),
186567e4f98SSean Cross
187567e4f98SSean Cross SOC_ENUM("Capture Polarity", adcpol),
188567e4f98SSean Cross
189567e4f98SSean Cross SOC_SINGLE_TLV("Left Mixer Left Bypass Volume",
190567e4f98SSean Cross ES8328_DACCONTROL17, 3, 7, 1, bypass_tlv),
191567e4f98SSean Cross SOC_SINGLE_TLV("Left Mixer Right Bypass Volume",
192567e4f98SSean Cross ES8328_DACCONTROL19, 3, 7, 1, bypass_tlv),
193567e4f98SSean Cross SOC_SINGLE_TLV("Right Mixer Left Bypass Volume",
194567e4f98SSean Cross ES8328_DACCONTROL18, 3, 7, 1, bypass_tlv),
195567e4f98SSean Cross SOC_SINGLE_TLV("Right Mixer Right Bypass Volume",
196567e4f98SSean Cross ES8328_DACCONTROL20, 3, 7, 1, bypass_tlv),
197567e4f98SSean Cross
198567e4f98SSean Cross SOC_DOUBLE_R_TLV("PCM Volume",
199567e4f98SSean Cross ES8328_LDACVOL, ES8328_RDACVOL,
200567e4f98SSean Cross 0, ES8328_DACVOL_MAX, 1, dac_adc_tlv),
201567e4f98SSean Cross
202567e4f98SSean Cross SOC_DOUBLE_R_TLV("Output 1 Playback Volume",
203567e4f98SSean Cross ES8328_LOUT1VOL, ES8328_ROUT1VOL,
204567e4f98SSean Cross 0, ES8328_OUT1VOL_MAX, 0, play_tlv),
205567e4f98SSean Cross
206567e4f98SSean Cross SOC_DOUBLE_R_TLV("Output 2 Playback Volume",
207567e4f98SSean Cross ES8328_LOUT2VOL, ES8328_ROUT2VOL,
208567e4f98SSean Cross 0, ES8328_OUT2VOL_MAX, 0, play_tlv),
209567e4f98SSean Cross
210567e4f98SSean Cross SOC_DOUBLE_TLV("Mic PGA Volume", ES8328_ADCCONTROL1,
211567e4f98SSean Cross 4, 0, 8, 0, mic_tlv),
212567e4f98SSean Cross };
213567e4f98SSean Cross
214567e4f98SSean Cross /*
215567e4f98SSean Cross * DAPM Controls
216567e4f98SSean Cross */
217567e4f98SSean Cross
218567e4f98SSean Cross static const char * const es8328_line_texts[] = {
219567e4f98SSean Cross "Line 1", "Line 2", "PGA", "Differential"};
220567e4f98SSean Cross
221567e4f98SSean Cross static const struct soc_enum es8328_lline_enum =
222567e4f98SSean Cross SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 3,
223567e4f98SSean Cross ARRAY_SIZE(es8328_line_texts),
224567e4f98SSean Cross es8328_line_texts);
225567e4f98SSean Cross static const struct snd_kcontrol_new es8328_left_line_controls =
226567e4f98SSean Cross SOC_DAPM_ENUM("Route", es8328_lline_enum);
227567e4f98SSean Cross
228567e4f98SSean Cross static const struct soc_enum es8328_rline_enum =
229567e4f98SSean Cross SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 0,
230567e4f98SSean Cross ARRAY_SIZE(es8328_line_texts),
231567e4f98SSean Cross es8328_line_texts);
232567e4f98SSean Cross static const struct snd_kcontrol_new es8328_right_line_controls =
233d63887bcSYueHaibing SOC_DAPM_ENUM("Route", es8328_rline_enum);
234567e4f98SSean Cross
235567e4f98SSean Cross /* Left Mixer */
236567e4f98SSean Cross static const struct snd_kcontrol_new es8328_left_mixer_controls[] = {
237352d52e2SJohn Keeping SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 6, 1, 0),
238352d52e2SJohn Keeping SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 7, 1, 0),
239352d52e2SJohn Keeping SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 6, 1, 0),
240567e4f98SSean Cross };
241567e4f98SSean Cross
242567e4f98SSean Cross /* Right Mixer */
243567e4f98SSean Cross static const struct snd_kcontrol_new es8328_right_mixer_controls[] = {
244352d52e2SJohn Keeping SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 7, 1, 0),
245352d52e2SJohn Keeping SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 6, 1, 0),
246352d52e2SJohn Keeping SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 6, 1, 0),
247567e4f98SSean Cross };
248567e4f98SSean Cross
249567e4f98SSean Cross static const char * const es8328_pga_sel[] = {
250567e4f98SSean Cross "Line 1", "Line 2", "Line 3", "Differential"};
251567e4f98SSean Cross
252567e4f98SSean Cross /* Left PGA Mux */
253567e4f98SSean Cross static const struct soc_enum es8328_lpga_enum =
254567e4f98SSean Cross SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 6,
255567e4f98SSean Cross ARRAY_SIZE(es8328_pga_sel),
256567e4f98SSean Cross es8328_pga_sel);
257567e4f98SSean Cross static const struct snd_kcontrol_new es8328_left_pga_controls =
258567e4f98SSean Cross SOC_DAPM_ENUM("Route", es8328_lpga_enum);
259567e4f98SSean Cross
260567e4f98SSean Cross /* Right PGA Mux */
261567e4f98SSean Cross static const struct soc_enum es8328_rpga_enum =
262567e4f98SSean Cross SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 4,
263567e4f98SSean Cross ARRAY_SIZE(es8328_pga_sel),
264567e4f98SSean Cross es8328_pga_sel);
265567e4f98SSean Cross static const struct snd_kcontrol_new es8328_right_pga_controls =
266567e4f98SSean Cross SOC_DAPM_ENUM("Route", es8328_rpga_enum);
267567e4f98SSean Cross
268567e4f98SSean Cross /* Differential Mux */
269567e4f98SSean Cross static const char * const es8328_diff_sel[] = {"Line 1", "Line 2"};
270567e4f98SSean Cross static SOC_ENUM_SINGLE_DECL(diffmux,
271567e4f98SSean Cross ES8328_ADCCONTROL3, 7, es8328_diff_sel);
272567e4f98SSean Cross static const struct snd_kcontrol_new es8328_diffmux_controls =
273567e4f98SSean Cross SOC_DAPM_ENUM("Route", diffmux);
274567e4f98SSean Cross
275567e4f98SSean Cross /* Mono ADC Mux */
276567e4f98SSean Cross static const char * const es8328_mono_mux[] = {"Stereo", "Mono (Left)",
277567e4f98SSean Cross "Mono (Right)", "Digital Mono"};
278567e4f98SSean Cross static SOC_ENUM_SINGLE_DECL(monomux,
279567e4f98SSean Cross ES8328_ADCCONTROL3, 3, es8328_mono_mux);
280567e4f98SSean Cross static const struct snd_kcontrol_new es8328_monomux_controls =
281567e4f98SSean Cross SOC_DAPM_ENUM("Route", monomux);
282567e4f98SSean Cross
283567e4f98SSean Cross static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = {
284567e4f98SSean Cross SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
285567e4f98SSean Cross &es8328_diffmux_controls),
286567e4f98SSean Cross SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
287567e4f98SSean Cross &es8328_monomux_controls),
288567e4f98SSean Cross SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
289567e4f98SSean Cross &es8328_monomux_controls),
290567e4f98SSean Cross
291567e4f98SSean Cross SND_SOC_DAPM_MUX("Left PGA Mux", ES8328_ADCPOWER,
292567e4f98SSean Cross ES8328_ADCPOWER_AINL_OFF, 1,
293567e4f98SSean Cross &es8328_left_pga_controls),
294567e4f98SSean Cross SND_SOC_DAPM_MUX("Right PGA Mux", ES8328_ADCPOWER,
295567e4f98SSean Cross ES8328_ADCPOWER_AINR_OFF, 1,
296567e4f98SSean Cross &es8328_right_pga_controls),
297567e4f98SSean Cross
298567e4f98SSean Cross SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
299567e4f98SSean Cross &es8328_left_line_controls),
300567e4f98SSean Cross SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
301567e4f98SSean Cross &es8328_right_line_controls),
302567e4f98SSean Cross
303567e4f98SSean Cross SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ES8328_ADCPOWER,
304567e4f98SSean Cross ES8328_ADCPOWER_ADCR_OFF, 1),
305567e4f98SSean Cross SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8328_ADCPOWER,
306567e4f98SSean Cross ES8328_ADCPOWER_ADCL_OFF, 1),
307567e4f98SSean Cross
308567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("Mic Bias", ES8328_ADCPOWER,
309567e4f98SSean Cross ES8328_ADCPOWER_MIC_BIAS_OFF, 1, NULL, 0),
310567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("Mic Bias Gen", ES8328_ADCPOWER,
311567e4f98SSean Cross ES8328_ADCPOWER_ADC_BIAS_GEN_OFF, 1, NULL, 0),
312567e4f98SSean Cross
313567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("DAC STM", ES8328_CHIPPOWER,
314567e4f98SSean Cross ES8328_CHIPPOWER_DACSTM_RESET, 1, NULL, 0),
315567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("ADC STM", ES8328_CHIPPOWER,
316567e4f98SSean Cross ES8328_CHIPPOWER_ADCSTM_RESET, 1, NULL, 0),
317567e4f98SSean Cross
318567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("DAC DIG", ES8328_CHIPPOWER,
319567e4f98SSean Cross ES8328_CHIPPOWER_DACDIG_OFF, 1, NULL, 0),
320567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("ADC DIG", ES8328_CHIPPOWER,
321567e4f98SSean Cross ES8328_CHIPPOWER_ADCDIG_OFF, 1, NULL, 0),
322567e4f98SSean Cross
323567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("DAC DLL", ES8328_CHIPPOWER,
324567e4f98SSean Cross ES8328_CHIPPOWER_DACDLL_OFF, 1, NULL, 0),
325567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("ADC DLL", ES8328_CHIPPOWER,
326567e4f98SSean Cross ES8328_CHIPPOWER_ADCDLL_OFF, 1, NULL, 0),
327567e4f98SSean Cross
328567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("ADC Vref", ES8328_CHIPPOWER,
329567e4f98SSean Cross ES8328_CHIPPOWER_ADCVREF_OFF, 1, NULL, 0),
330567e4f98SSean Cross SND_SOC_DAPM_SUPPLY("DAC Vref", ES8328_CHIPPOWER,
331567e4f98SSean Cross ES8328_CHIPPOWER_DACVREF_OFF, 1, NULL, 0),
332567e4f98SSean Cross
333567e4f98SSean Cross SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8328_DACPOWER,
334567e4f98SSean Cross ES8328_DACPOWER_RDAC_OFF, 1),
335567e4f98SSean Cross SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER,
336567e4f98SSean Cross ES8328_DACPOWER_LDAC_OFF, 1),
337567e4f98SSean Cross
338*53cdb4c3SNicolas Frattaroli SND_SOC_DAPM_MIXER("Left Mixer", ES8328_DACCONTROL17, 7, 0,
339567e4f98SSean Cross &es8328_left_mixer_controls[0],
340567e4f98SSean Cross ARRAY_SIZE(es8328_left_mixer_controls)),
341*53cdb4c3SNicolas Frattaroli SND_SOC_DAPM_MIXER("Right Mixer", ES8328_DACCONTROL20, 7, 0,
342567e4f98SSean Cross &es8328_right_mixer_controls[0],
343567e4f98SSean Cross ARRAY_SIZE(es8328_right_mixer_controls)),
344567e4f98SSean Cross
345567e4f98SSean Cross SND_SOC_DAPM_PGA("Right Out 2", ES8328_DACPOWER,
346567e4f98SSean Cross ES8328_DACPOWER_ROUT2_ON, 0, NULL, 0),
347567e4f98SSean Cross SND_SOC_DAPM_PGA("Left Out 2", ES8328_DACPOWER,
348567e4f98SSean Cross ES8328_DACPOWER_LOUT2_ON, 0, NULL, 0),
349567e4f98SSean Cross SND_SOC_DAPM_PGA("Right Out 1", ES8328_DACPOWER,
350567e4f98SSean Cross ES8328_DACPOWER_ROUT1_ON, 0, NULL, 0),
351567e4f98SSean Cross SND_SOC_DAPM_PGA("Left Out 1", ES8328_DACPOWER,
352567e4f98SSean Cross ES8328_DACPOWER_LOUT1_ON, 0, NULL, 0),
353567e4f98SSean Cross
354567e4f98SSean Cross SND_SOC_DAPM_OUTPUT("LOUT1"),
355567e4f98SSean Cross SND_SOC_DAPM_OUTPUT("ROUT1"),
356567e4f98SSean Cross SND_SOC_DAPM_OUTPUT("LOUT2"),
357567e4f98SSean Cross SND_SOC_DAPM_OUTPUT("ROUT2"),
358567e4f98SSean Cross
359567e4f98SSean Cross SND_SOC_DAPM_INPUT("LINPUT1"),
360567e4f98SSean Cross SND_SOC_DAPM_INPUT("LINPUT2"),
361567e4f98SSean Cross SND_SOC_DAPM_INPUT("RINPUT1"),
362567e4f98SSean Cross SND_SOC_DAPM_INPUT("RINPUT2"),
363567e4f98SSean Cross };
364567e4f98SSean Cross
365567e4f98SSean Cross static const struct snd_soc_dapm_route es8328_dapm_routes[] = {
366567e4f98SSean Cross
367567e4f98SSean Cross { "Left Line Mux", "Line 1", "LINPUT1" },
368567e4f98SSean Cross { "Left Line Mux", "Line 2", "LINPUT2" },
369567e4f98SSean Cross { "Left Line Mux", "PGA", "Left PGA Mux" },
370567e4f98SSean Cross { "Left Line Mux", "Differential", "Differential Mux" },
371567e4f98SSean Cross
372567e4f98SSean Cross { "Right Line Mux", "Line 1", "RINPUT1" },
373567e4f98SSean Cross { "Right Line Mux", "Line 2", "RINPUT2" },
374567e4f98SSean Cross { "Right Line Mux", "PGA", "Right PGA Mux" },
375567e4f98SSean Cross { "Right Line Mux", "Differential", "Differential Mux" },
376567e4f98SSean Cross
377567e4f98SSean Cross { "Left PGA Mux", "Line 1", "LINPUT1" },
378567e4f98SSean Cross { "Left PGA Mux", "Line 2", "LINPUT2" },
379567e4f98SSean Cross { "Left PGA Mux", "Differential", "Differential Mux" },
380567e4f98SSean Cross
381567e4f98SSean Cross { "Right PGA Mux", "Line 1", "RINPUT1" },
382567e4f98SSean Cross { "Right PGA Mux", "Line 2", "RINPUT2" },
383567e4f98SSean Cross { "Right PGA Mux", "Differential", "Differential Mux" },
384567e4f98SSean Cross
385567e4f98SSean Cross { "Differential Mux", "Line 1", "LINPUT1" },
386567e4f98SSean Cross { "Differential Mux", "Line 1", "RINPUT1" },
387567e4f98SSean Cross { "Differential Mux", "Line 2", "LINPUT2" },
388567e4f98SSean Cross { "Differential Mux", "Line 2", "RINPUT2" },
389567e4f98SSean Cross
390567e4f98SSean Cross { "Left ADC Mux", "Stereo", "Left PGA Mux" },
391567e4f98SSean Cross { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
392567e4f98SSean Cross { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },
393567e4f98SSean Cross
394567e4f98SSean Cross { "Right ADC Mux", "Stereo", "Right PGA Mux" },
395567e4f98SSean Cross { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },
396567e4f98SSean Cross { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },
397567e4f98SSean Cross
398567e4f98SSean Cross { "Left ADC", NULL, "Left ADC Mux" },
399567e4f98SSean Cross { "Right ADC", NULL, "Right ADC Mux" },
400567e4f98SSean Cross
401567e4f98SSean Cross { "ADC DIG", NULL, "ADC STM" },
402567e4f98SSean Cross { "ADC DIG", NULL, "ADC Vref" },
403567e4f98SSean Cross { "ADC DIG", NULL, "ADC DLL" },
404567e4f98SSean Cross
405567e4f98SSean Cross { "Left ADC", NULL, "ADC DIG" },
406567e4f98SSean Cross { "Right ADC", NULL, "ADC DIG" },
407567e4f98SSean Cross
408567e4f98SSean Cross { "Mic Bias", NULL, "Mic Bias Gen" },
409567e4f98SSean Cross
410567e4f98SSean Cross { "Left Line Mux", "Line 1", "LINPUT1" },
411567e4f98SSean Cross { "Left Line Mux", "Line 2", "LINPUT2" },
412567e4f98SSean Cross { "Left Line Mux", "PGA", "Left PGA Mux" },
413567e4f98SSean Cross { "Left Line Mux", "Differential", "Differential Mux" },
414567e4f98SSean Cross
415567e4f98SSean Cross { "Right Line Mux", "Line 1", "RINPUT1" },
416567e4f98SSean Cross { "Right Line Mux", "Line 2", "RINPUT2" },
417567e4f98SSean Cross { "Right Line Mux", "PGA", "Right PGA Mux" },
418567e4f98SSean Cross { "Right Line Mux", "Differential", "Differential Mux" },
419567e4f98SSean Cross
420*53cdb4c3SNicolas Frattaroli { "Left Mixer", NULL, "Left DAC" },
421567e4f98SSean Cross { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
422567e4f98SSean Cross { "Left Mixer", "Right Playback Switch", "Right DAC" },
423567e4f98SSean Cross { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
424567e4f98SSean Cross
425567e4f98SSean Cross { "Right Mixer", "Left Playback Switch", "Left DAC" },
426567e4f98SSean Cross { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
427*53cdb4c3SNicolas Frattaroli { "Right Mixer", NULL, "Right DAC" },
428567e4f98SSean Cross { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
429567e4f98SSean Cross
430567e4f98SSean Cross { "DAC DIG", NULL, "DAC STM" },
431567e4f98SSean Cross { "DAC DIG", NULL, "DAC Vref" },
432567e4f98SSean Cross { "DAC DIG", NULL, "DAC DLL" },
433567e4f98SSean Cross
434567e4f98SSean Cross { "Left DAC", NULL, "DAC DIG" },
435567e4f98SSean Cross { "Right DAC", NULL, "DAC DIG" },
436567e4f98SSean Cross
437567e4f98SSean Cross { "Left Out 1", NULL, "Left Mixer" },
438567e4f98SSean Cross { "LOUT1", NULL, "Left Out 1" },
439567e4f98SSean Cross { "Right Out 1", NULL, "Right Mixer" },
440567e4f98SSean Cross { "ROUT1", NULL, "Right Out 1" },
441567e4f98SSean Cross
442567e4f98SSean Cross { "Left Out 2", NULL, "Left Mixer" },
443567e4f98SSean Cross { "LOUT2", NULL, "Left Out 2" },
444567e4f98SSean Cross { "Right Out 2", NULL, "Right Mixer" },
445567e4f98SSean Cross { "ROUT2", NULL, "Right Out 2" },
446567e4f98SSean Cross };
447567e4f98SSean Cross
es8328_mute(struct snd_soc_dai * dai,int mute,int direction)4488667d948SKuninori Morimoto static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction)
449567e4f98SSean Cross {
450da4ce560SKuninori Morimoto return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3,
451567e4f98SSean Cross ES8328_DACCONTROL3_DACMUTE,
452567e4f98SSean Cross mute ? ES8328_DACCONTROL3_DACMUTE : 0);
453567e4f98SSean Cross }
454567e4f98SSean Cross
es8328_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)45545749c91SJohn Keeping static int es8328_startup(struct snd_pcm_substream *substream,
45645749c91SJohn Keeping struct snd_soc_dai *dai)
45745749c91SJohn Keeping {
458da4ce560SKuninori Morimoto struct snd_soc_component *component = dai->component;
459da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
46045749c91SJohn Keeping
4616d260880SMark Brown if (es8328->provider && es8328->sysclk_constraints)
46245749c91SJohn Keeping snd_pcm_hw_constraint_list(substream->runtime, 0,
46345749c91SJohn Keeping SNDRV_PCM_HW_PARAM_RATE,
46445749c91SJohn Keeping es8328->sysclk_constraints);
46545749c91SJohn Keeping
46645749c91SJohn Keeping return 0;
46745749c91SJohn Keeping }
46845749c91SJohn Keeping
es8328_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)469567e4f98SSean Cross static int es8328_hw_params(struct snd_pcm_substream *substream,
470567e4f98SSean Cross struct snd_pcm_hw_params *params,
471567e4f98SSean Cross struct snd_soc_dai *dai)
472567e4f98SSean Cross {
473da4ce560SKuninori Morimoto struct snd_soc_component *component = dai->component;
474da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
475567e4f98SSean Cross int i;
476567e4f98SSean Cross int reg;
477779e86a3SJohn Keeping int wl;
47845749c91SJohn Keeping int ratio;
47945749c91SJohn Keeping
480567e4f98SSean Cross if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
481567e4f98SSean Cross reg = ES8328_DACCONTROL2;
482567e4f98SSean Cross else
483567e4f98SSean Cross reg = ES8328_ADCCONTROL5;
484567e4f98SSean Cross
4856d260880SMark Brown if (es8328->provider) {
486ae884ae7SRomain Perier if (!es8328->sysclk_constraints) {
487da4ce560SKuninori Morimoto dev_err(component->dev, "No MCLK configured\n");
488567e4f98SSean Cross return -EINVAL;
489567e4f98SSean Cross }
49045749c91SJohn Keeping
491ae884ae7SRomain Perier for (i = 0; i < es8328->sysclk_constraints->count; i++)
492ae884ae7SRomain Perier if (es8328->sysclk_constraints->list[i] ==
493ae884ae7SRomain Perier params_rate(params))
494ae884ae7SRomain Perier break;
495ae884ae7SRomain Perier
496ae884ae7SRomain Perier if (i == es8328->sysclk_constraints->count) {
497da4ce560SKuninori Morimoto dev_err(component->dev,
498ae884ae7SRomain Perier "LRCLK %d unsupported with current clock\n",
499ae884ae7SRomain Perier params_rate(params));
500ae884ae7SRomain Perier return -EINVAL;
501ae884ae7SRomain Perier }
50245749c91SJohn Keeping ratio = es8328->mclk_ratios[i];
503ae884ae7SRomain Perier } else {
504ae884ae7SRomain Perier ratio = 0;
505ae884ae7SRomain Perier es8328->mclkdiv2 = 0;
506ae884ae7SRomain Perier }
507ae884ae7SRomain Perier
508da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_MASTERMODE,
50945749c91SJohn Keeping ES8328_MASTERMODE_MCLKDIV2,
51045749c91SJohn Keeping es8328->mclkdiv2 ? ES8328_MASTERMODE_MCLKDIV2 : 0);
511779e86a3SJohn Keeping
512779e86a3SJohn Keeping switch (params_width(params)) {
513779e86a3SJohn Keeping case 16:
514779e86a3SJohn Keeping wl = 3;
515779e86a3SJohn Keeping break;
516779e86a3SJohn Keeping case 18:
517779e86a3SJohn Keeping wl = 2;
518779e86a3SJohn Keeping break;
519779e86a3SJohn Keeping case 20:
520779e86a3SJohn Keeping wl = 1;
521779e86a3SJohn Keeping break;
522779e86a3SJohn Keeping case 24:
523779e86a3SJohn Keeping wl = 0;
524779e86a3SJohn Keeping break;
525779e86a3SJohn Keeping case 32:
526779e86a3SJohn Keeping wl = 4;
527779e86a3SJohn Keeping break;
528779e86a3SJohn Keeping default:
529779e86a3SJohn Keeping return -EINVAL;
530779e86a3SJohn Keeping }
531567e4f98SSean Cross
532567e4f98SSean Cross if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
533da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_DACCONTROL1,
5348865c95eSJohn Keeping ES8328_DACCONTROL1_DACWL_MASK,
535779e86a3SJohn Keeping wl << ES8328_DACCONTROL1_DACWL_SHIFT);
5368865c95eSJohn Keeping
537567e4f98SSean Cross es8328->playback_fs = params_rate(params);
538da4ce560SKuninori Morimoto es8328_set_deemph(component);
5398865c95eSJohn Keeping } else
540da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,
5418865c95eSJohn Keeping ES8328_ADCCONTROL4_ADCWL_MASK,
542779e86a3SJohn Keeping wl << ES8328_ADCCONTROL4_ADCWL_SHIFT);
543567e4f98SSean Cross
544da4ce560SKuninori Morimoto return snd_soc_component_update_bits(component, reg, ES8328_RATEMASK, ratio);
545567e4f98SSean Cross }
546567e4f98SSean Cross
es8328_set_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)54745749c91SJohn Keeping static int es8328_set_sysclk(struct snd_soc_dai *codec_dai,
54845749c91SJohn Keeping int clk_id, unsigned int freq, int dir)
54945749c91SJohn Keeping {
550da4ce560SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
551da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
55245749c91SJohn Keeping int mclkdiv2 = 0;
55345749c91SJohn Keeping
55445749c91SJohn Keeping switch (freq) {
55545749c91SJohn Keeping case 0:
55645749c91SJohn Keeping es8328->sysclk_constraints = NULL;
55745749c91SJohn Keeping es8328->mclk_ratios = NULL;
55845749c91SJohn Keeping break;
55945749c91SJohn Keeping case 22579200:
56045749c91SJohn Keeping mclkdiv2 = 1;
5613e146b55SGustavo A. R. Silva fallthrough;
56245749c91SJohn Keeping case 11289600:
56345749c91SJohn Keeping es8328->sysclk_constraints = &constraints_11289;
56445749c91SJohn Keeping es8328->mclk_ratios = ratios_11289;
56545749c91SJohn Keeping break;
56645749c91SJohn Keeping case 24576000:
56745749c91SJohn Keeping mclkdiv2 = 1;
5683e146b55SGustavo A. R. Silva fallthrough;
56945749c91SJohn Keeping case 12288000:
57045749c91SJohn Keeping es8328->sysclk_constraints = &constraints_12288;
57145749c91SJohn Keeping es8328->mclk_ratios = ratios_12288;
57245749c91SJohn Keeping break;
57345749c91SJohn Keeping default:
57445749c91SJohn Keeping return -EINVAL;
57545749c91SJohn Keeping }
57645749c91SJohn Keeping
57745749c91SJohn Keeping es8328->mclkdiv2 = mclkdiv2;
57845749c91SJohn Keeping return 0;
57945749c91SJohn Keeping }
58045749c91SJohn Keeping
es8328_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)581567e4f98SSean Cross static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
582567e4f98SSean Cross unsigned int fmt)
583567e4f98SSean Cross {
584da4ce560SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
585da4ce560SKuninori Morimoto struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
5868865c95eSJohn Keeping u8 dac_mode = 0;
5878865c95eSJohn Keeping u8 adc_mode = 0;
588567e4f98SSean Cross
5896d260880SMark Brown switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
5906d260880SMark Brown case SND_SOC_DAIFMT_CBP_CFP:
591b9b044e2SRomain Perier /* Master serial port mode, with BCLK generated automatically */
592da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_MASTERMODE,
593b9b044e2SRomain Perier ES8328_MASTERMODE_MSC,
594b9b044e2SRomain Perier ES8328_MASTERMODE_MSC);
5956d260880SMark Brown es8328->provider = true;
596b9b044e2SRomain Perier break;
5976d260880SMark Brown case SND_SOC_DAIFMT_CBC_CFC:
598b9b044e2SRomain Perier /* Slave serial port mode */
599da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_MASTERMODE,
600b9b044e2SRomain Perier ES8328_MASTERMODE_MSC, 0);
6016d260880SMark Brown es8328->provider = false;
602b9b044e2SRomain Perier break;
603b9b044e2SRomain Perier default:
604567e4f98SSean Cross return -EINVAL;
605b9b044e2SRomain Perier }
606567e4f98SSean Cross
607567e4f98SSean Cross /* interface format */
608567e4f98SSean Cross switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
609567e4f98SSean Cross case SND_SOC_DAIFMT_I2S:
61057e41f3fSJohn Keeping dac_mode |= ES8328_DACCONTROL1_DACFORMAT_I2S;
61157e41f3fSJohn Keeping adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_I2S;
612567e4f98SSean Cross break;
613567e4f98SSean Cross case SND_SOC_DAIFMT_RIGHT_J:
61457e41f3fSJohn Keeping dac_mode |= ES8328_DACCONTROL1_DACFORMAT_RJUST;
61557e41f3fSJohn Keeping adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_RJUST;
616567e4f98SSean Cross break;
617567e4f98SSean Cross case SND_SOC_DAIFMT_LEFT_J:
61857e41f3fSJohn Keeping dac_mode |= ES8328_DACCONTROL1_DACFORMAT_LJUST;
61957e41f3fSJohn Keeping adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_LJUST;
620567e4f98SSean Cross break;
621567e4f98SSean Cross default:
622567e4f98SSean Cross return -EINVAL;
623567e4f98SSean Cross }
624567e4f98SSean Cross
625567e4f98SSean Cross /* clock inversion */
626567e4f98SSean Cross if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
627567e4f98SSean Cross return -EINVAL;
628567e4f98SSean Cross
629da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_DACCONTROL1,
6308865c95eSJohn Keeping ES8328_DACCONTROL1_DACFORMAT_MASK, dac_mode);
631da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,
6328865c95eSJohn Keeping ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode);
633567e4f98SSean Cross
634567e4f98SSean Cross return 0;
635567e4f98SSean Cross }
636567e4f98SSean Cross
es8328_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)637da4ce560SKuninori Morimoto static int es8328_set_bias_level(struct snd_soc_component *component,
638567e4f98SSean Cross enum snd_soc_bias_level level)
639567e4f98SSean Cross {
640567e4f98SSean Cross switch (level) {
641567e4f98SSean Cross case SND_SOC_BIAS_ON:
642567e4f98SSean Cross break;
643567e4f98SSean Cross
644567e4f98SSean Cross case SND_SOC_BIAS_PREPARE:
645567e4f98SSean Cross /* VREF, VMID=2x50k, digital enabled */
646da4ce560SKuninori Morimoto snd_soc_component_write(component, ES8328_CHIPPOWER, 0);
647da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_CONTROL1,
648567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_MASK |
649567e4f98SSean Cross ES8328_CONTROL1_ENREF,
650567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_50k |
651567e4f98SSean Cross ES8328_CONTROL1_ENREF);
652567e4f98SSean Cross break;
653567e4f98SSean Cross
654567e4f98SSean Cross case SND_SOC_BIAS_STANDBY:
655da4ce560SKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
656da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_CONTROL1,
657567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_MASK |
658567e4f98SSean Cross ES8328_CONTROL1_ENREF,
659567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_5k |
660567e4f98SSean Cross ES8328_CONTROL1_ENREF);
661567e4f98SSean Cross
662567e4f98SSean Cross /* Charge caps */
663567e4f98SSean Cross msleep(100);
664567e4f98SSean Cross }
665567e4f98SSean Cross
666da4ce560SKuninori Morimoto snd_soc_component_write(component, ES8328_CONTROL2,
667567e4f98SSean Cross ES8328_CONTROL2_OVERCURRENT_ON |
668567e4f98SSean Cross ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);
669567e4f98SSean Cross
670567e4f98SSean Cross /* VREF, VMID=2*500k, digital stopped */
671da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_CONTROL1,
672567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_MASK |
673567e4f98SSean Cross ES8328_CONTROL1_ENREF,
674567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_500k |
675567e4f98SSean Cross ES8328_CONTROL1_ENREF);
676567e4f98SSean Cross break;
677567e4f98SSean Cross
678567e4f98SSean Cross case SND_SOC_BIAS_OFF:
679da4ce560SKuninori Morimoto snd_soc_component_update_bits(component, ES8328_CONTROL1,
680567e4f98SSean Cross ES8328_CONTROL1_VMIDSEL_MASK |
681567e4f98SSean Cross ES8328_CONTROL1_ENREF,
682567e4f98SSean Cross 0);
683567e4f98SSean Cross break;
684567e4f98SSean Cross }
685567e4f98SSean Cross return 0;
686567e4f98SSean Cross }
687567e4f98SSean Cross
688567e4f98SSean Cross static const struct snd_soc_dai_ops es8328_dai_ops = {
68945749c91SJohn Keeping .startup = es8328_startup,
690567e4f98SSean Cross .hw_params = es8328_hw_params,
6918667d948SKuninori Morimoto .mute_stream = es8328_mute,
69245749c91SJohn Keeping .set_sysclk = es8328_set_sysclk,
693567e4f98SSean Cross .set_fmt = es8328_set_dai_fmt,
6948667d948SKuninori Morimoto .no_capture_mute = 1,
695567e4f98SSean Cross };
696567e4f98SSean Cross
697567e4f98SSean Cross static struct snd_soc_dai_driver es8328_dai = {
698567e4f98SSean Cross .name = "es8328-hifi-analog",
699567e4f98SSean Cross .playback = {
700567e4f98SSean Cross .stream_name = "Playback",
701567e4f98SSean Cross .channels_min = 2,
702567e4f98SSean Cross .channels_max = 2,
703567e4f98SSean Cross .rates = ES8328_RATES,
704567e4f98SSean Cross .formats = ES8328_FORMATS,
705567e4f98SSean Cross },
706567e4f98SSean Cross .capture = {
707567e4f98SSean Cross .stream_name = "Capture",
708567e4f98SSean Cross .channels_min = 2,
709567e4f98SSean Cross .channels_max = 2,
710567e4f98SSean Cross .rates = ES8328_RATES,
711567e4f98SSean Cross .formats = ES8328_FORMATS,
712567e4f98SSean Cross },
713567e4f98SSean Cross .ops = &es8328_dai_ops,
7144060064eSKuninori Morimoto .symmetric_rate = 1,
715567e4f98SSean Cross };
716567e4f98SSean Cross
es8328_suspend(struct snd_soc_component * component)717da4ce560SKuninori Morimoto static int es8328_suspend(struct snd_soc_component *component)
718567e4f98SSean Cross {
719567e4f98SSean Cross struct es8328_priv *es8328;
720567e4f98SSean Cross int ret;
721567e4f98SSean Cross
722da4ce560SKuninori Morimoto es8328 = snd_soc_component_get_drvdata(component);
723567e4f98SSean Cross
724567e4f98SSean Cross clk_disable_unprepare(es8328->clk);
725567e4f98SSean Cross
726567e4f98SSean Cross ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
727567e4f98SSean Cross es8328->supplies);
728567e4f98SSean Cross if (ret) {
729da4ce560SKuninori Morimoto dev_err(component->dev, "unable to disable regulators\n");
730567e4f98SSean Cross return ret;
731567e4f98SSean Cross }
732567e4f98SSean Cross return 0;
733567e4f98SSean Cross }
734567e4f98SSean Cross
es8328_resume(struct snd_soc_component * component)735da4ce560SKuninori Morimoto static int es8328_resume(struct snd_soc_component *component)
736567e4f98SSean Cross {
737da4ce560SKuninori Morimoto struct regmap *regmap = dev_get_regmap(component->dev, NULL);
738567e4f98SSean Cross struct es8328_priv *es8328;
739567e4f98SSean Cross int ret;
740567e4f98SSean Cross
741da4ce560SKuninori Morimoto es8328 = snd_soc_component_get_drvdata(component);
742567e4f98SSean Cross
743567e4f98SSean Cross ret = clk_prepare_enable(es8328->clk);
744567e4f98SSean Cross if (ret) {
745da4ce560SKuninori Morimoto dev_err(component->dev, "unable to enable clock\n");
746567e4f98SSean Cross return ret;
747567e4f98SSean Cross }
748567e4f98SSean Cross
749567e4f98SSean Cross ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies),
750567e4f98SSean Cross es8328->supplies);
751567e4f98SSean Cross if (ret) {
752da4ce560SKuninori Morimoto dev_err(component->dev, "unable to enable regulators\n");
753567e4f98SSean Cross return ret;
754567e4f98SSean Cross }
755567e4f98SSean Cross
756567e4f98SSean Cross regcache_mark_dirty(regmap);
757567e4f98SSean Cross ret = regcache_sync(regmap);
758567e4f98SSean Cross if (ret) {
759da4ce560SKuninori Morimoto dev_err(component->dev, "unable to sync regcache\n");
760567e4f98SSean Cross return ret;
761567e4f98SSean Cross }
762567e4f98SSean Cross
763567e4f98SSean Cross return 0;
764567e4f98SSean Cross }
765567e4f98SSean Cross
es8328_component_probe(struct snd_soc_component * component)766da4ce560SKuninori Morimoto static int es8328_component_probe(struct snd_soc_component *component)
767567e4f98SSean Cross {
768567e4f98SSean Cross struct es8328_priv *es8328;
769567e4f98SSean Cross int ret;
770567e4f98SSean Cross
771da4ce560SKuninori Morimoto es8328 = snd_soc_component_get_drvdata(component);
772567e4f98SSean Cross
773567e4f98SSean Cross ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies),
774567e4f98SSean Cross es8328->supplies);
775567e4f98SSean Cross if (ret) {
776da4ce560SKuninori Morimoto dev_err(component->dev, "unable to enable regulators\n");
777567e4f98SSean Cross return ret;
778567e4f98SSean Cross }
779567e4f98SSean Cross
780567e4f98SSean Cross /* Setup clocks */
781da4ce560SKuninori Morimoto es8328->clk = devm_clk_get(component->dev, NULL);
782567e4f98SSean Cross if (IS_ERR(es8328->clk)) {
783da4ce560SKuninori Morimoto dev_err(component->dev, "codec clock missing or invalid\n");
78475c3daaaSWei Yongjun ret = PTR_ERR(es8328->clk);
785567e4f98SSean Cross goto clk_fail;
786567e4f98SSean Cross }
787567e4f98SSean Cross
788567e4f98SSean Cross ret = clk_prepare_enable(es8328->clk);
789567e4f98SSean Cross if (ret) {
790da4ce560SKuninori Morimoto dev_err(component->dev, "unable to prepare codec clk\n");
791567e4f98SSean Cross goto clk_fail;
792567e4f98SSean Cross }
793567e4f98SSean Cross
794567e4f98SSean Cross return 0;
795567e4f98SSean Cross
796567e4f98SSean Cross clk_fail:
797567e4f98SSean Cross regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
798567e4f98SSean Cross es8328->supplies);
799567e4f98SSean Cross return ret;
800567e4f98SSean Cross }
801567e4f98SSean Cross
es8328_remove(struct snd_soc_component * component)802da4ce560SKuninori Morimoto static void es8328_remove(struct snd_soc_component *component)
803567e4f98SSean Cross {
804567e4f98SSean Cross struct es8328_priv *es8328;
805567e4f98SSean Cross
806da4ce560SKuninori Morimoto es8328 = snd_soc_component_get_drvdata(component);
807567e4f98SSean Cross
808567e4f98SSean Cross clk_disable_unprepare(es8328->clk);
809567e4f98SSean Cross
810567e4f98SSean Cross regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
811567e4f98SSean Cross es8328->supplies);
812567e4f98SSean Cross }
813567e4f98SSean Cross
814567e4f98SSean Cross const struct regmap_config es8328_regmap_config = {
815567e4f98SSean Cross .reg_bits = 8,
816567e4f98SSean Cross .val_bits = 8,
817567e4f98SSean Cross .max_register = ES8328_REG_MAX,
8189321015aSMark Brown .cache_type = REGCACHE_MAPLE,
8191c96a2f6SDavid Frey .use_single_read = true,
8201c96a2f6SDavid Frey .use_single_write = true,
821567e4f98SSean Cross };
822567e4f98SSean Cross EXPORT_SYMBOL_GPL(es8328_regmap_config);
823567e4f98SSean Cross
824da4ce560SKuninori Morimoto static const struct snd_soc_component_driver es8328_component_driver = {
825da4ce560SKuninori Morimoto .probe = es8328_component_probe,
826da4ce560SKuninori Morimoto .remove = es8328_remove,
827567e4f98SSean Cross .suspend = es8328_suspend,
828567e4f98SSean Cross .resume = es8328_resume,
829567e4f98SSean Cross .set_bias_level = es8328_set_bias_level,
830567e4f98SSean Cross .controls = es8328_snd_controls,
831567e4f98SSean Cross .num_controls = ARRAY_SIZE(es8328_snd_controls),
832567e4f98SSean Cross .dapm_widgets = es8328_dapm_widgets,
833567e4f98SSean Cross .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets),
834567e4f98SSean Cross .dapm_routes = es8328_dapm_routes,
835567e4f98SSean Cross .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes),
836da4ce560SKuninori Morimoto .suspend_bias_off = 1,
837da4ce560SKuninori Morimoto .idle_bias_on = 1,
838da4ce560SKuninori Morimoto .use_pmdown_time = 1,
839da4ce560SKuninori Morimoto .endianness = 1,
840567e4f98SSean Cross };
841567e4f98SSean Cross
es8328_probe(struct device * dev,struct regmap * regmap)842567e4f98SSean Cross int es8328_probe(struct device *dev, struct regmap *regmap)
843567e4f98SSean Cross {
844567e4f98SSean Cross struct es8328_priv *es8328;
845567e4f98SSean Cross int ret;
846567e4f98SSean Cross int i;
847567e4f98SSean Cross
848567e4f98SSean Cross if (IS_ERR(regmap))
849567e4f98SSean Cross return PTR_ERR(regmap);
850567e4f98SSean Cross
851567e4f98SSean Cross es8328 = devm_kzalloc(dev, sizeof(*es8328), GFP_KERNEL);
852567e4f98SSean Cross if (es8328 == NULL)
853567e4f98SSean Cross return -ENOMEM;
854567e4f98SSean Cross
855567e4f98SSean Cross es8328->regmap = regmap;
856567e4f98SSean Cross
857567e4f98SSean Cross for (i = 0; i < ARRAY_SIZE(es8328->supplies); i++)
858567e4f98SSean Cross es8328->supplies[i].supply = supply_names[i];
859567e4f98SSean Cross
860567e4f98SSean Cross ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(es8328->supplies),
861567e4f98SSean Cross es8328->supplies);
862567e4f98SSean Cross if (ret) {
863567e4f98SSean Cross dev_err(dev, "unable to get regulators\n");
864567e4f98SSean Cross return ret;
865567e4f98SSean Cross }
866567e4f98SSean Cross
867567e4f98SSean Cross dev_set_drvdata(dev, es8328);
868567e4f98SSean Cross
869da4ce560SKuninori Morimoto return devm_snd_soc_register_component(dev,
870da4ce560SKuninori Morimoto &es8328_component_driver, &es8328_dai, 1);
871567e4f98SSean Cross }
872567e4f98SSean Cross EXPORT_SYMBOL_GPL(es8328_probe);
873567e4f98SSean Cross
874567e4f98SSean Cross MODULE_DESCRIPTION("ASoC ES8328 driver");
875567e4f98SSean Cross MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
876567e4f98SSean Cross MODULE_LICENSE("GPL");
877