1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for the PCM512x CODECs
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Author: Mark Brown <broonie@kernel.org>
6*4882a593Smuzhiyun * Copyright 2014 Linaro Ltd
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/clk.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/pm_runtime.h>
15*4882a593Smuzhiyun #include <linux/regmap.h>
16*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
17*4882a593Smuzhiyun #include <linux/gcd.h>
18*4882a593Smuzhiyun #include <sound/soc.h>
19*4882a593Smuzhiyun #include <sound/soc-dapm.h>
20*4882a593Smuzhiyun #include <sound/pcm_params.h>
21*4882a593Smuzhiyun #include <sound/tlv.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "pcm512x.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define PCM512x_NUM_SUPPLIES 3
26*4882a593Smuzhiyun static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
27*4882a593Smuzhiyun "AVDD",
28*4882a593Smuzhiyun "DVDD",
29*4882a593Smuzhiyun "CPVDD",
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun struct pcm512x_priv {
33*4882a593Smuzhiyun struct regmap *regmap;
34*4882a593Smuzhiyun struct clk *sclk;
35*4882a593Smuzhiyun struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
36*4882a593Smuzhiyun struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
37*4882a593Smuzhiyun int fmt;
38*4882a593Smuzhiyun int pll_in;
39*4882a593Smuzhiyun int pll_out;
40*4882a593Smuzhiyun int pll_r;
41*4882a593Smuzhiyun int pll_j;
42*4882a593Smuzhiyun int pll_d;
43*4882a593Smuzhiyun int pll_p;
44*4882a593Smuzhiyun unsigned long real_pll;
45*4882a593Smuzhiyun unsigned long overclock_pll;
46*4882a593Smuzhiyun unsigned long overclock_dac;
47*4882a593Smuzhiyun unsigned long overclock_dsp;
48*4882a593Smuzhiyun int mute;
49*4882a593Smuzhiyun struct mutex mutex;
50*4882a593Smuzhiyun unsigned int bclk_ratio;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /*
54*4882a593Smuzhiyun * We can't use the same notifier block for more than one supply and
55*4882a593Smuzhiyun * there's no way I can see to get from a callback to the caller
56*4882a593Smuzhiyun * except container_of().
57*4882a593Smuzhiyun */
58*4882a593Smuzhiyun #define PCM512x_REGULATOR_EVENT(n) \
59*4882a593Smuzhiyun static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
60*4882a593Smuzhiyun unsigned long event, void *data) \
61*4882a593Smuzhiyun { \
62*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
63*4882a593Smuzhiyun supply_nb[n]); \
64*4882a593Smuzhiyun if (event & REGULATOR_EVENT_DISABLE) { \
65*4882a593Smuzhiyun regcache_mark_dirty(pcm512x->regmap); \
66*4882a593Smuzhiyun regcache_cache_only(pcm512x->regmap, true); \
67*4882a593Smuzhiyun } \
68*4882a593Smuzhiyun return 0; \
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun PCM512x_REGULATOR_EVENT(0)
72*4882a593Smuzhiyun PCM512x_REGULATOR_EVENT(1)
73*4882a593Smuzhiyun PCM512x_REGULATOR_EVENT(2)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static const struct reg_default pcm512x_reg_defaults[] = {
76*4882a593Smuzhiyun { PCM512x_RESET, 0x00 },
77*4882a593Smuzhiyun { PCM512x_POWER, 0x00 },
78*4882a593Smuzhiyun { PCM512x_MUTE, 0x00 },
79*4882a593Smuzhiyun { PCM512x_DSP, 0x00 },
80*4882a593Smuzhiyun { PCM512x_PLL_REF, 0x00 },
81*4882a593Smuzhiyun { PCM512x_DAC_REF, 0x00 },
82*4882a593Smuzhiyun { PCM512x_DAC_ROUTING, 0x11 },
83*4882a593Smuzhiyun { PCM512x_DSP_PROGRAM, 0x01 },
84*4882a593Smuzhiyun { PCM512x_CLKDET, 0x00 },
85*4882a593Smuzhiyun { PCM512x_AUTO_MUTE, 0x00 },
86*4882a593Smuzhiyun { PCM512x_ERROR_DETECT, 0x00 },
87*4882a593Smuzhiyun { PCM512x_DIGITAL_VOLUME_1, 0x00 },
88*4882a593Smuzhiyun { PCM512x_DIGITAL_VOLUME_2, 0x30 },
89*4882a593Smuzhiyun { PCM512x_DIGITAL_VOLUME_3, 0x30 },
90*4882a593Smuzhiyun { PCM512x_DIGITAL_MUTE_1, 0x22 },
91*4882a593Smuzhiyun { PCM512x_DIGITAL_MUTE_2, 0x00 },
92*4882a593Smuzhiyun { PCM512x_DIGITAL_MUTE_3, 0x07 },
93*4882a593Smuzhiyun { PCM512x_OUTPUT_AMPLITUDE, 0x00 },
94*4882a593Smuzhiyun { PCM512x_ANALOG_GAIN_CTRL, 0x00 },
95*4882a593Smuzhiyun { PCM512x_UNDERVOLTAGE_PROT, 0x00 },
96*4882a593Smuzhiyun { PCM512x_ANALOG_MUTE_CTRL, 0x00 },
97*4882a593Smuzhiyun { PCM512x_ANALOG_GAIN_BOOST, 0x00 },
98*4882a593Smuzhiyun { PCM512x_VCOM_CTRL_1, 0x00 },
99*4882a593Smuzhiyun { PCM512x_VCOM_CTRL_2, 0x01 },
100*4882a593Smuzhiyun { PCM512x_BCLK_LRCLK_CFG, 0x00 },
101*4882a593Smuzhiyun { PCM512x_MASTER_MODE, 0x7c },
102*4882a593Smuzhiyun { PCM512x_GPIO_DACIN, 0x00 },
103*4882a593Smuzhiyun { PCM512x_GPIO_PLLIN, 0x00 },
104*4882a593Smuzhiyun { PCM512x_SYNCHRONIZE, 0x10 },
105*4882a593Smuzhiyun { PCM512x_PLL_COEFF_0, 0x00 },
106*4882a593Smuzhiyun { PCM512x_PLL_COEFF_1, 0x00 },
107*4882a593Smuzhiyun { PCM512x_PLL_COEFF_2, 0x00 },
108*4882a593Smuzhiyun { PCM512x_PLL_COEFF_3, 0x00 },
109*4882a593Smuzhiyun { PCM512x_PLL_COEFF_4, 0x00 },
110*4882a593Smuzhiyun { PCM512x_DSP_CLKDIV, 0x00 },
111*4882a593Smuzhiyun { PCM512x_DAC_CLKDIV, 0x00 },
112*4882a593Smuzhiyun { PCM512x_NCP_CLKDIV, 0x00 },
113*4882a593Smuzhiyun { PCM512x_OSR_CLKDIV, 0x00 },
114*4882a593Smuzhiyun { PCM512x_MASTER_CLKDIV_1, 0x00 },
115*4882a593Smuzhiyun { PCM512x_MASTER_CLKDIV_2, 0x00 },
116*4882a593Smuzhiyun { PCM512x_FS_SPEED_MODE, 0x00 },
117*4882a593Smuzhiyun { PCM512x_IDAC_1, 0x01 },
118*4882a593Smuzhiyun { PCM512x_IDAC_2, 0x00 },
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun
pcm512x_readable(struct device * dev,unsigned int reg)121*4882a593Smuzhiyun static bool pcm512x_readable(struct device *dev, unsigned int reg)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun switch (reg) {
124*4882a593Smuzhiyun case PCM512x_RESET:
125*4882a593Smuzhiyun case PCM512x_POWER:
126*4882a593Smuzhiyun case PCM512x_MUTE:
127*4882a593Smuzhiyun case PCM512x_PLL_EN:
128*4882a593Smuzhiyun case PCM512x_SPI_MISO_FUNCTION:
129*4882a593Smuzhiyun case PCM512x_DSP:
130*4882a593Smuzhiyun case PCM512x_GPIO_EN:
131*4882a593Smuzhiyun case PCM512x_BCLK_LRCLK_CFG:
132*4882a593Smuzhiyun case PCM512x_DSP_GPIO_INPUT:
133*4882a593Smuzhiyun case PCM512x_MASTER_MODE:
134*4882a593Smuzhiyun case PCM512x_PLL_REF:
135*4882a593Smuzhiyun case PCM512x_DAC_REF:
136*4882a593Smuzhiyun case PCM512x_GPIO_DACIN:
137*4882a593Smuzhiyun case PCM512x_GPIO_PLLIN:
138*4882a593Smuzhiyun case PCM512x_SYNCHRONIZE:
139*4882a593Smuzhiyun case PCM512x_PLL_COEFF_0:
140*4882a593Smuzhiyun case PCM512x_PLL_COEFF_1:
141*4882a593Smuzhiyun case PCM512x_PLL_COEFF_2:
142*4882a593Smuzhiyun case PCM512x_PLL_COEFF_3:
143*4882a593Smuzhiyun case PCM512x_PLL_COEFF_4:
144*4882a593Smuzhiyun case PCM512x_DSP_CLKDIV:
145*4882a593Smuzhiyun case PCM512x_DAC_CLKDIV:
146*4882a593Smuzhiyun case PCM512x_NCP_CLKDIV:
147*4882a593Smuzhiyun case PCM512x_OSR_CLKDIV:
148*4882a593Smuzhiyun case PCM512x_MASTER_CLKDIV_1:
149*4882a593Smuzhiyun case PCM512x_MASTER_CLKDIV_2:
150*4882a593Smuzhiyun case PCM512x_FS_SPEED_MODE:
151*4882a593Smuzhiyun case PCM512x_IDAC_1:
152*4882a593Smuzhiyun case PCM512x_IDAC_2:
153*4882a593Smuzhiyun case PCM512x_ERROR_DETECT:
154*4882a593Smuzhiyun case PCM512x_I2S_1:
155*4882a593Smuzhiyun case PCM512x_I2S_2:
156*4882a593Smuzhiyun case PCM512x_DAC_ROUTING:
157*4882a593Smuzhiyun case PCM512x_DSP_PROGRAM:
158*4882a593Smuzhiyun case PCM512x_CLKDET:
159*4882a593Smuzhiyun case PCM512x_AUTO_MUTE:
160*4882a593Smuzhiyun case PCM512x_DIGITAL_VOLUME_1:
161*4882a593Smuzhiyun case PCM512x_DIGITAL_VOLUME_2:
162*4882a593Smuzhiyun case PCM512x_DIGITAL_VOLUME_3:
163*4882a593Smuzhiyun case PCM512x_DIGITAL_MUTE_1:
164*4882a593Smuzhiyun case PCM512x_DIGITAL_MUTE_2:
165*4882a593Smuzhiyun case PCM512x_DIGITAL_MUTE_3:
166*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_1:
167*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_2:
168*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_3:
169*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_4:
170*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_5:
171*4882a593Smuzhiyun case PCM512x_GPIO_OUTPUT_6:
172*4882a593Smuzhiyun case PCM512x_GPIO_CONTROL_1:
173*4882a593Smuzhiyun case PCM512x_GPIO_CONTROL_2:
174*4882a593Smuzhiyun case PCM512x_OVERFLOW:
175*4882a593Smuzhiyun case PCM512x_RATE_DET_1:
176*4882a593Smuzhiyun case PCM512x_RATE_DET_2:
177*4882a593Smuzhiyun case PCM512x_RATE_DET_3:
178*4882a593Smuzhiyun case PCM512x_RATE_DET_4:
179*4882a593Smuzhiyun case PCM512x_CLOCK_STATUS:
180*4882a593Smuzhiyun case PCM512x_ANALOG_MUTE_DET:
181*4882a593Smuzhiyun case PCM512x_GPIN:
182*4882a593Smuzhiyun case PCM512x_DIGITAL_MUTE_DET:
183*4882a593Smuzhiyun case PCM512x_OUTPUT_AMPLITUDE:
184*4882a593Smuzhiyun case PCM512x_ANALOG_GAIN_CTRL:
185*4882a593Smuzhiyun case PCM512x_UNDERVOLTAGE_PROT:
186*4882a593Smuzhiyun case PCM512x_ANALOG_MUTE_CTRL:
187*4882a593Smuzhiyun case PCM512x_ANALOG_GAIN_BOOST:
188*4882a593Smuzhiyun case PCM512x_VCOM_CTRL_1:
189*4882a593Smuzhiyun case PCM512x_VCOM_CTRL_2:
190*4882a593Smuzhiyun case PCM512x_CRAM_CTRL:
191*4882a593Smuzhiyun case PCM512x_FLEX_A:
192*4882a593Smuzhiyun case PCM512x_FLEX_B:
193*4882a593Smuzhiyun return true;
194*4882a593Smuzhiyun default:
195*4882a593Smuzhiyun /* There are 256 raw register addresses */
196*4882a593Smuzhiyun return reg < 0xff;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
pcm512x_volatile(struct device * dev,unsigned int reg)200*4882a593Smuzhiyun static bool pcm512x_volatile(struct device *dev, unsigned int reg)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun switch (reg) {
203*4882a593Smuzhiyun case PCM512x_PLL_EN:
204*4882a593Smuzhiyun case PCM512x_OVERFLOW:
205*4882a593Smuzhiyun case PCM512x_RATE_DET_1:
206*4882a593Smuzhiyun case PCM512x_RATE_DET_2:
207*4882a593Smuzhiyun case PCM512x_RATE_DET_3:
208*4882a593Smuzhiyun case PCM512x_RATE_DET_4:
209*4882a593Smuzhiyun case PCM512x_CLOCK_STATUS:
210*4882a593Smuzhiyun case PCM512x_ANALOG_MUTE_DET:
211*4882a593Smuzhiyun case PCM512x_GPIN:
212*4882a593Smuzhiyun case PCM512x_DIGITAL_MUTE_DET:
213*4882a593Smuzhiyun case PCM512x_CRAM_CTRL:
214*4882a593Smuzhiyun return true;
215*4882a593Smuzhiyun default:
216*4882a593Smuzhiyun /* There are 256 raw register addresses */
217*4882a593Smuzhiyun return reg < 0xff;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
pcm512x_overclock_pll_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)221*4882a593Smuzhiyun static int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
222*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
225*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
228*4882a593Smuzhiyun return 0;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
pcm512x_overclock_pll_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)231*4882a593Smuzhiyun static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
232*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
235*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun switch (snd_soc_component_get_bias_level(component)) {
238*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
239*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
240*4882a593Smuzhiyun break;
241*4882a593Smuzhiyun default:
242*4882a593Smuzhiyun return -EBUSY;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun pcm512x->overclock_pll = ucontrol->value.integer.value[0];
246*4882a593Smuzhiyun return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
pcm512x_overclock_dsp_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)249*4882a593Smuzhiyun static int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
250*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
253*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
256*4882a593Smuzhiyun return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
pcm512x_overclock_dsp_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)259*4882a593Smuzhiyun static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
260*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
263*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun switch (snd_soc_component_get_bias_level(component)) {
266*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
267*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
268*4882a593Smuzhiyun break;
269*4882a593Smuzhiyun default:
270*4882a593Smuzhiyun return -EBUSY;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
274*4882a593Smuzhiyun return 0;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
pcm512x_overclock_dac_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)277*4882a593Smuzhiyun static int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
278*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
281*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
284*4882a593Smuzhiyun return 0;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
pcm512x_overclock_dac_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)287*4882a593Smuzhiyun static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
288*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
291*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun switch (snd_soc_component_get_bias_level(component)) {
294*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
295*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
296*4882a593Smuzhiyun break;
297*4882a593Smuzhiyun default:
298*4882a593Smuzhiyun return -EBUSY;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun pcm512x->overclock_dac = ucontrol->value.integer.value[0];
302*4882a593Smuzhiyun return 0;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
306*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
307*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static const char * const pcm512x_dsp_program_texts[] = {
310*4882a593Smuzhiyun "FIR interpolation with de-emphasis",
311*4882a593Smuzhiyun "Low latency IIR with de-emphasis",
312*4882a593Smuzhiyun "High attenuation with de-emphasis",
313*4882a593Smuzhiyun "Fixed process flow",
314*4882a593Smuzhiyun "Ringing-less low latency FIR",
315*4882a593Smuzhiyun };
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static const unsigned int pcm512x_dsp_program_values[] = {
318*4882a593Smuzhiyun 1,
319*4882a593Smuzhiyun 2,
320*4882a593Smuzhiyun 3,
321*4882a593Smuzhiyun 5,
322*4882a593Smuzhiyun 7,
323*4882a593Smuzhiyun };
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
326*4882a593Smuzhiyun PCM512x_DSP_PROGRAM, 0, 0x1f,
327*4882a593Smuzhiyun pcm512x_dsp_program_texts,
328*4882a593Smuzhiyun pcm512x_dsp_program_values);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun static const char * const pcm512x_clk_missing_text[] = {
331*4882a593Smuzhiyun "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
332*4882a593Smuzhiyun };
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun static const struct soc_enum pcm512x_clk_missing =
335*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun static const char * const pcm512x_autom_text[] = {
338*4882a593Smuzhiyun "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
339*4882a593Smuzhiyun };
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun static const struct soc_enum pcm512x_autom_l =
342*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
343*4882a593Smuzhiyun pcm512x_autom_text);
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun static const struct soc_enum pcm512x_autom_r =
346*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
347*4882a593Smuzhiyun pcm512x_autom_text);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun static const char * const pcm512x_ramp_rate_text[] = {
350*4882a593Smuzhiyun "1 sample/update", "2 samples/update", "4 samples/update",
351*4882a593Smuzhiyun "Immediate"
352*4882a593Smuzhiyun };
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun static const struct soc_enum pcm512x_vndf =
355*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
356*4882a593Smuzhiyun pcm512x_ramp_rate_text);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun static const struct soc_enum pcm512x_vnuf =
359*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
360*4882a593Smuzhiyun pcm512x_ramp_rate_text);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun static const struct soc_enum pcm512x_vedf =
363*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
364*4882a593Smuzhiyun pcm512x_ramp_rate_text);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun static const char * const pcm512x_ramp_step_text[] = {
367*4882a593Smuzhiyun "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
368*4882a593Smuzhiyun };
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun static const struct soc_enum pcm512x_vnds =
371*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
372*4882a593Smuzhiyun pcm512x_ramp_step_text);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static const struct soc_enum pcm512x_vnus =
375*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
376*4882a593Smuzhiyun pcm512x_ramp_step_text);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun static const struct soc_enum pcm512x_veds =
379*4882a593Smuzhiyun SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
380*4882a593Smuzhiyun pcm512x_ramp_step_text);
381*4882a593Smuzhiyun
pcm512x_update_mute(struct pcm512x_priv * pcm512x)382*4882a593Smuzhiyun static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun return regmap_update_bits(
385*4882a593Smuzhiyun pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
386*4882a593Smuzhiyun (!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
387*4882a593Smuzhiyun | (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
pcm512x_digital_playback_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)390*4882a593Smuzhiyun static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
391*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
394*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun mutex_lock(&pcm512x->mutex);
397*4882a593Smuzhiyun ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
398*4882a593Smuzhiyun ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
399*4882a593Smuzhiyun mutex_unlock(&pcm512x->mutex);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return 0;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
pcm512x_digital_playback_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)404*4882a593Smuzhiyun static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
405*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
408*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
409*4882a593Smuzhiyun int ret, changed = 0;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun mutex_lock(&pcm512x->mutex);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
414*4882a593Smuzhiyun pcm512x->mute ^= 0x4;
415*4882a593Smuzhiyun changed = 1;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
418*4882a593Smuzhiyun pcm512x->mute ^= 0x2;
419*4882a593Smuzhiyun changed = 1;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (changed) {
423*4882a593Smuzhiyun ret = pcm512x_update_mute(pcm512x);
424*4882a593Smuzhiyun if (ret != 0) {
425*4882a593Smuzhiyun dev_err(component->dev,
426*4882a593Smuzhiyun "Failed to update digital mute: %d\n", ret);
427*4882a593Smuzhiyun mutex_unlock(&pcm512x->mutex);
428*4882a593Smuzhiyun return ret;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun mutex_unlock(&pcm512x->mutex);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun return changed;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun static const struct snd_kcontrol_new pcm512x_controls[] = {
438*4882a593Smuzhiyun SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
439*4882a593Smuzhiyun PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
440*4882a593Smuzhiyun SOC_DOUBLE_TLV("Analogue Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
441*4882a593Smuzhiyun PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
442*4882a593Smuzhiyun SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
443*4882a593Smuzhiyun PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
446*4882a593Smuzhiyun .name = "Digital Playback Switch",
447*4882a593Smuzhiyun .index = 0,
448*4882a593Smuzhiyun .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
449*4882a593Smuzhiyun .info = snd_ctl_boolean_stereo_info,
450*4882a593Smuzhiyun .get = pcm512x_digital_playback_switch_get,
451*4882a593Smuzhiyun .put = pcm512x_digital_playback_switch_put
452*4882a593Smuzhiyun },
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
455*4882a593Smuzhiyun SOC_ENUM("DSP Program", pcm512x_dsp_program),
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
458*4882a593Smuzhiyun SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
459*4882a593Smuzhiyun SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
460*4882a593Smuzhiyun SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
461*4882a593Smuzhiyun PCM512x_ACTL_SHIFT, 1, 0),
462*4882a593Smuzhiyun SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
463*4882a593Smuzhiyun PCM512x_AMRE_SHIFT, 1, 0),
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
466*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
467*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
468*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
469*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
470*4882a593Smuzhiyun SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun SOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
473*4882a593Smuzhiyun pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
474*4882a593Smuzhiyun SOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
475*4882a593Smuzhiyun pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
476*4882a593Smuzhiyun SOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
477*4882a593Smuzhiyun pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
478*4882a593Smuzhiyun };
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
481*4882a593Smuzhiyun SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
482*4882a593Smuzhiyun SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("OUTL"),
485*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("OUTR"),
486*4882a593Smuzhiyun };
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
489*4882a593Smuzhiyun { "DACL", NULL, "Playback" },
490*4882a593Smuzhiyun { "DACR", NULL, "Playback" },
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun { "OUTL", NULL, "DACL" },
493*4882a593Smuzhiyun { "OUTR", NULL, "DACR" },
494*4882a593Smuzhiyun };
495*4882a593Smuzhiyun
pcm512x_pll_max(struct pcm512x_priv * pcm512x)496*4882a593Smuzhiyun static unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
pcm512x_dsp_max(struct pcm512x_priv * pcm512x)501*4882a593Smuzhiyun static unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
pcm512x_dac_max(struct pcm512x_priv * pcm512x,unsigned long rate)506*4882a593Smuzhiyun static unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
507*4882a593Smuzhiyun unsigned long rate)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun return rate + rate * pcm512x->overclock_dac / 100;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
pcm512x_sck_max(struct pcm512x_priv * pcm512x)512*4882a593Smuzhiyun static unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun if (!pcm512x->pll_out)
515*4882a593Smuzhiyun return 25000000;
516*4882a593Smuzhiyun return pcm512x_pll_max(pcm512x);
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
pcm512x_ncp_target(struct pcm512x_priv * pcm512x,unsigned long dac_rate)519*4882a593Smuzhiyun static unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
520*4882a593Smuzhiyun unsigned long dac_rate)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun /*
523*4882a593Smuzhiyun * If the DAC is not actually overclocked, use the good old
524*4882a593Smuzhiyun * NCP target rate...
525*4882a593Smuzhiyun */
526*4882a593Smuzhiyun if (dac_rate <= 6144000)
527*4882a593Smuzhiyun return 1536000;
528*4882a593Smuzhiyun /*
529*4882a593Smuzhiyun * ...but if the DAC is in fact overclocked, bump the NCP target
530*4882a593Smuzhiyun * rate to get the recommended dividers even when overclocking.
531*4882a593Smuzhiyun */
532*4882a593Smuzhiyun return pcm512x_dac_max(pcm512x, 1536000);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun static const u32 pcm512x_dai_rates[] = {
536*4882a593Smuzhiyun 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
537*4882a593Smuzhiyun 88200, 96000, 176400, 192000, 384000,
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun static const struct snd_pcm_hw_constraint_list constraints_slave = {
541*4882a593Smuzhiyun .count = ARRAY_SIZE(pcm512x_dai_rates),
542*4882a593Smuzhiyun .list = pcm512x_dai_rates,
543*4882a593Smuzhiyun };
544*4882a593Smuzhiyun
pcm512x_hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)545*4882a593Smuzhiyun static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
546*4882a593Smuzhiyun struct snd_pcm_hw_rule *rule)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = rule->private;
549*4882a593Smuzhiyun struct snd_interval ranges[2];
550*4882a593Smuzhiyun int frame_size;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun frame_size = snd_soc_params_to_frame_size(params);
553*4882a593Smuzhiyun if (frame_size < 0)
554*4882a593Smuzhiyun return frame_size;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun switch (frame_size) {
557*4882a593Smuzhiyun case 32:
558*4882a593Smuzhiyun /* No hole when the frame size is 32. */
559*4882a593Smuzhiyun return 0;
560*4882a593Smuzhiyun case 48:
561*4882a593Smuzhiyun case 64:
562*4882a593Smuzhiyun /* There is only one hole in the range of supported
563*4882a593Smuzhiyun * rates, but it moves with the frame size.
564*4882a593Smuzhiyun */
565*4882a593Smuzhiyun memset(ranges, 0, sizeof(ranges));
566*4882a593Smuzhiyun ranges[0].min = 8000;
567*4882a593Smuzhiyun ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
568*4882a593Smuzhiyun ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
569*4882a593Smuzhiyun ranges[1].max = 384000;
570*4882a593Smuzhiyun break;
571*4882a593Smuzhiyun default:
572*4882a593Smuzhiyun return -EINVAL;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun return snd_interval_ranges(hw_param_interval(params, rule->var),
576*4882a593Smuzhiyun ARRAY_SIZE(ranges), ranges, 0);
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
pcm512x_dai_startup_master(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)579*4882a593Smuzhiyun static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
580*4882a593Smuzhiyun struct snd_soc_dai *dai)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
583*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
584*4882a593Smuzhiyun struct device *dev = dai->dev;
585*4882a593Smuzhiyun struct snd_pcm_hw_constraint_ratnums *constraints_no_pll;
586*4882a593Smuzhiyun struct snd_ratnum *rats_no_pll;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (IS_ERR(pcm512x->sclk)) {
589*4882a593Smuzhiyun dev_err(dev, "Need SCLK for master mode: %ld\n",
590*4882a593Smuzhiyun PTR_ERR(pcm512x->sclk));
591*4882a593Smuzhiyun return PTR_ERR(pcm512x->sclk);
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun if (pcm512x->pll_out)
595*4882a593Smuzhiyun return snd_pcm_hw_rule_add(substream->runtime, 0,
596*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE,
597*4882a593Smuzhiyun pcm512x_hw_rule_rate,
598*4882a593Smuzhiyun pcm512x,
599*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_FRAME_BITS,
600*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_CHANNELS, -1);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun constraints_no_pll = devm_kzalloc(dev, sizeof(*constraints_no_pll),
603*4882a593Smuzhiyun GFP_KERNEL);
604*4882a593Smuzhiyun if (!constraints_no_pll)
605*4882a593Smuzhiyun return -ENOMEM;
606*4882a593Smuzhiyun constraints_no_pll->nrats = 1;
607*4882a593Smuzhiyun rats_no_pll = devm_kzalloc(dev, sizeof(*rats_no_pll), GFP_KERNEL);
608*4882a593Smuzhiyun if (!rats_no_pll)
609*4882a593Smuzhiyun return -ENOMEM;
610*4882a593Smuzhiyun constraints_no_pll->rats = rats_no_pll;
611*4882a593Smuzhiyun rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
612*4882a593Smuzhiyun rats_no_pll->den_min = 1;
613*4882a593Smuzhiyun rats_no_pll->den_max = 128;
614*4882a593Smuzhiyun rats_no_pll->den_step = 1;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun return snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
617*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE,
618*4882a593Smuzhiyun constraints_no_pll);
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
pcm512x_dai_startup_slave(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)621*4882a593Smuzhiyun static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream,
622*4882a593Smuzhiyun struct snd_soc_dai *dai)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
625*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
626*4882a593Smuzhiyun struct device *dev = dai->dev;
627*4882a593Smuzhiyun struct regmap *regmap = pcm512x->regmap;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if (IS_ERR(pcm512x->sclk)) {
630*4882a593Smuzhiyun dev_info(dev, "No SCLK, using BCLK: %ld\n",
631*4882a593Smuzhiyun PTR_ERR(pcm512x->sclk));
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun /* Disable reporting of missing SCLK as an error */
634*4882a593Smuzhiyun regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
635*4882a593Smuzhiyun PCM512x_IDCH, PCM512x_IDCH);
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /* Switch PLL input to BCLK */
638*4882a593Smuzhiyun regmap_update_bits(regmap, PCM512x_PLL_REF,
639*4882a593Smuzhiyun PCM512x_SREF, PCM512x_SREF_BCK);
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun return snd_pcm_hw_constraint_list(substream->runtime, 0,
643*4882a593Smuzhiyun SNDRV_PCM_HW_PARAM_RATE,
644*4882a593Smuzhiyun &constraints_slave);
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
pcm512x_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)647*4882a593Smuzhiyun static int pcm512x_dai_startup(struct snd_pcm_substream *substream,
648*4882a593Smuzhiyun struct snd_soc_dai *dai)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
651*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
654*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
655*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFS:
656*4882a593Smuzhiyun return pcm512x_dai_startup_master(substream, dai);
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
659*4882a593Smuzhiyun return pcm512x_dai_startup_slave(substream, dai);
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun default:
662*4882a593Smuzhiyun return -EINVAL;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun
pcm512x_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)666*4882a593Smuzhiyun static int pcm512x_set_bias_level(struct snd_soc_component *component,
667*4882a593Smuzhiyun enum snd_soc_bias_level level)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = dev_get_drvdata(component->dev);
670*4882a593Smuzhiyun int ret;
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun switch (level) {
673*4882a593Smuzhiyun case SND_SOC_BIAS_ON:
674*4882a593Smuzhiyun case SND_SOC_BIAS_PREPARE:
675*4882a593Smuzhiyun break;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun case SND_SOC_BIAS_STANDBY:
678*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
679*4882a593Smuzhiyun PCM512x_RQST, 0);
680*4882a593Smuzhiyun if (ret != 0) {
681*4882a593Smuzhiyun dev_err(component->dev, "Failed to remove standby: %d\n",
682*4882a593Smuzhiyun ret);
683*4882a593Smuzhiyun return ret;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun break;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun case SND_SOC_BIAS_OFF:
688*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
689*4882a593Smuzhiyun PCM512x_RQST, PCM512x_RQST);
690*4882a593Smuzhiyun if (ret != 0) {
691*4882a593Smuzhiyun dev_err(component->dev, "Failed to request standby: %d\n",
692*4882a593Smuzhiyun ret);
693*4882a593Smuzhiyun return ret;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun break;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun return 0;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
pcm512x_find_sck(struct snd_soc_dai * dai,unsigned long bclk_rate)701*4882a593Smuzhiyun static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
702*4882a593Smuzhiyun unsigned long bclk_rate)
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun struct device *dev = dai->dev;
705*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
706*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
707*4882a593Smuzhiyun unsigned long sck_rate;
708*4882a593Smuzhiyun int pow2;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /* 64 MHz <= pll_rate <= 100 MHz, VREF mode */
711*4882a593Smuzhiyun /* 16 MHz <= sck_rate <= 25 MHz, VREF mode */
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun /* select sck_rate as a multiple of bclk_rate but still with
714*4882a593Smuzhiyun * as many factors of 2 as possible, as that makes it easier
715*4882a593Smuzhiyun * to find a fast DAC rate
716*4882a593Smuzhiyun */
717*4882a593Smuzhiyun pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
718*4882a593Smuzhiyun for (; pow2; pow2 >>= 1) {
719*4882a593Smuzhiyun sck_rate = rounddown(pcm512x_pll_max(pcm512x),
720*4882a593Smuzhiyun bclk_rate * pow2);
721*4882a593Smuzhiyun if (sck_rate >= 16000000)
722*4882a593Smuzhiyun break;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun if (!pow2) {
725*4882a593Smuzhiyun dev_err(dev, "Impossible to generate a suitable SCK\n");
726*4882a593Smuzhiyun return 0;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun dev_dbg(dev, "sck_rate %lu\n", sck_rate);
730*4882a593Smuzhiyun return sck_rate;
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun /* pll_rate = pllin_rate * R * J.D / P
734*4882a593Smuzhiyun * 1 <= R <= 16
735*4882a593Smuzhiyun * 1 <= J <= 63
736*4882a593Smuzhiyun * 0 <= D <= 9999
737*4882a593Smuzhiyun * 1 <= P <= 15
738*4882a593Smuzhiyun * 64 MHz <= pll_rate <= 100 MHz
739*4882a593Smuzhiyun * if D == 0
740*4882a593Smuzhiyun * 1 MHz <= pllin_rate / P <= 20 MHz
741*4882a593Smuzhiyun * else if D > 0
742*4882a593Smuzhiyun * 6.667 MHz <= pllin_rate / P <= 20 MHz
743*4882a593Smuzhiyun * 4 <= J <= 11
744*4882a593Smuzhiyun * R = 1
745*4882a593Smuzhiyun */
pcm512x_find_pll_coeff(struct snd_soc_dai * dai,unsigned long pllin_rate,unsigned long pll_rate)746*4882a593Smuzhiyun static int pcm512x_find_pll_coeff(struct snd_soc_dai *dai,
747*4882a593Smuzhiyun unsigned long pllin_rate,
748*4882a593Smuzhiyun unsigned long pll_rate)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun struct device *dev = dai->dev;
751*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
752*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
753*4882a593Smuzhiyun unsigned long common;
754*4882a593Smuzhiyun int R, J, D, P;
755*4882a593Smuzhiyun unsigned long K; /* 10000 * J.D */
756*4882a593Smuzhiyun unsigned long num;
757*4882a593Smuzhiyun unsigned long den;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun common = gcd(pll_rate, pllin_rate);
760*4882a593Smuzhiyun dev_dbg(dev, "pll %lu pllin %lu common %lu\n",
761*4882a593Smuzhiyun pll_rate, pllin_rate, common);
762*4882a593Smuzhiyun num = pll_rate / common;
763*4882a593Smuzhiyun den = pllin_rate / common;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun /* pllin_rate / P (or here, den) cannot be greater than 20 MHz */
766*4882a593Smuzhiyun if (pllin_rate / den > 20000000 && num < 8) {
767*4882a593Smuzhiyun num *= DIV_ROUND_UP(pllin_rate / den, 20000000);
768*4882a593Smuzhiyun den *= DIV_ROUND_UP(pllin_rate / den, 20000000);
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun dev_dbg(dev, "num / den = %lu / %lu\n", num, den);
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun P = den;
773*4882a593Smuzhiyun if (den <= 15 && num <= 16 * 63
774*4882a593Smuzhiyun && 1000000 <= pllin_rate / P && pllin_rate / P <= 20000000) {
775*4882a593Smuzhiyun /* Try the case with D = 0 */
776*4882a593Smuzhiyun D = 0;
777*4882a593Smuzhiyun /* factor 'num' into J and R, such that R <= 16 and J <= 63 */
778*4882a593Smuzhiyun for (R = 16; R; R--) {
779*4882a593Smuzhiyun if (num % R)
780*4882a593Smuzhiyun continue;
781*4882a593Smuzhiyun J = num / R;
782*4882a593Smuzhiyun if (J == 0 || J > 63)
783*4882a593Smuzhiyun continue;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun dev_dbg(dev, "R * J / P = %d * %d / %d\n", R, J, P);
786*4882a593Smuzhiyun pcm512x->real_pll = pll_rate;
787*4882a593Smuzhiyun goto done;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun /* no luck */
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun R = 1;
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun if (num > 0xffffffffUL / 10000)
795*4882a593Smuzhiyun goto fallback;
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /* Try to find an exact pll_rate using the D > 0 case */
798*4882a593Smuzhiyun common = gcd(10000 * num, den);
799*4882a593Smuzhiyun num = 10000 * num / common;
800*4882a593Smuzhiyun den /= common;
801*4882a593Smuzhiyun dev_dbg(dev, "num %lu den %lu common %lu\n", num, den, common);
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun for (P = den; P <= 15; P++) {
804*4882a593Smuzhiyun if (pllin_rate / P < 6667000 || 200000000 < pllin_rate / P)
805*4882a593Smuzhiyun continue;
806*4882a593Smuzhiyun if (num * P % den)
807*4882a593Smuzhiyun continue;
808*4882a593Smuzhiyun K = num * P / den;
809*4882a593Smuzhiyun /* J == 12 is ok if D == 0 */
810*4882a593Smuzhiyun if (K < 40000 || K > 120000)
811*4882a593Smuzhiyun continue;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun J = K / 10000;
814*4882a593Smuzhiyun D = K % 10000;
815*4882a593Smuzhiyun dev_dbg(dev, "J.D / P = %d.%04d / %d\n", J, D, P);
816*4882a593Smuzhiyun pcm512x->real_pll = pll_rate;
817*4882a593Smuzhiyun goto done;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun /* Fall back to an approximate pll_rate */
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun fallback:
823*4882a593Smuzhiyun /* find smallest possible P */
824*4882a593Smuzhiyun P = DIV_ROUND_UP(pllin_rate, 20000000);
825*4882a593Smuzhiyun if (!P)
826*4882a593Smuzhiyun P = 1;
827*4882a593Smuzhiyun else if (P > 15) {
828*4882a593Smuzhiyun dev_err(dev, "Need a slower clock as pll-input\n");
829*4882a593Smuzhiyun return -EINVAL;
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun if (pllin_rate / P < 6667000) {
832*4882a593Smuzhiyun dev_err(dev, "Need a faster clock as pll-input\n");
833*4882a593Smuzhiyun return -EINVAL;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun K = DIV_ROUND_CLOSEST_ULL(10000ULL * pll_rate * P, pllin_rate);
836*4882a593Smuzhiyun if (K < 40000)
837*4882a593Smuzhiyun K = 40000;
838*4882a593Smuzhiyun /* J == 12 is ok if D == 0 */
839*4882a593Smuzhiyun if (K > 120000)
840*4882a593Smuzhiyun K = 120000;
841*4882a593Smuzhiyun J = K / 10000;
842*4882a593Smuzhiyun D = K % 10000;
843*4882a593Smuzhiyun dev_dbg(dev, "J.D / P ~ %d.%04d / %d\n", J, D, P);
844*4882a593Smuzhiyun pcm512x->real_pll = DIV_ROUND_DOWN_ULL((u64)K * pllin_rate, 10000 * P);
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun done:
847*4882a593Smuzhiyun pcm512x->pll_r = R;
848*4882a593Smuzhiyun pcm512x->pll_j = J;
849*4882a593Smuzhiyun pcm512x->pll_d = D;
850*4882a593Smuzhiyun pcm512x->pll_p = P;
851*4882a593Smuzhiyun return 0;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun
pcm512x_pllin_dac_rate(struct snd_soc_dai * dai,unsigned long osr_rate,unsigned long pllin_rate)854*4882a593Smuzhiyun static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
855*4882a593Smuzhiyun unsigned long osr_rate,
856*4882a593Smuzhiyun unsigned long pllin_rate)
857*4882a593Smuzhiyun {
858*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
859*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
860*4882a593Smuzhiyun unsigned long dac_rate;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun if (!pcm512x->pll_out)
863*4882a593Smuzhiyun return 0; /* no PLL to bypass, force SCK as DAC input */
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun if (pllin_rate % osr_rate)
866*4882a593Smuzhiyun return 0; /* futile, quit early */
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun /* run DAC no faster than 6144000 Hz */
869*4882a593Smuzhiyun for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
870*4882a593Smuzhiyun dac_rate;
871*4882a593Smuzhiyun dac_rate -= osr_rate) {
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun if (pllin_rate / dac_rate > 128)
874*4882a593Smuzhiyun return 0; /* DAC divider would be too big */
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun if (!(pllin_rate % dac_rate))
877*4882a593Smuzhiyun return dac_rate;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun dac_rate -= osr_rate;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun return 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
pcm512x_set_dividers(struct snd_soc_dai * dai,struct snd_pcm_hw_params * params)885*4882a593Smuzhiyun static int pcm512x_set_dividers(struct snd_soc_dai *dai,
886*4882a593Smuzhiyun struct snd_pcm_hw_params *params)
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun struct device *dev = dai->dev;
889*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
890*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
891*4882a593Smuzhiyun unsigned long pllin_rate = 0;
892*4882a593Smuzhiyun unsigned long pll_rate;
893*4882a593Smuzhiyun unsigned long sck_rate;
894*4882a593Smuzhiyun unsigned long mck_rate;
895*4882a593Smuzhiyun unsigned long bclk_rate;
896*4882a593Smuzhiyun unsigned long sample_rate;
897*4882a593Smuzhiyun unsigned long osr_rate;
898*4882a593Smuzhiyun unsigned long dacsrc_rate;
899*4882a593Smuzhiyun int bclk_div;
900*4882a593Smuzhiyun int lrclk_div;
901*4882a593Smuzhiyun int dsp_div;
902*4882a593Smuzhiyun int dac_div;
903*4882a593Smuzhiyun unsigned long dac_rate;
904*4882a593Smuzhiyun int ncp_div;
905*4882a593Smuzhiyun int osr_div;
906*4882a593Smuzhiyun int ret;
907*4882a593Smuzhiyun int idac;
908*4882a593Smuzhiyun int fssp;
909*4882a593Smuzhiyun int gpio;
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun if (pcm512x->bclk_ratio > 0) {
912*4882a593Smuzhiyun lrclk_div = pcm512x->bclk_ratio;
913*4882a593Smuzhiyun } else {
914*4882a593Smuzhiyun lrclk_div = snd_soc_params_to_frame_size(params);
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun if (lrclk_div == 0) {
917*4882a593Smuzhiyun dev_err(dev, "No LRCLK?\n");
918*4882a593Smuzhiyun return -EINVAL;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun if (!pcm512x->pll_out) {
923*4882a593Smuzhiyun sck_rate = clk_get_rate(pcm512x->sclk);
924*4882a593Smuzhiyun bclk_rate = params_rate(params) * lrclk_div;
925*4882a593Smuzhiyun bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun mck_rate = sck_rate;
928*4882a593Smuzhiyun } else {
929*4882a593Smuzhiyun ret = snd_soc_params_to_bclk(params);
930*4882a593Smuzhiyun if (ret < 0) {
931*4882a593Smuzhiyun dev_err(dev, "Failed to find suitable BCLK: %d\n", ret);
932*4882a593Smuzhiyun return ret;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun if (ret == 0) {
935*4882a593Smuzhiyun dev_err(dev, "No BCLK?\n");
936*4882a593Smuzhiyun return -EINVAL;
937*4882a593Smuzhiyun }
938*4882a593Smuzhiyun bclk_rate = ret;
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun pllin_rate = clk_get_rate(pcm512x->sclk);
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun sck_rate = pcm512x_find_sck(dai, bclk_rate);
943*4882a593Smuzhiyun if (!sck_rate)
944*4882a593Smuzhiyun return -EINVAL;
945*4882a593Smuzhiyun pll_rate = 4 * sck_rate;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun ret = pcm512x_find_pll_coeff(dai, pllin_rate, pll_rate);
948*4882a593Smuzhiyun if (ret != 0)
949*4882a593Smuzhiyun return ret;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
952*4882a593Smuzhiyun PCM512x_PLL_COEFF_0, pcm512x->pll_p - 1);
953*4882a593Smuzhiyun if (ret != 0) {
954*4882a593Smuzhiyun dev_err(dev, "Failed to write PLL P: %d\n", ret);
955*4882a593Smuzhiyun return ret;
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
959*4882a593Smuzhiyun PCM512x_PLL_COEFF_1, pcm512x->pll_j);
960*4882a593Smuzhiyun if (ret != 0) {
961*4882a593Smuzhiyun dev_err(dev, "Failed to write PLL J: %d\n", ret);
962*4882a593Smuzhiyun return ret;
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
966*4882a593Smuzhiyun PCM512x_PLL_COEFF_2, pcm512x->pll_d >> 8);
967*4882a593Smuzhiyun if (ret != 0) {
968*4882a593Smuzhiyun dev_err(dev, "Failed to write PLL D msb: %d\n", ret);
969*4882a593Smuzhiyun return ret;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
973*4882a593Smuzhiyun PCM512x_PLL_COEFF_3, pcm512x->pll_d & 0xff);
974*4882a593Smuzhiyun if (ret != 0) {
975*4882a593Smuzhiyun dev_err(dev, "Failed to write PLL D lsb: %d\n", ret);
976*4882a593Smuzhiyun return ret;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
980*4882a593Smuzhiyun PCM512x_PLL_COEFF_4, pcm512x->pll_r - 1);
981*4882a593Smuzhiyun if (ret != 0) {
982*4882a593Smuzhiyun dev_err(dev, "Failed to write PLL R: %d\n", ret);
983*4882a593Smuzhiyun return ret;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun mck_rate = pcm512x->real_pll;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun if (bclk_div > 128) {
992*4882a593Smuzhiyun dev_err(dev, "Failed to find BCLK divider\n");
993*4882a593Smuzhiyun return -EINVAL;
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun /* the actual rate */
997*4882a593Smuzhiyun sample_rate = sck_rate / bclk_div / lrclk_div;
998*4882a593Smuzhiyun osr_rate = 16 * sample_rate;
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun /* run DSP no faster than 50 MHz */
1001*4882a593Smuzhiyun dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
1004*4882a593Smuzhiyun if (dac_rate) {
1005*4882a593Smuzhiyun /* the desired clock rate is "compatible" with the pll input
1006*4882a593Smuzhiyun * clock, so use that clock as dac input instead of the pll
1007*4882a593Smuzhiyun * output clock since the pll will introduce jitter and thus
1008*4882a593Smuzhiyun * noise.
1009*4882a593Smuzhiyun */
1010*4882a593Smuzhiyun dev_dbg(dev, "using pll input as dac input\n");
1011*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
1012*4882a593Smuzhiyun PCM512x_SDAC, PCM512x_SDAC_GPIO);
1013*4882a593Smuzhiyun if (ret != 0) {
1014*4882a593Smuzhiyun dev_err(component->dev,
1015*4882a593Smuzhiyun "Failed to set gpio as dacref: %d\n", ret);
1016*4882a593Smuzhiyun return ret;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
1020*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN,
1021*4882a593Smuzhiyun PCM512x_GREF, gpio);
1022*4882a593Smuzhiyun if (ret != 0) {
1023*4882a593Smuzhiyun dev_err(component->dev,
1024*4882a593Smuzhiyun "Failed to set gpio %d as dacin: %d\n",
1025*4882a593Smuzhiyun pcm512x->pll_in, ret);
1026*4882a593Smuzhiyun return ret;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun dacsrc_rate = pllin_rate;
1030*4882a593Smuzhiyun } else {
1031*4882a593Smuzhiyun /* run DAC no faster than 6144000 Hz */
1032*4882a593Smuzhiyun unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
1033*4882a593Smuzhiyun / osr_rate;
1034*4882a593Smuzhiyun unsigned long sck_mul = sck_rate / osr_rate;
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun for (; dac_mul; dac_mul--) {
1037*4882a593Smuzhiyun if (!(sck_mul % dac_mul))
1038*4882a593Smuzhiyun break;
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun if (!dac_mul) {
1041*4882a593Smuzhiyun dev_err(dev, "Failed to find DAC rate\n");
1042*4882a593Smuzhiyun return -EINVAL;
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun dac_rate = dac_mul * osr_rate;
1046*4882a593Smuzhiyun dev_dbg(dev, "dac_rate %lu sample_rate %lu\n",
1047*4882a593Smuzhiyun dac_rate, sample_rate);
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
1050*4882a593Smuzhiyun PCM512x_SDAC, PCM512x_SDAC_SCK);
1051*4882a593Smuzhiyun if (ret != 0) {
1052*4882a593Smuzhiyun dev_err(component->dev,
1053*4882a593Smuzhiyun "Failed to set sck as dacref: %d\n", ret);
1054*4882a593Smuzhiyun return ret;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun dacsrc_rate = sck_rate;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
1061*4882a593Smuzhiyun if (osr_div > 128) {
1062*4882a593Smuzhiyun dev_err(dev, "Failed to find OSR divider\n");
1063*4882a593Smuzhiyun return -EINVAL;
1064*4882a593Smuzhiyun }
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
1067*4882a593Smuzhiyun if (dac_div > 128) {
1068*4882a593Smuzhiyun dev_err(dev, "Failed to find DAC divider\n");
1069*4882a593Smuzhiyun return -EINVAL;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun dac_rate = dacsrc_rate / dac_div;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun ncp_div = DIV_ROUND_CLOSEST(dac_rate,
1074*4882a593Smuzhiyun pcm512x_ncp_target(pcm512x, dac_rate));
1075*4882a593Smuzhiyun if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
1076*4882a593Smuzhiyun /* run NCP no faster than 2048000 Hz, but why? */
1077*4882a593Smuzhiyun ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
1078*4882a593Smuzhiyun if (ncp_div > 128) {
1079*4882a593Smuzhiyun dev_err(dev, "Failed to find NCP divider\n");
1080*4882a593Smuzhiyun return -EINVAL;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun idac = mck_rate / (dsp_div * sample_rate);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1);
1087*4882a593Smuzhiyun if (ret != 0) {
1088*4882a593Smuzhiyun dev_err(dev, "Failed to write DSP divider: %d\n", ret);
1089*4882a593Smuzhiyun return ret;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1);
1093*4882a593Smuzhiyun if (ret != 0) {
1094*4882a593Smuzhiyun dev_err(dev, "Failed to write DAC divider: %d\n", ret);
1095*4882a593Smuzhiyun return ret;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1);
1099*4882a593Smuzhiyun if (ret != 0) {
1100*4882a593Smuzhiyun dev_err(dev, "Failed to write NCP divider: %d\n", ret);
1101*4882a593Smuzhiyun return ret;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1);
1105*4882a593Smuzhiyun if (ret != 0) {
1106*4882a593Smuzhiyun dev_err(dev, "Failed to write OSR divider: %d\n", ret);
1107*4882a593Smuzhiyun return ret;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
1111*4882a593Smuzhiyun PCM512x_MASTER_CLKDIV_1, bclk_div - 1);
1112*4882a593Smuzhiyun if (ret != 0) {
1113*4882a593Smuzhiyun dev_err(dev, "Failed to write BCLK divider: %d\n", ret);
1114*4882a593Smuzhiyun return ret;
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap,
1118*4882a593Smuzhiyun PCM512x_MASTER_CLKDIV_2, lrclk_div - 1);
1119*4882a593Smuzhiyun if (ret != 0) {
1120*4882a593Smuzhiyun dev_err(dev, "Failed to write LRCLK divider: %d\n", ret);
1121*4882a593Smuzhiyun return ret;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8);
1125*4882a593Smuzhiyun if (ret != 0) {
1126*4882a593Smuzhiyun dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret);
1127*4882a593Smuzhiyun return ret;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff);
1131*4882a593Smuzhiyun if (ret != 0) {
1132*4882a593Smuzhiyun dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret);
1133*4882a593Smuzhiyun return ret;
1134*4882a593Smuzhiyun }
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
1137*4882a593Smuzhiyun fssp = PCM512x_FSSP_48KHZ;
1138*4882a593Smuzhiyun else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
1139*4882a593Smuzhiyun fssp = PCM512x_FSSP_96KHZ;
1140*4882a593Smuzhiyun else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
1141*4882a593Smuzhiyun fssp = PCM512x_FSSP_192KHZ;
1142*4882a593Smuzhiyun else
1143*4882a593Smuzhiyun fssp = PCM512x_FSSP_384KHZ;
1144*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE,
1145*4882a593Smuzhiyun PCM512x_FSSP, fssp);
1146*4882a593Smuzhiyun if (ret != 0) {
1147*4882a593Smuzhiyun dev_err(component->dev, "Failed to set fs speed: %d\n", ret);
1148*4882a593Smuzhiyun return ret;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun dev_dbg(component->dev, "DSP divider %d\n", dsp_div);
1152*4882a593Smuzhiyun dev_dbg(component->dev, "DAC divider %d\n", dac_div);
1153*4882a593Smuzhiyun dev_dbg(component->dev, "NCP divider %d\n", ncp_div);
1154*4882a593Smuzhiyun dev_dbg(component->dev, "OSR divider %d\n", osr_div);
1155*4882a593Smuzhiyun dev_dbg(component->dev, "BCK divider %d\n", bclk_div);
1156*4882a593Smuzhiyun dev_dbg(component->dev, "LRCK divider %d\n", lrclk_div);
1157*4882a593Smuzhiyun dev_dbg(component->dev, "IDAC %d\n", idac);
1158*4882a593Smuzhiyun dev_dbg(component->dev, "1<<FSSP %d\n", 1 << fssp);
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun return 0;
1161*4882a593Smuzhiyun }
1162*4882a593Smuzhiyun
pcm512x_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)1163*4882a593Smuzhiyun static int pcm512x_hw_params(struct snd_pcm_substream *substream,
1164*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
1165*4882a593Smuzhiyun struct snd_soc_dai *dai)
1166*4882a593Smuzhiyun {
1167*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1168*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1169*4882a593Smuzhiyun int alen;
1170*4882a593Smuzhiyun int gpio;
1171*4882a593Smuzhiyun int clock_output;
1172*4882a593Smuzhiyun int master_mode;
1173*4882a593Smuzhiyun int ret;
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun dev_dbg(component->dev, "hw_params %u Hz, %u channels\n",
1176*4882a593Smuzhiyun params_rate(params),
1177*4882a593Smuzhiyun params_channels(params));
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun switch (params_width(params)) {
1180*4882a593Smuzhiyun case 16:
1181*4882a593Smuzhiyun alen = PCM512x_ALEN_16;
1182*4882a593Smuzhiyun break;
1183*4882a593Smuzhiyun case 20:
1184*4882a593Smuzhiyun alen = PCM512x_ALEN_20;
1185*4882a593Smuzhiyun break;
1186*4882a593Smuzhiyun case 24:
1187*4882a593Smuzhiyun alen = PCM512x_ALEN_24;
1188*4882a593Smuzhiyun break;
1189*4882a593Smuzhiyun case 32:
1190*4882a593Smuzhiyun alen = PCM512x_ALEN_32;
1191*4882a593Smuzhiyun break;
1192*4882a593Smuzhiyun default:
1193*4882a593Smuzhiyun dev_err(component->dev, "Bad frame size: %d\n",
1194*4882a593Smuzhiyun params_width(params));
1195*4882a593Smuzhiyun return -EINVAL;
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1199*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBS_CFS:
1200*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap,
1201*4882a593Smuzhiyun PCM512x_BCLK_LRCLK_CFG,
1202*4882a593Smuzhiyun PCM512x_BCKP
1203*4882a593Smuzhiyun | PCM512x_BCKO | PCM512x_LRKO,
1204*4882a593Smuzhiyun 0);
1205*4882a593Smuzhiyun if (ret != 0) {
1206*4882a593Smuzhiyun dev_err(component->dev,
1207*4882a593Smuzhiyun "Failed to enable slave mode: %d\n", ret);
1208*4882a593Smuzhiyun return ret;
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
1212*4882a593Smuzhiyun PCM512x_DCAS, 0);
1213*4882a593Smuzhiyun if (ret != 0) {
1214*4882a593Smuzhiyun dev_err(component->dev,
1215*4882a593Smuzhiyun "Failed to enable clock divider autoset: %d\n",
1216*4882a593Smuzhiyun ret);
1217*4882a593Smuzhiyun return ret;
1218*4882a593Smuzhiyun }
1219*4882a593Smuzhiyun return 0;
1220*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFM:
1221*4882a593Smuzhiyun clock_output = PCM512x_BCKO | PCM512x_LRKO;
1222*4882a593Smuzhiyun master_mode = PCM512x_RLRK | PCM512x_RBCK;
1223*4882a593Smuzhiyun break;
1224*4882a593Smuzhiyun case SND_SOC_DAIFMT_CBM_CFS:
1225*4882a593Smuzhiyun clock_output = PCM512x_BCKO;
1226*4882a593Smuzhiyun master_mode = PCM512x_RBCK;
1227*4882a593Smuzhiyun break;
1228*4882a593Smuzhiyun default:
1229*4882a593Smuzhiyun return -EINVAL;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
1233*4882a593Smuzhiyun PCM512x_ALEN, alen);
1234*4882a593Smuzhiyun if (ret != 0) {
1235*4882a593Smuzhiyun dev_err(component->dev, "Failed to set frame size: %d\n", ret);
1236*4882a593Smuzhiyun return ret;
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun if (pcm512x->pll_out) {
1240*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11);
1241*4882a593Smuzhiyun if (ret != 0) {
1242*4882a593Smuzhiyun dev_err(component->dev, "Failed to set FLEX_A: %d\n", ret);
1243*4882a593Smuzhiyun return ret;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff);
1247*4882a593Smuzhiyun if (ret != 0) {
1248*4882a593Smuzhiyun dev_err(component->dev, "Failed to set FLEX_B: %d\n", ret);
1249*4882a593Smuzhiyun return ret;
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun
1252*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
1253*4882a593Smuzhiyun PCM512x_IDFS | PCM512x_IDBK
1254*4882a593Smuzhiyun | PCM512x_IDSK | PCM512x_IDCH
1255*4882a593Smuzhiyun | PCM512x_IDCM | PCM512x_DCAS
1256*4882a593Smuzhiyun | PCM512x_IPLK,
1257*4882a593Smuzhiyun PCM512x_IDFS | PCM512x_IDBK
1258*4882a593Smuzhiyun | PCM512x_IDSK | PCM512x_IDCH
1259*4882a593Smuzhiyun | PCM512x_DCAS);
1260*4882a593Smuzhiyun if (ret != 0) {
1261*4882a593Smuzhiyun dev_err(component->dev,
1262*4882a593Smuzhiyun "Failed to ignore auto-clock failures: %d\n",
1263*4882a593Smuzhiyun ret);
1264*4882a593Smuzhiyun return ret;
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun } else {
1267*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
1268*4882a593Smuzhiyun PCM512x_IDFS | PCM512x_IDBK
1269*4882a593Smuzhiyun | PCM512x_IDSK | PCM512x_IDCH
1270*4882a593Smuzhiyun | PCM512x_IDCM | PCM512x_DCAS
1271*4882a593Smuzhiyun | PCM512x_IPLK,
1272*4882a593Smuzhiyun PCM512x_IDFS | PCM512x_IDBK
1273*4882a593Smuzhiyun | PCM512x_IDSK | PCM512x_IDCH
1274*4882a593Smuzhiyun | PCM512x_DCAS | PCM512x_IPLK);
1275*4882a593Smuzhiyun if (ret != 0) {
1276*4882a593Smuzhiyun dev_err(component->dev,
1277*4882a593Smuzhiyun "Failed to ignore auto-clock failures: %d\n",
1278*4882a593Smuzhiyun ret);
1279*4882a593Smuzhiyun return ret;
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
1283*4882a593Smuzhiyun PCM512x_PLLE, 0);
1284*4882a593Smuzhiyun if (ret != 0) {
1285*4882a593Smuzhiyun dev_err(component->dev, "Failed to disable pll: %d\n", ret);
1286*4882a593Smuzhiyun return ret;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun }
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun ret = pcm512x_set_dividers(dai, params);
1291*4882a593Smuzhiyun if (ret != 0)
1292*4882a593Smuzhiyun return ret;
1293*4882a593Smuzhiyun
1294*4882a593Smuzhiyun if (pcm512x->pll_out) {
1295*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF,
1296*4882a593Smuzhiyun PCM512x_SREF, PCM512x_SREF_GPIO);
1297*4882a593Smuzhiyun if (ret != 0) {
1298*4882a593Smuzhiyun dev_err(component->dev,
1299*4882a593Smuzhiyun "Failed to set gpio as pllref: %d\n", ret);
1300*4882a593Smuzhiyun return ret;
1301*4882a593Smuzhiyun }
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
1304*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN,
1305*4882a593Smuzhiyun PCM512x_GREF, gpio);
1306*4882a593Smuzhiyun if (ret != 0) {
1307*4882a593Smuzhiyun dev_err(component->dev,
1308*4882a593Smuzhiyun "Failed to set gpio %d as pllin: %d\n",
1309*4882a593Smuzhiyun pcm512x->pll_in, ret);
1310*4882a593Smuzhiyun return ret;
1311*4882a593Smuzhiyun }
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
1314*4882a593Smuzhiyun PCM512x_PLLE, PCM512x_PLLE);
1315*4882a593Smuzhiyun if (ret != 0) {
1316*4882a593Smuzhiyun dev_err(component->dev, "Failed to enable pll: %d\n", ret);
1317*4882a593Smuzhiyun return ret;
1318*4882a593Smuzhiyun }
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG,
1322*4882a593Smuzhiyun PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO,
1323*4882a593Smuzhiyun clock_output);
1324*4882a593Smuzhiyun if (ret != 0) {
1325*4882a593Smuzhiyun dev_err(component->dev, "Failed to enable clock output: %d\n", ret);
1326*4882a593Smuzhiyun return ret;
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun
1329*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE,
1330*4882a593Smuzhiyun PCM512x_RLRK | PCM512x_RBCK,
1331*4882a593Smuzhiyun master_mode);
1332*4882a593Smuzhiyun if (ret != 0) {
1333*4882a593Smuzhiyun dev_err(component->dev, "Failed to enable master mode: %d\n", ret);
1334*4882a593Smuzhiyun return ret;
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun if (pcm512x->pll_out) {
1338*4882a593Smuzhiyun gpio = PCM512x_G1OE << (pcm512x->pll_out - 1);
1339*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN,
1340*4882a593Smuzhiyun gpio, gpio);
1341*4882a593Smuzhiyun if (ret != 0) {
1342*4882a593Smuzhiyun dev_err(component->dev, "Failed to enable gpio %d: %d\n",
1343*4882a593Smuzhiyun pcm512x->pll_out, ret);
1344*4882a593Smuzhiyun return ret;
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1;
1348*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, gpio,
1349*4882a593Smuzhiyun PCM512x_GxSL, PCM512x_GxSL_PLLCK);
1350*4882a593Smuzhiyun if (ret != 0) {
1351*4882a593Smuzhiyun dev_err(component->dev, "Failed to output pll on %d: %d\n",
1352*4882a593Smuzhiyun ret, pcm512x->pll_out);
1353*4882a593Smuzhiyun return ret;
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun
1357*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
1358*4882a593Smuzhiyun PCM512x_RQSY, PCM512x_RQSY_HALT);
1359*4882a593Smuzhiyun if (ret != 0) {
1360*4882a593Smuzhiyun dev_err(component->dev, "Failed to halt clocks: %d\n", ret);
1361*4882a593Smuzhiyun return ret;
1362*4882a593Smuzhiyun }
1363*4882a593Smuzhiyun
1364*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
1365*4882a593Smuzhiyun PCM512x_RQSY, PCM512x_RQSY_RESUME);
1366*4882a593Smuzhiyun if (ret != 0) {
1367*4882a593Smuzhiyun dev_err(component->dev, "Failed to resume clocks: %d\n", ret);
1368*4882a593Smuzhiyun return ret;
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun return 0;
1372*4882a593Smuzhiyun }
1373*4882a593Smuzhiyun
pcm512x_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)1374*4882a593Smuzhiyun static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1375*4882a593Smuzhiyun {
1376*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1377*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun pcm512x->fmt = fmt;
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun return 0;
1382*4882a593Smuzhiyun }
1383*4882a593Smuzhiyun
pcm512x_set_bclk_ratio(struct snd_soc_dai * dai,unsigned int ratio)1384*4882a593Smuzhiyun static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
1385*4882a593Smuzhiyun {
1386*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1387*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1388*4882a593Smuzhiyun
1389*4882a593Smuzhiyun if (ratio > 256)
1390*4882a593Smuzhiyun return -EINVAL;
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun pcm512x->bclk_ratio = ratio;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun return 0;
1395*4882a593Smuzhiyun }
1396*4882a593Smuzhiyun
pcm512x_mute(struct snd_soc_dai * dai,int mute,int direction)1397*4882a593Smuzhiyun static int pcm512x_mute(struct snd_soc_dai *dai, int mute, int direction)
1398*4882a593Smuzhiyun {
1399*4882a593Smuzhiyun struct snd_soc_component *component = dai->component;
1400*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1401*4882a593Smuzhiyun int ret;
1402*4882a593Smuzhiyun unsigned int mute_det;
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun mutex_lock(&pcm512x->mutex);
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun if (mute) {
1407*4882a593Smuzhiyun pcm512x->mute |= 0x1;
1408*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
1409*4882a593Smuzhiyun PCM512x_RQML | PCM512x_RQMR,
1410*4882a593Smuzhiyun PCM512x_RQML | PCM512x_RQMR);
1411*4882a593Smuzhiyun if (ret != 0) {
1412*4882a593Smuzhiyun dev_err(component->dev,
1413*4882a593Smuzhiyun "Failed to set digital mute: %d\n", ret);
1414*4882a593Smuzhiyun goto unlock;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun regmap_read_poll_timeout(pcm512x->regmap,
1418*4882a593Smuzhiyun PCM512x_ANALOG_MUTE_DET,
1419*4882a593Smuzhiyun mute_det, (mute_det & 0x3) == 0,
1420*4882a593Smuzhiyun 200, 10000);
1421*4882a593Smuzhiyun } else {
1422*4882a593Smuzhiyun pcm512x->mute &= ~0x1;
1423*4882a593Smuzhiyun ret = pcm512x_update_mute(pcm512x);
1424*4882a593Smuzhiyun if (ret != 0) {
1425*4882a593Smuzhiyun dev_err(component->dev,
1426*4882a593Smuzhiyun "Failed to update digital mute: %d\n", ret);
1427*4882a593Smuzhiyun goto unlock;
1428*4882a593Smuzhiyun }
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun regmap_read_poll_timeout(pcm512x->regmap,
1431*4882a593Smuzhiyun PCM512x_ANALOG_MUTE_DET,
1432*4882a593Smuzhiyun mute_det,
1433*4882a593Smuzhiyun (mute_det & 0x3)
1434*4882a593Smuzhiyun == ((~pcm512x->mute >> 1) & 0x3),
1435*4882a593Smuzhiyun 200, 10000);
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun unlock:
1439*4882a593Smuzhiyun mutex_unlock(&pcm512x->mutex);
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun return ret;
1442*4882a593Smuzhiyun }
1443*4882a593Smuzhiyun
1444*4882a593Smuzhiyun static const struct snd_soc_dai_ops pcm512x_dai_ops = {
1445*4882a593Smuzhiyun .startup = pcm512x_dai_startup,
1446*4882a593Smuzhiyun .hw_params = pcm512x_hw_params,
1447*4882a593Smuzhiyun .set_fmt = pcm512x_set_fmt,
1448*4882a593Smuzhiyun .mute_stream = pcm512x_mute,
1449*4882a593Smuzhiyun .set_bclk_ratio = pcm512x_set_bclk_ratio,
1450*4882a593Smuzhiyun .no_capture_mute = 1,
1451*4882a593Smuzhiyun };
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun static struct snd_soc_dai_driver pcm512x_dai = {
1454*4882a593Smuzhiyun .name = "pcm512x-hifi",
1455*4882a593Smuzhiyun .playback = {
1456*4882a593Smuzhiyun .stream_name = "Playback",
1457*4882a593Smuzhiyun .channels_min = 2,
1458*4882a593Smuzhiyun .channels_max = 2,
1459*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_CONTINUOUS,
1460*4882a593Smuzhiyun .rate_min = 8000,
1461*4882a593Smuzhiyun .rate_max = 384000,
1462*4882a593Smuzhiyun .formats = SNDRV_PCM_FMTBIT_S16_LE |
1463*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE |
1464*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE
1465*4882a593Smuzhiyun },
1466*4882a593Smuzhiyun .ops = &pcm512x_dai_ops,
1467*4882a593Smuzhiyun };
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun static const struct snd_soc_component_driver pcm512x_component_driver = {
1470*4882a593Smuzhiyun .set_bias_level = pcm512x_set_bias_level,
1471*4882a593Smuzhiyun .controls = pcm512x_controls,
1472*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(pcm512x_controls),
1473*4882a593Smuzhiyun .dapm_widgets = pcm512x_dapm_widgets,
1474*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
1475*4882a593Smuzhiyun .dapm_routes = pcm512x_dapm_routes,
1476*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
1477*4882a593Smuzhiyun .use_pmdown_time = 1,
1478*4882a593Smuzhiyun .endianness = 1,
1479*4882a593Smuzhiyun .non_legacy_dai_naming = 1,
1480*4882a593Smuzhiyun };
1481*4882a593Smuzhiyun
1482*4882a593Smuzhiyun static const struct regmap_range_cfg pcm512x_range = {
1483*4882a593Smuzhiyun .name = "Pages", .range_min = PCM512x_VIRT_BASE,
1484*4882a593Smuzhiyun .range_max = PCM512x_MAX_REGISTER,
1485*4882a593Smuzhiyun .selector_reg = PCM512x_PAGE,
1486*4882a593Smuzhiyun .selector_mask = 0xff,
1487*4882a593Smuzhiyun .window_start = 0, .window_len = 0x100,
1488*4882a593Smuzhiyun };
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun const struct regmap_config pcm512x_regmap = {
1491*4882a593Smuzhiyun .reg_bits = 8,
1492*4882a593Smuzhiyun .val_bits = 8,
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun .readable_reg = pcm512x_readable,
1495*4882a593Smuzhiyun .volatile_reg = pcm512x_volatile,
1496*4882a593Smuzhiyun
1497*4882a593Smuzhiyun .ranges = &pcm512x_range,
1498*4882a593Smuzhiyun .num_ranges = 1,
1499*4882a593Smuzhiyun
1500*4882a593Smuzhiyun .max_register = PCM512x_MAX_REGISTER,
1501*4882a593Smuzhiyun .reg_defaults = pcm512x_reg_defaults,
1502*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
1503*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
1504*4882a593Smuzhiyun };
1505*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pcm512x_regmap);
1506*4882a593Smuzhiyun
pcm512x_probe(struct device * dev,struct regmap * regmap)1507*4882a593Smuzhiyun int pcm512x_probe(struct device *dev, struct regmap *regmap)
1508*4882a593Smuzhiyun {
1509*4882a593Smuzhiyun struct pcm512x_priv *pcm512x;
1510*4882a593Smuzhiyun int i, ret;
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
1513*4882a593Smuzhiyun if (!pcm512x)
1514*4882a593Smuzhiyun return -ENOMEM;
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun mutex_init(&pcm512x->mutex);
1517*4882a593Smuzhiyun
1518*4882a593Smuzhiyun dev_set_drvdata(dev, pcm512x);
1519*4882a593Smuzhiyun pcm512x->regmap = regmap;
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
1522*4882a593Smuzhiyun pcm512x->supplies[i].supply = pcm512x_supply_names[i];
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
1525*4882a593Smuzhiyun pcm512x->supplies);
1526*4882a593Smuzhiyun if (ret != 0) {
1527*4882a593Smuzhiyun dev_err(dev, "Failed to get supplies: %d\n", ret);
1528*4882a593Smuzhiyun return ret;
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
1532*4882a593Smuzhiyun pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
1533*4882a593Smuzhiyun pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
1536*4882a593Smuzhiyun ret = devm_regulator_register_notifier(
1537*4882a593Smuzhiyun pcm512x->supplies[i].consumer,
1538*4882a593Smuzhiyun &pcm512x->supply_nb[i]);
1539*4882a593Smuzhiyun if (ret != 0) {
1540*4882a593Smuzhiyun dev_err(dev,
1541*4882a593Smuzhiyun "Failed to register regulator notifier: %d\n",
1542*4882a593Smuzhiyun ret);
1543*4882a593Smuzhiyun }
1544*4882a593Smuzhiyun }
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
1547*4882a593Smuzhiyun pcm512x->supplies);
1548*4882a593Smuzhiyun if (ret != 0) {
1549*4882a593Smuzhiyun dev_err(dev, "Failed to enable supplies: %d\n", ret);
1550*4882a593Smuzhiyun return ret;
1551*4882a593Smuzhiyun }
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun /* Reset the device, verifying I/O in the process for I2C */
1554*4882a593Smuzhiyun ret = regmap_write(regmap, PCM512x_RESET,
1555*4882a593Smuzhiyun PCM512x_RSTM | PCM512x_RSTR);
1556*4882a593Smuzhiyun if (ret != 0) {
1557*4882a593Smuzhiyun dev_err(dev, "Failed to reset device: %d\n", ret);
1558*4882a593Smuzhiyun goto err;
1559*4882a593Smuzhiyun }
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun ret = regmap_write(regmap, PCM512x_RESET, 0);
1562*4882a593Smuzhiyun if (ret != 0) {
1563*4882a593Smuzhiyun dev_err(dev, "Failed to reset device: %d\n", ret);
1564*4882a593Smuzhiyun goto err;
1565*4882a593Smuzhiyun }
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun pcm512x->sclk = devm_clk_get(dev, NULL);
1568*4882a593Smuzhiyun if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) {
1569*4882a593Smuzhiyun ret = -EPROBE_DEFER;
1570*4882a593Smuzhiyun goto err;
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun if (!IS_ERR(pcm512x->sclk)) {
1573*4882a593Smuzhiyun ret = clk_prepare_enable(pcm512x->sclk);
1574*4882a593Smuzhiyun if (ret != 0) {
1575*4882a593Smuzhiyun dev_err(dev, "Failed to enable SCLK: %d\n", ret);
1576*4882a593Smuzhiyun goto err;
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun }
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun /* Default to standby mode */
1581*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
1582*4882a593Smuzhiyun PCM512x_RQST, PCM512x_RQST);
1583*4882a593Smuzhiyun if (ret != 0) {
1584*4882a593Smuzhiyun dev_err(dev, "Failed to request standby: %d\n",
1585*4882a593Smuzhiyun ret);
1586*4882a593Smuzhiyun goto err_clk;
1587*4882a593Smuzhiyun }
1588*4882a593Smuzhiyun
1589*4882a593Smuzhiyun pm_runtime_set_active(dev);
1590*4882a593Smuzhiyun pm_runtime_enable(dev);
1591*4882a593Smuzhiyun pm_runtime_idle(dev);
1592*4882a593Smuzhiyun
1593*4882a593Smuzhiyun #ifdef CONFIG_OF
1594*4882a593Smuzhiyun if (dev->of_node) {
1595*4882a593Smuzhiyun const struct device_node *np = dev->of_node;
1596*4882a593Smuzhiyun u32 val;
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun if (of_property_read_u32(np, "pll-in", &val) >= 0) {
1599*4882a593Smuzhiyun if (val > 6) {
1600*4882a593Smuzhiyun dev_err(dev, "Invalid pll-in\n");
1601*4882a593Smuzhiyun ret = -EINVAL;
1602*4882a593Smuzhiyun goto err_clk;
1603*4882a593Smuzhiyun }
1604*4882a593Smuzhiyun pcm512x->pll_in = val;
1605*4882a593Smuzhiyun }
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun if (of_property_read_u32(np, "pll-out", &val) >= 0) {
1608*4882a593Smuzhiyun if (val > 6) {
1609*4882a593Smuzhiyun dev_err(dev, "Invalid pll-out\n");
1610*4882a593Smuzhiyun ret = -EINVAL;
1611*4882a593Smuzhiyun goto err_clk;
1612*4882a593Smuzhiyun }
1613*4882a593Smuzhiyun pcm512x->pll_out = val;
1614*4882a593Smuzhiyun }
1615*4882a593Smuzhiyun
1616*4882a593Smuzhiyun if (!pcm512x->pll_in != !pcm512x->pll_out) {
1617*4882a593Smuzhiyun dev_err(dev,
1618*4882a593Smuzhiyun "Error: both pll-in and pll-out, or none\n");
1619*4882a593Smuzhiyun ret = -EINVAL;
1620*4882a593Smuzhiyun goto err_clk;
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) {
1623*4882a593Smuzhiyun dev_err(dev, "Error: pll-in == pll-out\n");
1624*4882a593Smuzhiyun ret = -EINVAL;
1625*4882a593Smuzhiyun goto err_clk;
1626*4882a593Smuzhiyun }
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun #endif
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun ret = devm_snd_soc_register_component(dev, &pcm512x_component_driver,
1631*4882a593Smuzhiyun &pcm512x_dai, 1);
1632*4882a593Smuzhiyun if (ret != 0) {
1633*4882a593Smuzhiyun dev_err(dev, "Failed to register CODEC: %d\n", ret);
1634*4882a593Smuzhiyun goto err_pm;
1635*4882a593Smuzhiyun }
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun return 0;
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun err_pm:
1640*4882a593Smuzhiyun pm_runtime_disable(dev);
1641*4882a593Smuzhiyun err_clk:
1642*4882a593Smuzhiyun if (!IS_ERR(pcm512x->sclk))
1643*4882a593Smuzhiyun clk_disable_unprepare(pcm512x->sclk);
1644*4882a593Smuzhiyun err:
1645*4882a593Smuzhiyun regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
1646*4882a593Smuzhiyun pcm512x->supplies);
1647*4882a593Smuzhiyun return ret;
1648*4882a593Smuzhiyun }
1649*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pcm512x_probe);
1650*4882a593Smuzhiyun
pcm512x_remove(struct device * dev)1651*4882a593Smuzhiyun void pcm512x_remove(struct device *dev)
1652*4882a593Smuzhiyun {
1653*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
1654*4882a593Smuzhiyun
1655*4882a593Smuzhiyun pm_runtime_disable(dev);
1656*4882a593Smuzhiyun if (!IS_ERR(pcm512x->sclk))
1657*4882a593Smuzhiyun clk_disable_unprepare(pcm512x->sclk);
1658*4882a593Smuzhiyun regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
1659*4882a593Smuzhiyun pcm512x->supplies);
1660*4882a593Smuzhiyun }
1661*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pcm512x_remove);
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun #ifdef CONFIG_PM
pcm512x_suspend(struct device * dev)1664*4882a593Smuzhiyun static int pcm512x_suspend(struct device *dev)
1665*4882a593Smuzhiyun {
1666*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
1667*4882a593Smuzhiyun int ret;
1668*4882a593Smuzhiyun
1669*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
1670*4882a593Smuzhiyun PCM512x_RQPD, PCM512x_RQPD);
1671*4882a593Smuzhiyun if (ret != 0) {
1672*4882a593Smuzhiyun dev_err(dev, "Failed to request power down: %d\n", ret);
1673*4882a593Smuzhiyun return ret;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
1677*4882a593Smuzhiyun pcm512x->supplies);
1678*4882a593Smuzhiyun if (ret != 0) {
1679*4882a593Smuzhiyun dev_err(dev, "Failed to disable supplies: %d\n", ret);
1680*4882a593Smuzhiyun return ret;
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun if (!IS_ERR(pcm512x->sclk))
1684*4882a593Smuzhiyun clk_disable_unprepare(pcm512x->sclk);
1685*4882a593Smuzhiyun
1686*4882a593Smuzhiyun return 0;
1687*4882a593Smuzhiyun }
1688*4882a593Smuzhiyun
pcm512x_resume(struct device * dev)1689*4882a593Smuzhiyun static int pcm512x_resume(struct device *dev)
1690*4882a593Smuzhiyun {
1691*4882a593Smuzhiyun struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
1692*4882a593Smuzhiyun int ret;
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun if (!IS_ERR(pcm512x->sclk)) {
1695*4882a593Smuzhiyun ret = clk_prepare_enable(pcm512x->sclk);
1696*4882a593Smuzhiyun if (ret != 0) {
1697*4882a593Smuzhiyun dev_err(dev, "Failed to enable SCLK: %d\n", ret);
1698*4882a593Smuzhiyun return ret;
1699*4882a593Smuzhiyun }
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
1703*4882a593Smuzhiyun pcm512x->supplies);
1704*4882a593Smuzhiyun if (ret != 0) {
1705*4882a593Smuzhiyun dev_err(dev, "Failed to enable supplies: %d\n", ret);
1706*4882a593Smuzhiyun return ret;
1707*4882a593Smuzhiyun }
1708*4882a593Smuzhiyun
1709*4882a593Smuzhiyun regcache_cache_only(pcm512x->regmap, false);
1710*4882a593Smuzhiyun ret = regcache_sync(pcm512x->regmap);
1711*4882a593Smuzhiyun if (ret != 0) {
1712*4882a593Smuzhiyun dev_err(dev, "Failed to sync cache: %d\n", ret);
1713*4882a593Smuzhiyun return ret;
1714*4882a593Smuzhiyun }
1715*4882a593Smuzhiyun
1716*4882a593Smuzhiyun ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
1717*4882a593Smuzhiyun PCM512x_RQPD, 0);
1718*4882a593Smuzhiyun if (ret != 0) {
1719*4882a593Smuzhiyun dev_err(dev, "Failed to remove power down: %d\n", ret);
1720*4882a593Smuzhiyun return ret;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun return 0;
1724*4882a593Smuzhiyun }
1725*4882a593Smuzhiyun #endif
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun const struct dev_pm_ops pcm512x_pm_ops = {
1728*4882a593Smuzhiyun SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
1729*4882a593Smuzhiyun };
1730*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pcm512x_pm_ops);
1731*4882a593Smuzhiyun
1732*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC PCM512x codec driver");
1733*4882a593Smuzhiyun MODULE_AUTHOR("Mark Brown <broonie@kernel.org>");
1734*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1735