xref: /openbmc/linux/sound/soc/codecs/pcm512x.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25a3af129SMark Brown /*
35a3af129SMark Brown  * Driver for the PCM512x CODECs
45a3af129SMark Brown  *
5da924c3aSMark Brown  * Author:	Mark Brown <broonie@kernel.org>
65a3af129SMark Brown  *		Copyright 2014 Linaro Ltd
75a3af129SMark Brown  */
85a3af129SMark Brown 
95a3af129SMark Brown 
105a3af129SMark Brown #include <linux/init.h>
115a3af129SMark Brown #include <linux/module.h>
125a3af129SMark Brown #include <linux/clk.h>
13d48502eaSJavi Merino #include <linux/kernel.h>
145a3af129SMark Brown #include <linux/pm_runtime.h>
155a3af129SMark Brown #include <linux/regmap.h>
165a3af129SMark Brown #include <linux/regulator/consumer.h>
17f086ba9dSPeter Rosin #include <linux/gcd.h>
185a3af129SMark Brown #include <sound/soc.h>
195a3af129SMark Brown #include <sound/soc-dapm.h>
2081249307SPeter Rosin #include <sound/pcm_params.h>
215a3af129SMark Brown #include <sound/tlv.h>
225a3af129SMark Brown 
235a3af129SMark Brown #include "pcm512x.h"
245a3af129SMark Brown 
255a3af129SMark Brown #define PCM512x_NUM_SUPPLIES 3
2606d0ffccSMark Brown static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
275a3af129SMark Brown 	"AVDD",
285a3af129SMark Brown 	"DVDD",
295a3af129SMark Brown 	"CPVDD",
305a3af129SMark Brown };
315a3af129SMark Brown 
325a3af129SMark Brown struct pcm512x_priv {
335a3af129SMark Brown 	struct regmap *regmap;
345a3af129SMark Brown 	struct clk *sclk;
355a3af129SMark Brown 	struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
365a3af129SMark Brown 	struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
3781249307SPeter Rosin 	int fmt;
38f086ba9dSPeter Rosin 	int pll_in;
39f086ba9dSPeter Rosin 	int pll_out;
40f086ba9dSPeter Rosin 	int pll_r;
41f086ba9dSPeter Rosin 	int pll_j;
42f086ba9dSPeter Rosin 	int pll_d;
43f086ba9dSPeter Rosin 	int pll_p;
44f086ba9dSPeter Rosin 	unsigned long real_pll;
45f29933c9SPeter Rosin 	unsigned long overclock_pll;
46f29933c9SPeter Rosin 	unsigned long overclock_dac;
47f29933c9SPeter Rosin 	unsigned long overclock_dsp;
483500f1c5SDimitris Papavasiliou 	int mute;
493500f1c5SDimitris Papavasiliou 	struct mutex mutex;
50ccc8d6c7SDimitris Papavasiliou 	unsigned int bclk_ratio;
515a3af129SMark Brown };
525a3af129SMark Brown 
535a3af129SMark Brown /*
545a3af129SMark Brown  * We can't use the same notifier block for more than one supply and
555a3af129SMark Brown  * there's no way I can see to get from a callback to the caller
565a3af129SMark Brown  * except container_of().
575a3af129SMark Brown  */
585a3af129SMark Brown #define PCM512x_REGULATOR_EVENT(n) \
595a3af129SMark Brown static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
605a3af129SMark Brown 				      unsigned long event, void *data)    \
615a3af129SMark Brown { \
625a3af129SMark Brown 	struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
635a3af129SMark Brown 						    supply_nb[n]); \
645a3af129SMark Brown 	if (event & REGULATOR_EVENT_DISABLE) { \
655a3af129SMark Brown 		regcache_mark_dirty(pcm512x->regmap);	\
665a3af129SMark Brown 		regcache_cache_only(pcm512x->regmap, true);	\
675a3af129SMark Brown 	} \
685a3af129SMark Brown 	return 0; \
695a3af129SMark Brown }
705a3af129SMark Brown 
715a3af129SMark Brown PCM512x_REGULATOR_EVENT(0)
725a3af129SMark Brown PCM512x_REGULATOR_EVENT(1)
735a3af129SMark Brown PCM512x_REGULATOR_EVENT(2)
745a3af129SMark Brown 
755a3af129SMark Brown static const struct reg_default pcm512x_reg_defaults[] = {
765a3af129SMark Brown 	{ PCM512x_RESET,             0x00 },
775a3af129SMark Brown 	{ PCM512x_POWER,             0x00 },
785a3af129SMark Brown 	{ PCM512x_MUTE,              0x00 },
795a3af129SMark Brown 	{ PCM512x_DSP,               0x00 },
805a3af129SMark Brown 	{ PCM512x_PLL_REF,           0x00 },
8181249307SPeter Rosin 	{ PCM512x_DAC_REF,           0x00 },
825a3af129SMark Brown 	{ PCM512x_DAC_ROUTING,       0x11 },
835a3af129SMark Brown 	{ PCM512x_DSP_PROGRAM,       0x01 },
845a3af129SMark Brown 	{ PCM512x_CLKDET,            0x00 },
855a3af129SMark Brown 	{ PCM512x_AUTO_MUTE,         0x00 },
865a3af129SMark Brown 	{ PCM512x_ERROR_DETECT,      0x00 },
875a3af129SMark Brown 	{ PCM512x_DIGITAL_VOLUME_1,  0x00 },
885a3af129SMark Brown 	{ PCM512x_DIGITAL_VOLUME_2,  0x30 },
895a3af129SMark Brown 	{ PCM512x_DIGITAL_VOLUME_3,  0x30 },
905a3af129SMark Brown 	{ PCM512x_DIGITAL_MUTE_1,    0x22 },
915a3af129SMark Brown 	{ PCM512x_DIGITAL_MUTE_2,    0x00 },
925a3af129SMark Brown 	{ PCM512x_DIGITAL_MUTE_3,    0x07 },
93806d6466SMark Brown 	{ PCM512x_OUTPUT_AMPLITUDE,  0x00 },
94806d6466SMark Brown 	{ PCM512x_ANALOG_GAIN_CTRL,  0x00 },
95806d6466SMark Brown 	{ PCM512x_UNDERVOLTAGE_PROT, 0x00 },
96806d6466SMark Brown 	{ PCM512x_ANALOG_MUTE_CTRL,  0x00 },
97806d6466SMark Brown 	{ PCM512x_ANALOG_GAIN_BOOST, 0x00 },
98806d6466SMark Brown 	{ PCM512x_VCOM_CTRL_1,       0x00 },
99806d6466SMark Brown 	{ PCM512x_VCOM_CTRL_2,       0x01 },
10081249307SPeter Rosin 	{ PCM512x_BCLK_LRCLK_CFG,    0x00 },
10181249307SPeter Rosin 	{ PCM512x_MASTER_MODE,       0x7c },
1027c4e1119SPeter Rosin 	{ PCM512x_GPIO_DACIN,        0x00 },
103f086ba9dSPeter Rosin 	{ PCM512x_GPIO_PLLIN,        0x00 },
10481249307SPeter Rosin 	{ PCM512x_SYNCHRONIZE,       0x10 },
105f086ba9dSPeter Rosin 	{ PCM512x_PLL_COEFF_0,       0x00 },
106f086ba9dSPeter Rosin 	{ PCM512x_PLL_COEFF_1,       0x00 },
107f086ba9dSPeter Rosin 	{ PCM512x_PLL_COEFF_2,       0x00 },
108f086ba9dSPeter Rosin 	{ PCM512x_PLL_COEFF_3,       0x00 },
109f086ba9dSPeter Rosin 	{ PCM512x_PLL_COEFF_4,       0x00 },
11081249307SPeter Rosin 	{ PCM512x_DSP_CLKDIV,        0x00 },
11181249307SPeter Rosin 	{ PCM512x_DAC_CLKDIV,        0x00 },
11281249307SPeter Rosin 	{ PCM512x_NCP_CLKDIV,        0x00 },
11381249307SPeter Rosin 	{ PCM512x_OSR_CLKDIV,        0x00 },
11481249307SPeter Rosin 	{ PCM512x_MASTER_CLKDIV_1,   0x00 },
11581249307SPeter Rosin 	{ PCM512x_MASTER_CLKDIV_2,   0x00 },
11681249307SPeter Rosin 	{ PCM512x_FS_SPEED_MODE,     0x00 },
11781249307SPeter Rosin 	{ PCM512x_IDAC_1,            0x01 },
11881249307SPeter Rosin 	{ PCM512x_IDAC_2,            0x00 },
1193f4b57adSPeter Rosin 	{ PCM512x_I2S_1,             0x02 },
1203f4b57adSPeter Rosin 	{ PCM512x_I2S_2,             0x00 },
1215a3af129SMark Brown };
1225a3af129SMark Brown 
pcm512x_readable(struct device * dev,unsigned int reg)1235a3af129SMark Brown static bool pcm512x_readable(struct device *dev, unsigned int reg)
1245a3af129SMark Brown {
1255a3af129SMark Brown 	switch (reg) {
1265a3af129SMark Brown 	case PCM512x_RESET:
1275a3af129SMark Brown 	case PCM512x_POWER:
1285a3af129SMark Brown 	case PCM512x_MUTE:
1295a3af129SMark Brown 	case PCM512x_PLL_EN:
1305a3af129SMark Brown 	case PCM512x_SPI_MISO_FUNCTION:
1315a3af129SMark Brown 	case PCM512x_DSP:
1325a3af129SMark Brown 	case PCM512x_GPIO_EN:
1335a3af129SMark Brown 	case PCM512x_BCLK_LRCLK_CFG:
1345a3af129SMark Brown 	case PCM512x_DSP_GPIO_INPUT:
1355a3af129SMark Brown 	case PCM512x_MASTER_MODE:
1365a3af129SMark Brown 	case PCM512x_PLL_REF:
13781249307SPeter Rosin 	case PCM512x_DAC_REF:
1387c4e1119SPeter Rosin 	case PCM512x_GPIO_DACIN:
139f086ba9dSPeter Rosin 	case PCM512x_GPIO_PLLIN:
14081249307SPeter Rosin 	case PCM512x_SYNCHRONIZE:
1415a3af129SMark Brown 	case PCM512x_PLL_COEFF_0:
1425a3af129SMark Brown 	case PCM512x_PLL_COEFF_1:
1435a3af129SMark Brown 	case PCM512x_PLL_COEFF_2:
1445a3af129SMark Brown 	case PCM512x_PLL_COEFF_3:
1455a3af129SMark Brown 	case PCM512x_PLL_COEFF_4:
1465a3af129SMark Brown 	case PCM512x_DSP_CLKDIV:
1475a3af129SMark Brown 	case PCM512x_DAC_CLKDIV:
1485a3af129SMark Brown 	case PCM512x_NCP_CLKDIV:
1495a3af129SMark Brown 	case PCM512x_OSR_CLKDIV:
1505a3af129SMark Brown 	case PCM512x_MASTER_CLKDIV_1:
1515a3af129SMark Brown 	case PCM512x_MASTER_CLKDIV_2:
1525a3af129SMark Brown 	case PCM512x_FS_SPEED_MODE:
1535a3af129SMark Brown 	case PCM512x_IDAC_1:
1545a3af129SMark Brown 	case PCM512x_IDAC_2:
1555a3af129SMark Brown 	case PCM512x_ERROR_DETECT:
1565a3af129SMark Brown 	case PCM512x_I2S_1:
1575a3af129SMark Brown 	case PCM512x_I2S_2:
1585a3af129SMark Brown 	case PCM512x_DAC_ROUTING:
1595a3af129SMark Brown 	case PCM512x_DSP_PROGRAM:
1605a3af129SMark Brown 	case PCM512x_CLKDET:
1615a3af129SMark Brown 	case PCM512x_AUTO_MUTE:
1625a3af129SMark Brown 	case PCM512x_DIGITAL_VOLUME_1:
1635a3af129SMark Brown 	case PCM512x_DIGITAL_VOLUME_2:
1645a3af129SMark Brown 	case PCM512x_DIGITAL_VOLUME_3:
1655a3af129SMark Brown 	case PCM512x_DIGITAL_MUTE_1:
1665a3af129SMark Brown 	case PCM512x_DIGITAL_MUTE_2:
1675a3af129SMark Brown 	case PCM512x_DIGITAL_MUTE_3:
1685a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_1:
1695a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_2:
1705a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_3:
1715a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_4:
1725a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_5:
1735a3af129SMark Brown 	case PCM512x_GPIO_OUTPUT_6:
1745a3af129SMark Brown 	case PCM512x_GPIO_CONTROL_1:
1755a3af129SMark Brown 	case PCM512x_GPIO_CONTROL_2:
1765a3af129SMark Brown 	case PCM512x_OVERFLOW:
1775a3af129SMark Brown 	case PCM512x_RATE_DET_1:
1785a3af129SMark Brown 	case PCM512x_RATE_DET_2:
1795a3af129SMark Brown 	case PCM512x_RATE_DET_3:
1805a3af129SMark Brown 	case PCM512x_RATE_DET_4:
181f086ba9dSPeter Rosin 	case PCM512x_CLOCK_STATUS:
1825a3af129SMark Brown 	case PCM512x_ANALOG_MUTE_DET:
1835a3af129SMark Brown 	case PCM512x_GPIN:
1845a3af129SMark Brown 	case PCM512x_DIGITAL_MUTE_DET:
185806d6466SMark Brown 	case PCM512x_OUTPUT_AMPLITUDE:
186806d6466SMark Brown 	case PCM512x_ANALOG_GAIN_CTRL:
187806d6466SMark Brown 	case PCM512x_UNDERVOLTAGE_PROT:
188806d6466SMark Brown 	case PCM512x_ANALOG_MUTE_CTRL:
189806d6466SMark Brown 	case PCM512x_ANALOG_GAIN_BOOST:
190806d6466SMark Brown 	case PCM512x_VCOM_CTRL_1:
191806d6466SMark Brown 	case PCM512x_VCOM_CTRL_2:
192806d6466SMark Brown 	case PCM512x_CRAM_CTRL:
193f086ba9dSPeter Rosin 	case PCM512x_FLEX_A:
194f086ba9dSPeter Rosin 	case PCM512x_FLEX_B:
1955a3af129SMark Brown 		return true;
1965a3af129SMark Brown 	default:
197806d6466SMark Brown 		/* There are 256 raw register addresses */
198806d6466SMark Brown 		return reg < 0xff;
1995a3af129SMark Brown 	}
2005a3af129SMark Brown }
2015a3af129SMark Brown 
pcm512x_volatile(struct device * dev,unsigned int reg)2025a3af129SMark Brown static bool pcm512x_volatile(struct device *dev, unsigned int reg)
2035a3af129SMark Brown {
2045a3af129SMark Brown 	switch (reg) {
2055a3af129SMark Brown 	case PCM512x_PLL_EN:
2065a3af129SMark Brown 	case PCM512x_OVERFLOW:
2075a3af129SMark Brown 	case PCM512x_RATE_DET_1:
2085a3af129SMark Brown 	case PCM512x_RATE_DET_2:
2095a3af129SMark Brown 	case PCM512x_RATE_DET_3:
2105a3af129SMark Brown 	case PCM512x_RATE_DET_4:
211f086ba9dSPeter Rosin 	case PCM512x_CLOCK_STATUS:
2125a3af129SMark Brown 	case PCM512x_ANALOG_MUTE_DET:
2135a3af129SMark Brown 	case PCM512x_GPIN:
2145a3af129SMark Brown 	case PCM512x_DIGITAL_MUTE_DET:
215806d6466SMark Brown 	case PCM512x_CRAM_CTRL:
2165a3af129SMark Brown 		return true;
2175a3af129SMark Brown 	default:
218806d6466SMark Brown 		/* There are 256 raw register addresses */
219806d6466SMark Brown 		return reg < 0xff;
2205a3af129SMark Brown 	}
2215a3af129SMark Brown }
2225a3af129SMark Brown 
pcm512x_overclock_pll_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)223f29933c9SPeter Rosin static int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
224f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
225f29933c9SPeter Rosin {
2265bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2275bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
228f29933c9SPeter Rosin 
229f29933c9SPeter Rosin 	ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
230f29933c9SPeter Rosin 	return 0;
231f29933c9SPeter Rosin }
232f29933c9SPeter Rosin 
pcm512x_overclock_pll_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)233f29933c9SPeter Rosin static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
234f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
235f29933c9SPeter Rosin {
2365bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2375bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
238f29933c9SPeter Rosin 
2395bdef14aSKuninori Morimoto 	switch (snd_soc_component_get_bias_level(component)) {
240f29933c9SPeter Rosin 	case SND_SOC_BIAS_OFF:
241f29933c9SPeter Rosin 	case SND_SOC_BIAS_STANDBY:
242f29933c9SPeter Rosin 		break;
243f29933c9SPeter Rosin 	default:
244f29933c9SPeter Rosin 		return -EBUSY;
245f29933c9SPeter Rosin 	}
246f29933c9SPeter Rosin 
247f29933c9SPeter Rosin 	pcm512x->overclock_pll = ucontrol->value.integer.value[0];
248f29933c9SPeter Rosin 	return 0;
249f29933c9SPeter Rosin }
250f29933c9SPeter Rosin 
pcm512x_overclock_dsp_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)251f29933c9SPeter Rosin static int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
252f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
253f29933c9SPeter Rosin {
2545bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2555bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
256f29933c9SPeter Rosin 
257f29933c9SPeter Rosin 	ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
258f29933c9SPeter Rosin 	return 0;
259f29933c9SPeter Rosin }
260f29933c9SPeter Rosin 
pcm512x_overclock_dsp_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)261f29933c9SPeter Rosin static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
262f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
263f29933c9SPeter Rosin {
2645bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2655bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
266f29933c9SPeter Rosin 
2675bdef14aSKuninori Morimoto 	switch (snd_soc_component_get_bias_level(component)) {
268f29933c9SPeter Rosin 	case SND_SOC_BIAS_OFF:
269f29933c9SPeter Rosin 	case SND_SOC_BIAS_STANDBY:
270f29933c9SPeter Rosin 		break;
271f29933c9SPeter Rosin 	default:
272f29933c9SPeter Rosin 		return -EBUSY;
273f29933c9SPeter Rosin 	}
274f29933c9SPeter Rosin 
275f29933c9SPeter Rosin 	pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
276f29933c9SPeter Rosin 	return 0;
277f29933c9SPeter Rosin }
278f29933c9SPeter Rosin 
pcm512x_overclock_dac_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)279f29933c9SPeter Rosin static int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
280f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
281f29933c9SPeter Rosin {
2825bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2835bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
284f29933c9SPeter Rosin 
285f29933c9SPeter Rosin 	ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
286f29933c9SPeter Rosin 	return 0;
287f29933c9SPeter Rosin }
288f29933c9SPeter Rosin 
pcm512x_overclock_dac_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)289f29933c9SPeter Rosin static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
290f29933c9SPeter Rosin 				     struct snd_ctl_elem_value *ucontrol)
291f29933c9SPeter Rosin {
2925bdef14aSKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2935bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
294f29933c9SPeter Rosin 
2955bdef14aSKuninori Morimoto 	switch (snd_soc_component_get_bias_level(component)) {
296f29933c9SPeter Rosin 	case SND_SOC_BIAS_OFF:
297f29933c9SPeter Rosin 	case SND_SOC_BIAS_STANDBY:
298f29933c9SPeter Rosin 		break;
299f29933c9SPeter Rosin 	default:
300f29933c9SPeter Rosin 		return -EBUSY;
301f29933c9SPeter Rosin 	}
302f29933c9SPeter Rosin 
303f29933c9SPeter Rosin 	pcm512x->overclock_dac = ucontrol->value.integer.value[0];
304f29933c9SPeter Rosin 	return 0;
305f29933c9SPeter Rosin }
306f29933c9SPeter Rosin 
3075a3af129SMark Brown static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
3085be2fc20SMark Brown static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
3095be2fc20SMark Brown static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
3105a3af129SMark Brown 
31106d0ffccSMark Brown static const char * const pcm512x_dsp_program_texts[] = {
3125a3af129SMark Brown 	"FIR interpolation with de-emphasis",
3135a3af129SMark Brown 	"Low latency IIR with de-emphasis",
3145a3af129SMark Brown 	"High attenuation with de-emphasis",
3153a8e5019SPeter Rosin 	"Fixed process flow",
3165a3af129SMark Brown 	"Ringing-less low latency FIR",
3175a3af129SMark Brown };
3185a3af129SMark Brown 
3195a3af129SMark Brown static const unsigned int pcm512x_dsp_program_values[] = {
3205a3af129SMark Brown 	1,
3215a3af129SMark Brown 	2,
3225a3af129SMark Brown 	3,
3235a3af129SMark Brown 	5,
3245a3af129SMark Brown 	7,
3255a3af129SMark Brown };
3265a3af129SMark Brown 
327e97db9abSMark Brown static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
3285a3af129SMark Brown 				  PCM512x_DSP_PROGRAM, 0, 0x1f,
3295a3af129SMark Brown 				  pcm512x_dsp_program_texts,
3305a3af129SMark Brown 				  pcm512x_dsp_program_values);
3315a3af129SMark Brown 
33206d0ffccSMark Brown static const char * const pcm512x_clk_missing_text[] = {
3335a3af129SMark Brown 	"1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
3345a3af129SMark Brown };
3355a3af129SMark Brown 
3365a3af129SMark Brown static const struct soc_enum pcm512x_clk_missing =
3375a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_CLKDET, 0,  8, pcm512x_clk_missing_text);
3385a3af129SMark Brown 
33906d0ffccSMark Brown static const char * const pcm512x_autom_text[] = {
3405a3af129SMark Brown 	"21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
3415a3af129SMark Brown };
3425a3af129SMark Brown 
3435a3af129SMark Brown static const struct soc_enum pcm512x_autom_l =
3445a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
3455a3af129SMark Brown 			pcm512x_autom_text);
3465a3af129SMark Brown 
3475a3af129SMark Brown static const struct soc_enum pcm512x_autom_r =
3485a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
3495a3af129SMark Brown 			pcm512x_autom_text);
3505a3af129SMark Brown 
35106d0ffccSMark Brown static const char * const pcm512x_ramp_rate_text[] = {
3525a3af129SMark Brown 	"1 sample/update", "2 samples/update", "4 samples/update",
3535a3af129SMark Brown 	"Immediate"
3545a3af129SMark Brown };
3555a3af129SMark Brown 
3565a3af129SMark Brown static const struct soc_enum pcm512x_vndf =
3575a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
3585a3af129SMark Brown 			pcm512x_ramp_rate_text);
3595a3af129SMark Brown 
3605a3af129SMark Brown static const struct soc_enum pcm512x_vnuf =
3615a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
3625a3af129SMark Brown 			pcm512x_ramp_rate_text);
3635a3af129SMark Brown 
3645a3af129SMark Brown static const struct soc_enum pcm512x_vedf =
3655a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
3665a3af129SMark Brown 			pcm512x_ramp_rate_text);
3675a3af129SMark Brown 
36806d0ffccSMark Brown static const char * const pcm512x_ramp_step_text[] = {
3695a3af129SMark Brown 	"4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
3705a3af129SMark Brown };
3715a3af129SMark Brown 
3725a3af129SMark Brown static const struct soc_enum pcm512x_vnds =
3735a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
3745a3af129SMark Brown 			pcm512x_ramp_step_text);
3755a3af129SMark Brown 
3765a3af129SMark Brown static const struct soc_enum pcm512x_vnus =
3775a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
3785a3af129SMark Brown 			pcm512x_ramp_step_text);
3795a3af129SMark Brown 
3805a3af129SMark Brown static const struct soc_enum pcm512x_veds =
3815a3af129SMark Brown 	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
3825a3af129SMark Brown 			pcm512x_ramp_step_text);
3835a3af129SMark Brown 
pcm512x_update_mute(struct pcm512x_priv * pcm512x)3843500f1c5SDimitris Papavasiliou static int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
3853500f1c5SDimitris Papavasiliou {
3863500f1c5SDimitris Papavasiliou 	return regmap_update_bits(
3873500f1c5SDimitris Papavasiliou 		pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
3883500f1c5SDimitris Papavasiliou 		(!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
3893500f1c5SDimitris Papavasiliou 		| (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
3903500f1c5SDimitris Papavasiliou }
3913500f1c5SDimitris Papavasiliou 
pcm512x_digital_playback_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3923500f1c5SDimitris Papavasiliou static int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
3933500f1c5SDimitris Papavasiliou 					       struct snd_ctl_elem_value *ucontrol)
3943500f1c5SDimitris Papavasiliou {
3953500f1c5SDimitris Papavasiliou 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3963500f1c5SDimitris Papavasiliou 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
3973500f1c5SDimitris Papavasiliou 
3983500f1c5SDimitris Papavasiliou 	mutex_lock(&pcm512x->mutex);
3993500f1c5SDimitris Papavasiliou 	ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
4003500f1c5SDimitris Papavasiliou 	ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
4013500f1c5SDimitris Papavasiliou 	mutex_unlock(&pcm512x->mutex);
4023500f1c5SDimitris Papavasiliou 
4033500f1c5SDimitris Papavasiliou 	return 0;
4043500f1c5SDimitris Papavasiliou }
4053500f1c5SDimitris Papavasiliou 
pcm512x_digital_playback_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4063500f1c5SDimitris Papavasiliou static int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
4073500f1c5SDimitris Papavasiliou 					       struct snd_ctl_elem_value *ucontrol)
4083500f1c5SDimitris Papavasiliou {
4093500f1c5SDimitris Papavasiliou 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
4103500f1c5SDimitris Papavasiliou 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
4113500f1c5SDimitris Papavasiliou 	int ret, changed = 0;
4123500f1c5SDimitris Papavasiliou 
4133500f1c5SDimitris Papavasiliou 	mutex_lock(&pcm512x->mutex);
4143500f1c5SDimitris Papavasiliou 
4153500f1c5SDimitris Papavasiliou 	if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
4163500f1c5SDimitris Papavasiliou 		pcm512x->mute ^= 0x4;
4173500f1c5SDimitris Papavasiliou 		changed = 1;
4183500f1c5SDimitris Papavasiliou 	}
4193500f1c5SDimitris Papavasiliou 	if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
4203500f1c5SDimitris Papavasiliou 		pcm512x->mute ^= 0x2;
4213500f1c5SDimitris Papavasiliou 		changed = 1;
4223500f1c5SDimitris Papavasiliou 	}
4233500f1c5SDimitris Papavasiliou 
4243500f1c5SDimitris Papavasiliou 	if (changed) {
4253500f1c5SDimitris Papavasiliou 		ret = pcm512x_update_mute(pcm512x);
4263500f1c5SDimitris Papavasiliou 		if (ret != 0) {
4273500f1c5SDimitris Papavasiliou 			dev_err(component->dev,
4283500f1c5SDimitris Papavasiliou 				"Failed to update digital mute: %d\n", ret);
4293500f1c5SDimitris Papavasiliou 			mutex_unlock(&pcm512x->mutex);
4303500f1c5SDimitris Papavasiliou 			return ret;
4313500f1c5SDimitris Papavasiliou 		}
4323500f1c5SDimitris Papavasiliou 	}
4333500f1c5SDimitris Papavasiliou 
4343500f1c5SDimitris Papavasiliou 	mutex_unlock(&pcm512x->mutex);
4353500f1c5SDimitris Papavasiliou 
4363500f1c5SDimitris Papavasiliou 	return changed;
4373500f1c5SDimitris Papavasiliou }
4383500f1c5SDimitris Papavasiliou 
4395a3af129SMark Brown static const struct snd_kcontrol_new pcm512x_controls[] = {
4401c6d3680SMark Brown SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
4415a3af129SMark Brown 		 PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
4424d9b13c7SHoward Mitchell SOC_DOUBLE_TLV("Analogue Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
4435be2fc20SMark Brown 	       PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
4444d9b13c7SHoward Mitchell SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
4455be2fc20SMark Brown 	       PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
4463500f1c5SDimitris Papavasiliou {
4473500f1c5SDimitris Papavasiliou 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4483500f1c5SDimitris Papavasiliou 	.name = "Digital Playback Switch",
4493500f1c5SDimitris Papavasiliou 	.index = 0,
4503500f1c5SDimitris Papavasiliou 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4513500f1c5SDimitris Papavasiliou 	.info = snd_ctl_boolean_stereo_info,
4523500f1c5SDimitris Papavasiliou 	.get = pcm512x_digital_playback_switch_get,
4533500f1c5SDimitris Papavasiliou 	.put = pcm512x_digital_playback_switch_put
4543500f1c5SDimitris Papavasiliou },
4555a3af129SMark Brown 
4565a3af129SMark Brown SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
45754581be7SLars-Peter Clausen SOC_ENUM("DSP Program", pcm512x_dsp_program),
4585a3af129SMark Brown 
4595a3af129SMark Brown SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
4605a3af129SMark Brown SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
4615a3af129SMark Brown SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
4625a3af129SMark Brown SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
4635a3af129SMark Brown 	   PCM512x_ACTL_SHIFT, 1, 0),
4645a3af129SMark Brown SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
465376dc490SPeter Rosin 	   PCM512x_AMRE_SHIFT, 1, 0),
4665a3af129SMark Brown 
4675a3af129SMark Brown SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
4685a3af129SMark Brown SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
4695a3af129SMark Brown SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
4705a3af129SMark Brown SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
4715a3af129SMark Brown SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
4725a3af129SMark Brown SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
473f29933c9SPeter Rosin 
474f29933c9SPeter Rosin SOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
475f29933c9SPeter Rosin 	       pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
476f29933c9SPeter Rosin SOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
477f29933c9SPeter Rosin 	       pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
478f29933c9SPeter Rosin SOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
479f29933c9SPeter Rosin 	       pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
4805a3af129SMark Brown };
4815a3af129SMark Brown 
4825a3af129SMark Brown static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
4835a3af129SMark Brown SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
4845a3af129SMark Brown SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
4855a3af129SMark Brown 
4865a3af129SMark Brown SND_SOC_DAPM_OUTPUT("OUTL"),
4875a3af129SMark Brown SND_SOC_DAPM_OUTPUT("OUTR"),
4885a3af129SMark Brown };
4895a3af129SMark Brown 
4905a3af129SMark Brown static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
4915a3af129SMark Brown 	{ "DACL", NULL, "Playback" },
4925a3af129SMark Brown 	{ "DACR", NULL, "Playback" },
4935a3af129SMark Brown 
4945a3af129SMark Brown 	{ "OUTL", NULL, "DACL" },
4955a3af129SMark Brown 	{ "OUTR", NULL, "DACR" },
4965a3af129SMark Brown };
4975a3af129SMark Brown 
pcm512x_pll_max(struct pcm512x_priv * pcm512x)498f29933c9SPeter Rosin static unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
499f29933c9SPeter Rosin {
500f29933c9SPeter Rosin 	return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
501f29933c9SPeter Rosin }
502f29933c9SPeter Rosin 
pcm512x_dsp_max(struct pcm512x_priv * pcm512x)503f29933c9SPeter Rosin static unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
504f29933c9SPeter Rosin {
505f29933c9SPeter Rosin 	return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
506f29933c9SPeter Rosin }
507f29933c9SPeter Rosin 
pcm512x_dac_max(struct pcm512x_priv * pcm512x,unsigned long rate)508f29933c9SPeter Rosin static unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
509f29933c9SPeter Rosin 				     unsigned long rate)
510f29933c9SPeter Rosin {
511f29933c9SPeter Rosin 	return rate + rate * pcm512x->overclock_dac / 100;
512f29933c9SPeter Rosin }
513f29933c9SPeter Rosin 
pcm512x_sck_max(struct pcm512x_priv * pcm512x)514f29933c9SPeter Rosin static unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
515f29933c9SPeter Rosin {
516f29933c9SPeter Rosin 	if (!pcm512x->pll_out)
517f29933c9SPeter Rosin 		return 25000000;
518f29933c9SPeter Rosin 	return pcm512x_pll_max(pcm512x);
519f29933c9SPeter Rosin }
520f29933c9SPeter Rosin 
pcm512x_ncp_target(struct pcm512x_priv * pcm512x,unsigned long dac_rate)521f29933c9SPeter Rosin static unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
522f29933c9SPeter Rosin 					unsigned long dac_rate)
523f29933c9SPeter Rosin {
524f29933c9SPeter Rosin 	/*
525f29933c9SPeter Rosin 	 * If the DAC is not actually overclocked, use the good old
526f29933c9SPeter Rosin 	 * NCP target rate...
527f29933c9SPeter Rosin 	 */
528f29933c9SPeter Rosin 	if (dac_rate <= 6144000)
529f29933c9SPeter Rosin 		return 1536000;
530f29933c9SPeter Rosin 	/*
531f29933c9SPeter Rosin 	 * ...but if the DAC is in fact overclocked, bump the NCP target
532f29933c9SPeter Rosin 	 * rate to get the recommended dividers even when overclocking.
533f29933c9SPeter Rosin 	 */
534f29933c9SPeter Rosin 	return pcm512x_dac_max(pcm512x, 1536000);
535f29933c9SPeter Rosin }
536f29933c9SPeter Rosin 
53781249307SPeter Rosin static const u32 pcm512x_dai_rates[] = {
53881249307SPeter Rosin 	8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
53981249307SPeter Rosin 	88200, 96000, 176400, 192000, 384000,
54081249307SPeter Rosin };
54181249307SPeter Rosin 
54281249307SPeter Rosin static const struct snd_pcm_hw_constraint_list constraints_slave = {
54381249307SPeter Rosin 	.count = ARRAY_SIZE(pcm512x_dai_rates),
54481249307SPeter Rosin 	.list  = pcm512x_dai_rates,
54581249307SPeter Rosin };
54681249307SPeter Rosin 
pcm512x_hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)547f086ba9dSPeter Rosin static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
548f086ba9dSPeter Rosin 				struct snd_pcm_hw_rule *rule)
549f086ba9dSPeter Rosin {
550f29933c9SPeter Rosin 	struct pcm512x_priv *pcm512x = rule->private;
5519c7da1a5SPeter Rosin 	struct snd_interval ranges[2];
552f086ba9dSPeter Rosin 	int frame_size;
553f086ba9dSPeter Rosin 
554f086ba9dSPeter Rosin 	frame_size = snd_soc_params_to_frame_size(params);
555f086ba9dSPeter Rosin 	if (frame_size < 0)
556f086ba9dSPeter Rosin 		return frame_size;
557f086ba9dSPeter Rosin 
5589c7da1a5SPeter Rosin 	switch (frame_size) {
5599c7da1a5SPeter Rosin 	case 32:
5609c7da1a5SPeter Rosin 		/* No hole when the frame size is 32. */
561f086ba9dSPeter Rosin 		return 0;
5629c7da1a5SPeter Rosin 	case 48:
5639c7da1a5SPeter Rosin 	case 64:
5649c7da1a5SPeter Rosin 		/* There is only one hole in the range of supported
5659c7da1a5SPeter Rosin 		 * rates, but it moves with the frame size.
5669c7da1a5SPeter Rosin 		 */
5679c7da1a5SPeter Rosin 		memset(ranges, 0, sizeof(ranges));
5689c7da1a5SPeter Rosin 		ranges[0].min = 8000;
569f29933c9SPeter Rosin 		ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
5709c7da1a5SPeter Rosin 		ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
5719c7da1a5SPeter Rosin 		ranges[1].max = 384000;
5729c7da1a5SPeter Rosin 		break;
5739c7da1a5SPeter Rosin 	default:
5749c7da1a5SPeter Rosin 		return -EINVAL;
5759c7da1a5SPeter Rosin 	}
576f086ba9dSPeter Rosin 
577f086ba9dSPeter Rosin 	return snd_interval_ranges(hw_param_interval(params, rule->var),
5789c7da1a5SPeter Rosin 				   ARRAY_SIZE(ranges), ranges, 0);
579f086ba9dSPeter Rosin }
580f086ba9dSPeter Rosin 
pcm512x_dai_startup_master(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)58181249307SPeter Rosin static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
58281249307SPeter Rosin 				      struct snd_soc_dai *dai)
58381249307SPeter Rosin {
5845bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
5855bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
58681249307SPeter Rosin 	struct device *dev = dai->dev;
58781249307SPeter Rosin 	struct snd_pcm_hw_constraint_ratnums *constraints_no_pll;
58881249307SPeter Rosin 	struct snd_ratnum *rats_no_pll;
58981249307SPeter Rosin 
59081249307SPeter Rosin 	if (IS_ERR(pcm512x->sclk)) {
59181249307SPeter Rosin 		dev_err(dev, "Need SCLK for master mode: %ld\n",
59281249307SPeter Rosin 			PTR_ERR(pcm512x->sclk));
59381249307SPeter Rosin 		return PTR_ERR(pcm512x->sclk);
59481249307SPeter Rosin 	}
59581249307SPeter Rosin 
596f086ba9dSPeter Rosin 	if (pcm512x->pll_out)
597f086ba9dSPeter Rosin 		return snd_pcm_hw_rule_add(substream->runtime, 0,
598f086ba9dSPeter Rosin 					   SNDRV_PCM_HW_PARAM_RATE,
599f086ba9dSPeter Rosin 					   pcm512x_hw_rule_rate,
600f29933c9SPeter Rosin 					   pcm512x,
601f086ba9dSPeter Rosin 					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
602f086ba9dSPeter Rosin 					   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
603f086ba9dSPeter Rosin 
60481249307SPeter Rosin 	constraints_no_pll = devm_kzalloc(dev, sizeof(*constraints_no_pll),
60581249307SPeter Rosin 					  GFP_KERNEL);
60681249307SPeter Rosin 	if (!constraints_no_pll)
60781249307SPeter Rosin 		return -ENOMEM;
60881249307SPeter Rosin 	constraints_no_pll->nrats = 1;
60981249307SPeter Rosin 	rats_no_pll = devm_kzalloc(dev, sizeof(*rats_no_pll), GFP_KERNEL);
61081249307SPeter Rosin 	if (!rats_no_pll)
61181249307SPeter Rosin 		return -ENOMEM;
61281249307SPeter Rosin 	constraints_no_pll->rats = rats_no_pll;
61381249307SPeter Rosin 	rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
61481249307SPeter Rosin 	rats_no_pll->den_min = 1;
61581249307SPeter Rosin 	rats_no_pll->den_max = 128;
61681249307SPeter Rosin 	rats_no_pll->den_step = 1;
61781249307SPeter Rosin 
61881249307SPeter Rosin 	return snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
61981249307SPeter Rosin 					     SNDRV_PCM_HW_PARAM_RATE,
62081249307SPeter Rosin 					     constraints_no_pll);
62181249307SPeter Rosin }
62281249307SPeter Rosin 
pcm512x_dai_startup_slave(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)62381249307SPeter Rosin static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream,
62481249307SPeter Rosin 				     struct snd_soc_dai *dai)
62581249307SPeter Rosin {
6265bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
6275bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
62881249307SPeter Rosin 	struct device *dev = dai->dev;
62981249307SPeter Rosin 	struct regmap *regmap = pcm512x->regmap;
63081249307SPeter Rosin 
63181249307SPeter Rosin 	if (IS_ERR(pcm512x->sclk)) {
63281249307SPeter Rosin 		dev_info(dev, "No SCLK, using BCLK: %ld\n",
63381249307SPeter Rosin 			 PTR_ERR(pcm512x->sclk));
63481249307SPeter Rosin 
63581249307SPeter Rosin 		/* Disable reporting of missing SCLK as an error */
63681249307SPeter Rosin 		regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
63781249307SPeter Rosin 				   PCM512x_IDCH, PCM512x_IDCH);
63881249307SPeter Rosin 
63981249307SPeter Rosin 		/* Switch PLL input to BCLK */
64081249307SPeter Rosin 		regmap_update_bits(regmap, PCM512x_PLL_REF,
64181249307SPeter Rosin 				   PCM512x_SREF, PCM512x_SREF_BCK);
64281249307SPeter Rosin 	}
64381249307SPeter Rosin 
64481249307SPeter Rosin 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
64581249307SPeter Rosin 					  SNDRV_PCM_HW_PARAM_RATE,
64681249307SPeter Rosin 					  &constraints_slave);
64781249307SPeter Rosin }
64881249307SPeter Rosin 
pcm512x_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)64981249307SPeter Rosin static int pcm512x_dai_startup(struct snd_pcm_substream *substream,
65081249307SPeter Rosin 			       struct snd_soc_dai *dai)
65181249307SPeter Rosin {
6525bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
6535bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
65481249307SPeter Rosin 
655e0dab089SMark Brown 	switch (pcm512x->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
656e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
657e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBP_CFC:
65881249307SPeter Rosin 		return pcm512x_dai_startup_master(substream, dai);
65981249307SPeter Rosin 
660e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBC_CFC:
66181249307SPeter Rosin 		return pcm512x_dai_startup_slave(substream, dai);
66281249307SPeter Rosin 
66381249307SPeter Rosin 	default:
66481249307SPeter Rosin 		return -EINVAL;
66581249307SPeter Rosin 	}
66681249307SPeter Rosin }
66781249307SPeter Rosin 
pcm512x_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)6685bdef14aSKuninori Morimoto static int pcm512x_set_bias_level(struct snd_soc_component *component,
6695a3af129SMark Brown 				  enum snd_soc_bias_level level)
6705a3af129SMark Brown {
6715bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = dev_get_drvdata(component->dev);
6725a3af129SMark Brown 	int ret;
6735a3af129SMark Brown 
6745a3af129SMark Brown 	switch (level) {
6755a3af129SMark Brown 	case SND_SOC_BIAS_ON:
6765a3af129SMark Brown 	case SND_SOC_BIAS_PREPARE:
6775a3af129SMark Brown 		break;
6785a3af129SMark Brown 
6795a3af129SMark Brown 	case SND_SOC_BIAS_STANDBY:
6805a3af129SMark Brown 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
6815a3af129SMark Brown 					 PCM512x_RQST, 0);
6825a3af129SMark Brown 		if (ret != 0) {
6835bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to remove standby: %d\n",
6845a3af129SMark Brown 				ret);
6855a3af129SMark Brown 			return ret;
6865a3af129SMark Brown 		}
6875a3af129SMark Brown 		break;
6885a3af129SMark Brown 
6895a3af129SMark Brown 	case SND_SOC_BIAS_OFF:
6905a3af129SMark Brown 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
6915a3af129SMark Brown 					 PCM512x_RQST, PCM512x_RQST);
6925a3af129SMark Brown 		if (ret != 0) {
6935bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to request standby: %d\n",
6945a3af129SMark Brown 				ret);
6955a3af129SMark Brown 			return ret;
6965a3af129SMark Brown 		}
6975a3af129SMark Brown 		break;
6985a3af129SMark Brown 	}
6995a3af129SMark Brown 
7005a3af129SMark Brown 	return 0;
7015a3af129SMark Brown }
7025a3af129SMark Brown 
pcm512x_find_sck(struct snd_soc_dai * dai,unsigned long bclk_rate)703f086ba9dSPeter Rosin static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
704f086ba9dSPeter Rosin 				      unsigned long bclk_rate)
705f086ba9dSPeter Rosin {
706f086ba9dSPeter Rosin 	struct device *dev = dai->dev;
7075bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
7085bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
709f086ba9dSPeter Rosin 	unsigned long sck_rate;
710f086ba9dSPeter Rosin 	int pow2;
711f086ba9dSPeter Rosin 
712f086ba9dSPeter Rosin 	/* 64 MHz <= pll_rate <= 100 MHz, VREF mode */
713f086ba9dSPeter Rosin 	/* 16 MHz <= sck_rate <=  25 MHz, VREF mode */
714f086ba9dSPeter Rosin 
715f086ba9dSPeter Rosin 	/* select sck_rate as a multiple of bclk_rate but still with
716f086ba9dSPeter Rosin 	 * as many factors of 2 as possible, as that makes it easier
717f086ba9dSPeter Rosin 	 * to find a fast DAC rate
718f086ba9dSPeter Rosin 	 */
719f29933c9SPeter Rosin 	pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
720f086ba9dSPeter Rosin 	for (; pow2; pow2 >>= 1) {
721f29933c9SPeter Rosin 		sck_rate = rounddown(pcm512x_pll_max(pcm512x),
722f29933c9SPeter Rosin 				     bclk_rate * pow2);
723f086ba9dSPeter Rosin 		if (sck_rate >= 16000000)
724f086ba9dSPeter Rosin 			break;
725f086ba9dSPeter Rosin 	}
726f086ba9dSPeter Rosin 	if (!pow2) {
727f086ba9dSPeter Rosin 		dev_err(dev, "Impossible to generate a suitable SCK\n");
728f086ba9dSPeter Rosin 		return 0;
729f086ba9dSPeter Rosin 	}
730f086ba9dSPeter Rosin 
731f086ba9dSPeter Rosin 	dev_dbg(dev, "sck_rate %lu\n", sck_rate);
732f086ba9dSPeter Rosin 	return sck_rate;
733f086ba9dSPeter Rosin }
734f086ba9dSPeter Rosin 
735f086ba9dSPeter Rosin /* pll_rate = pllin_rate * R * J.D / P
736f086ba9dSPeter Rosin  * 1 <= R <= 16
737f086ba9dSPeter Rosin  * 1 <= J <= 63
738f086ba9dSPeter Rosin  * 0 <= D <= 9999
739f086ba9dSPeter Rosin  * 1 <= P <= 15
740f086ba9dSPeter Rosin  * 64 MHz <= pll_rate <= 100 MHz
741f086ba9dSPeter Rosin  * if D == 0
742f086ba9dSPeter Rosin  *     1 MHz <= pllin_rate / P <= 20 MHz
743f086ba9dSPeter Rosin  * else if D > 0
744f086ba9dSPeter Rosin  *     6.667 MHz <= pllin_rate / P <= 20 MHz
745f086ba9dSPeter Rosin  *     4 <= J <= 11
746f086ba9dSPeter Rosin  *     R = 1
747f086ba9dSPeter Rosin  */
pcm512x_find_pll_coeff(struct snd_soc_dai * dai,unsigned long pllin_rate,unsigned long pll_rate)748f086ba9dSPeter Rosin static int pcm512x_find_pll_coeff(struct snd_soc_dai *dai,
749f086ba9dSPeter Rosin 				  unsigned long pllin_rate,
750f086ba9dSPeter Rosin 				  unsigned long pll_rate)
751f086ba9dSPeter Rosin {
752f086ba9dSPeter Rosin 	struct device *dev = dai->dev;
7535bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
7545bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
755f086ba9dSPeter Rosin 	unsigned long common;
756f086ba9dSPeter Rosin 	int R, J, D, P;
757f086ba9dSPeter Rosin 	unsigned long K; /* 10000 * J.D */
758f086ba9dSPeter Rosin 	unsigned long num;
759f086ba9dSPeter Rosin 	unsigned long den;
760f086ba9dSPeter Rosin 
761f086ba9dSPeter Rosin 	common = gcd(pll_rate, pllin_rate);
762f086ba9dSPeter Rosin 	dev_dbg(dev, "pll %lu pllin %lu common %lu\n",
763f086ba9dSPeter Rosin 		pll_rate, pllin_rate, common);
764f086ba9dSPeter Rosin 	num = pll_rate / common;
765f086ba9dSPeter Rosin 	den = pllin_rate / common;
766f086ba9dSPeter Rosin 
767f086ba9dSPeter Rosin 	/* pllin_rate / P (or here, den) cannot be greater than 20 MHz */
768f086ba9dSPeter Rosin 	if (pllin_rate / den > 20000000 && num < 8) {
769f073faa7SHoward Mitchell 		num *= DIV_ROUND_UP(pllin_rate / den, 20000000);
770f073faa7SHoward Mitchell 		den *= DIV_ROUND_UP(pllin_rate / den, 20000000);
771f086ba9dSPeter Rosin 	}
772f086ba9dSPeter Rosin 	dev_dbg(dev, "num / den = %lu / %lu\n", num, den);
773f086ba9dSPeter Rosin 
774f086ba9dSPeter Rosin 	P = den;
775f086ba9dSPeter Rosin 	if (den <= 15 && num <= 16 * 63
776f086ba9dSPeter Rosin 	    && 1000000 <= pllin_rate / P && pllin_rate / P <= 20000000) {
777f086ba9dSPeter Rosin 		/* Try the case with D = 0 */
778f086ba9dSPeter Rosin 		D = 0;
779f086ba9dSPeter Rosin 		/* factor 'num' into J and R, such that R <= 16 and J <= 63 */
780f086ba9dSPeter Rosin 		for (R = 16; R; R--) {
781f086ba9dSPeter Rosin 			if (num % R)
782f086ba9dSPeter Rosin 				continue;
783f086ba9dSPeter Rosin 			J = num / R;
784f086ba9dSPeter Rosin 			if (J == 0 || J > 63)
785f086ba9dSPeter Rosin 				continue;
786f086ba9dSPeter Rosin 
787f086ba9dSPeter Rosin 			dev_dbg(dev, "R * J / P = %d * %d / %d\n", R, J, P);
788f086ba9dSPeter Rosin 			pcm512x->real_pll = pll_rate;
789f086ba9dSPeter Rosin 			goto done;
790f086ba9dSPeter Rosin 		}
791f086ba9dSPeter Rosin 		/* no luck */
792f086ba9dSPeter Rosin 	}
793f086ba9dSPeter Rosin 
794f086ba9dSPeter Rosin 	R = 1;
795f086ba9dSPeter Rosin 
796f086ba9dSPeter Rosin 	if (num > 0xffffffffUL / 10000)
797f086ba9dSPeter Rosin 		goto fallback;
798f086ba9dSPeter Rosin 
799f086ba9dSPeter Rosin 	/* Try to find an exact pll_rate using the D > 0 case */
800f086ba9dSPeter Rosin 	common = gcd(10000 * num, den);
801f086ba9dSPeter Rosin 	num = 10000 * num / common;
802f086ba9dSPeter Rosin 	den /= common;
803f086ba9dSPeter Rosin 	dev_dbg(dev, "num %lu den %lu common %lu\n", num, den, common);
804f086ba9dSPeter Rosin 
805f086ba9dSPeter Rosin 	for (P = den; P <= 15; P++) {
806f086ba9dSPeter Rosin 		if (pllin_rate / P < 6667000 || 200000000 < pllin_rate / P)
807f086ba9dSPeter Rosin 			continue;
808f086ba9dSPeter Rosin 		if (num * P % den)
809f086ba9dSPeter Rosin 			continue;
810f086ba9dSPeter Rosin 		K = num * P / den;
811f086ba9dSPeter Rosin 		/* J == 12 is ok if D == 0 */
812f086ba9dSPeter Rosin 		if (K < 40000 || K > 120000)
813f086ba9dSPeter Rosin 			continue;
814f086ba9dSPeter Rosin 
815f086ba9dSPeter Rosin 		J = K / 10000;
816f086ba9dSPeter Rosin 		D = K % 10000;
817f086ba9dSPeter Rosin 		dev_dbg(dev, "J.D / P = %d.%04d / %d\n", J, D, P);
818f086ba9dSPeter Rosin 		pcm512x->real_pll = pll_rate;
819f086ba9dSPeter Rosin 		goto done;
820f086ba9dSPeter Rosin 	}
821f086ba9dSPeter Rosin 
822f086ba9dSPeter Rosin 	/* Fall back to an approximate pll_rate */
823f086ba9dSPeter Rosin 
824f086ba9dSPeter Rosin fallback:
825f086ba9dSPeter Rosin 	/* find smallest possible P */
826f086ba9dSPeter Rosin 	P = DIV_ROUND_UP(pllin_rate, 20000000);
827f086ba9dSPeter Rosin 	if (!P)
828f086ba9dSPeter Rosin 		P = 1;
829f086ba9dSPeter Rosin 	else if (P > 15) {
830f086ba9dSPeter Rosin 		dev_err(dev, "Need a slower clock as pll-input\n");
831f086ba9dSPeter Rosin 		return -EINVAL;
832f086ba9dSPeter Rosin 	}
833f086ba9dSPeter Rosin 	if (pllin_rate / P < 6667000) {
834f086ba9dSPeter Rosin 		dev_err(dev, "Need a faster clock as pll-input\n");
835f086ba9dSPeter Rosin 		return -EINVAL;
836f086ba9dSPeter Rosin 	}
837f086ba9dSPeter Rosin 	K = DIV_ROUND_CLOSEST_ULL(10000ULL * pll_rate * P, pllin_rate);
838f086ba9dSPeter Rosin 	if (K < 40000)
839f086ba9dSPeter Rosin 		K = 40000;
840f086ba9dSPeter Rosin 	/* J == 12 is ok if D == 0 */
841f086ba9dSPeter Rosin 	if (K > 120000)
842f086ba9dSPeter Rosin 		K = 120000;
843f086ba9dSPeter Rosin 	J = K / 10000;
844f086ba9dSPeter Rosin 	D = K % 10000;
845f086ba9dSPeter Rosin 	dev_dbg(dev, "J.D / P ~ %d.%04d / %d\n", J, D, P);
846f086ba9dSPeter Rosin 	pcm512x->real_pll = DIV_ROUND_DOWN_ULL((u64)K * pllin_rate, 10000 * P);
847f086ba9dSPeter Rosin 
848f086ba9dSPeter Rosin done:
849f086ba9dSPeter Rosin 	pcm512x->pll_r = R;
850f086ba9dSPeter Rosin 	pcm512x->pll_j = J;
851f086ba9dSPeter Rosin 	pcm512x->pll_d = D;
852f086ba9dSPeter Rosin 	pcm512x->pll_p = P;
853f086ba9dSPeter Rosin 	return 0;
854f086ba9dSPeter Rosin }
855f086ba9dSPeter Rosin 
pcm512x_pllin_dac_rate(struct snd_soc_dai * dai,unsigned long osr_rate,unsigned long pllin_rate)8567c4e1119SPeter Rosin static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
8577c4e1119SPeter Rosin 					    unsigned long osr_rate,
8587c4e1119SPeter Rosin 					    unsigned long pllin_rate)
8597c4e1119SPeter Rosin {
8605bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
8615bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
8627c4e1119SPeter Rosin 	unsigned long dac_rate;
8637c4e1119SPeter Rosin 
8647c4e1119SPeter Rosin 	if (!pcm512x->pll_out)
8657c4e1119SPeter Rosin 		return 0; /* no PLL to bypass, force SCK as DAC input */
8667c4e1119SPeter Rosin 
8677c4e1119SPeter Rosin 	if (pllin_rate % osr_rate)
8687c4e1119SPeter Rosin 		return 0; /* futile, quit early */
8697c4e1119SPeter Rosin 
8707c4e1119SPeter Rosin 	/* run DAC no faster than 6144000 Hz */
871f29933c9SPeter Rosin 	for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
8727c4e1119SPeter Rosin 	     dac_rate;
8737c4e1119SPeter Rosin 	     dac_rate -= osr_rate) {
8747c4e1119SPeter Rosin 
8757c4e1119SPeter Rosin 		if (pllin_rate / dac_rate > 128)
8767c4e1119SPeter Rosin 			return 0; /* DAC divider would be too big */
8777c4e1119SPeter Rosin 
8787c4e1119SPeter Rosin 		if (!(pllin_rate % dac_rate))
8797c4e1119SPeter Rosin 			return dac_rate;
8807c4e1119SPeter Rosin 
8817c4e1119SPeter Rosin 		dac_rate -= osr_rate;
8827c4e1119SPeter Rosin 	}
8837c4e1119SPeter Rosin 
8847c4e1119SPeter Rosin 	return 0;
8857c4e1119SPeter Rosin }
8867c4e1119SPeter Rosin 
pcm512x_set_dividers(struct snd_soc_dai * dai,struct snd_pcm_hw_params * params)88781249307SPeter Rosin static int pcm512x_set_dividers(struct snd_soc_dai *dai,
88881249307SPeter Rosin 				struct snd_pcm_hw_params *params)
88981249307SPeter Rosin {
89081249307SPeter Rosin 	struct device *dev = dai->dev;
8915bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
8925bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
893f086ba9dSPeter Rosin 	unsigned long pllin_rate = 0;
894f086ba9dSPeter Rosin 	unsigned long pll_rate;
89581249307SPeter Rosin 	unsigned long sck_rate;
89681249307SPeter Rosin 	unsigned long mck_rate;
89781249307SPeter Rosin 	unsigned long bclk_rate;
89881249307SPeter Rosin 	unsigned long sample_rate;
89981249307SPeter Rosin 	unsigned long osr_rate;
9007c4e1119SPeter Rosin 	unsigned long dacsrc_rate;
90181249307SPeter Rosin 	int bclk_div;
90281249307SPeter Rosin 	int lrclk_div;
90381249307SPeter Rosin 	int dsp_div;
90481249307SPeter Rosin 	int dac_div;
90581249307SPeter Rosin 	unsigned long dac_rate;
90681249307SPeter Rosin 	int ncp_div;
90781249307SPeter Rosin 	int osr_div;
90881249307SPeter Rosin 	int ret;
90981249307SPeter Rosin 	int idac;
91081249307SPeter Rosin 	int fssp;
9117c4e1119SPeter Rosin 	int gpio;
91281249307SPeter Rosin 
913ccc8d6c7SDimitris Papavasiliou 	if (pcm512x->bclk_ratio > 0) {
914ccc8d6c7SDimitris Papavasiliou 		lrclk_div = pcm512x->bclk_ratio;
915ccc8d6c7SDimitris Papavasiliou 	} else {
91681249307SPeter Rosin 		lrclk_div = snd_soc_params_to_frame_size(params);
917ccc8d6c7SDimitris Papavasiliou 
91881249307SPeter Rosin 		if (lrclk_div == 0) {
91981249307SPeter Rosin 			dev_err(dev, "No LRCLK?\n");
92081249307SPeter Rosin 			return -EINVAL;
92181249307SPeter Rosin 		}
922ccc8d6c7SDimitris Papavasiliou 	}
92381249307SPeter Rosin 
924f086ba9dSPeter Rosin 	if (!pcm512x->pll_out) {
92581249307SPeter Rosin 		sck_rate = clk_get_rate(pcm512x->sclk);
92651b033c2SDimitris Papavasiliou 		bclk_rate = params_rate(params) * lrclk_div;
92751b033c2SDimitris Papavasiliou 		bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
92881249307SPeter Rosin 
92981249307SPeter Rosin 		mck_rate = sck_rate;
930f086ba9dSPeter Rosin 	} else {
931f086ba9dSPeter Rosin 		ret = snd_soc_params_to_bclk(params);
932f086ba9dSPeter Rosin 		if (ret < 0) {
933f086ba9dSPeter Rosin 			dev_err(dev, "Failed to find suitable BCLK: %d\n", ret);
934f086ba9dSPeter Rosin 			return ret;
935f086ba9dSPeter Rosin 		}
936f086ba9dSPeter Rosin 		if (ret == 0) {
937f086ba9dSPeter Rosin 			dev_err(dev, "No BCLK?\n");
938f086ba9dSPeter Rosin 			return -EINVAL;
939f086ba9dSPeter Rosin 		}
940f086ba9dSPeter Rosin 		bclk_rate = ret;
941f086ba9dSPeter Rosin 
942f086ba9dSPeter Rosin 		pllin_rate = clk_get_rate(pcm512x->sclk);
943f086ba9dSPeter Rosin 
944f086ba9dSPeter Rosin 		sck_rate = pcm512x_find_sck(dai, bclk_rate);
945f086ba9dSPeter Rosin 		if (!sck_rate)
946f086ba9dSPeter Rosin 			return -EINVAL;
947f086ba9dSPeter Rosin 		pll_rate = 4 * sck_rate;
948f086ba9dSPeter Rosin 
949f086ba9dSPeter Rosin 		ret = pcm512x_find_pll_coeff(dai, pllin_rate, pll_rate);
950f086ba9dSPeter Rosin 		if (ret != 0)
951f086ba9dSPeter Rosin 			return ret;
952f086ba9dSPeter Rosin 
953f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap,
954f086ba9dSPeter Rosin 				   PCM512x_PLL_COEFF_0, pcm512x->pll_p - 1);
955f086ba9dSPeter Rosin 		if (ret != 0) {
956f086ba9dSPeter Rosin 			dev_err(dev, "Failed to write PLL P: %d\n", ret);
957f086ba9dSPeter Rosin 			return ret;
958f086ba9dSPeter Rosin 		}
959f086ba9dSPeter Rosin 
960f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap,
961f086ba9dSPeter Rosin 				   PCM512x_PLL_COEFF_1, pcm512x->pll_j);
962f086ba9dSPeter Rosin 		if (ret != 0) {
963f086ba9dSPeter Rosin 			dev_err(dev, "Failed to write PLL J: %d\n", ret);
964f086ba9dSPeter Rosin 			return ret;
965f086ba9dSPeter Rosin 		}
966f086ba9dSPeter Rosin 
967f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap,
968f086ba9dSPeter Rosin 				   PCM512x_PLL_COEFF_2, pcm512x->pll_d >> 8);
969f086ba9dSPeter Rosin 		if (ret != 0) {
970f086ba9dSPeter Rosin 			dev_err(dev, "Failed to write PLL D msb: %d\n", ret);
971f086ba9dSPeter Rosin 			return ret;
972f086ba9dSPeter Rosin 		}
973f086ba9dSPeter Rosin 
974f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap,
975f086ba9dSPeter Rosin 				   PCM512x_PLL_COEFF_3, pcm512x->pll_d & 0xff);
976f086ba9dSPeter Rosin 		if (ret != 0) {
977f086ba9dSPeter Rosin 			dev_err(dev, "Failed to write PLL D lsb: %d\n", ret);
978f086ba9dSPeter Rosin 			return ret;
979f086ba9dSPeter Rosin 		}
980f086ba9dSPeter Rosin 
981f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap,
982f086ba9dSPeter Rosin 				   PCM512x_PLL_COEFF_4, pcm512x->pll_r - 1);
983f086ba9dSPeter Rosin 		if (ret != 0) {
984f086ba9dSPeter Rosin 			dev_err(dev, "Failed to write PLL R: %d\n", ret);
985f086ba9dSPeter Rosin 			return ret;
986f086ba9dSPeter Rosin 		}
987f086ba9dSPeter Rosin 
988f086ba9dSPeter Rosin 		mck_rate = pcm512x->real_pll;
989f086ba9dSPeter Rosin 
990f086ba9dSPeter Rosin 		bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
991f086ba9dSPeter Rosin 	}
99281249307SPeter Rosin 
99381249307SPeter Rosin 	if (bclk_div > 128) {
99481249307SPeter Rosin 		dev_err(dev, "Failed to find BCLK divider\n");
99581249307SPeter Rosin 		return -EINVAL;
99681249307SPeter Rosin 	}
99781249307SPeter Rosin 
99881249307SPeter Rosin 	/* the actual rate */
99981249307SPeter Rosin 	sample_rate = sck_rate / bclk_div / lrclk_div;
100081249307SPeter Rosin 	osr_rate = 16 * sample_rate;
100181249307SPeter Rosin 
100281249307SPeter Rosin 	/* run DSP no faster than 50 MHz */
1003f29933c9SPeter Rosin 	dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
100481249307SPeter Rosin 
10057c4e1119SPeter Rosin 	dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
10067c4e1119SPeter Rosin 	if (dac_rate) {
10077c4e1119SPeter Rosin 		/* the desired clock rate is "compatible" with the pll input
10087c4e1119SPeter Rosin 		 * clock, so use that clock as dac input instead of the pll
10097c4e1119SPeter Rosin 		 * output clock since the pll will introduce jitter and thus
10107c4e1119SPeter Rosin 		 * noise.
10117c4e1119SPeter Rosin 		 */
10127c4e1119SPeter Rosin 		dev_dbg(dev, "using pll input as dac input\n");
10137c4e1119SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
10147c4e1119SPeter Rosin 					 PCM512x_SDAC, PCM512x_SDAC_GPIO);
10157c4e1119SPeter Rosin 		if (ret != 0) {
10165bdef14aSKuninori Morimoto 			dev_err(component->dev,
10177c4e1119SPeter Rosin 				"Failed to set gpio as dacref: %d\n", ret);
10187c4e1119SPeter Rosin 			return ret;
10197c4e1119SPeter Rosin 		}
10207c4e1119SPeter Rosin 
10217c4e1119SPeter Rosin 		gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
10227c4e1119SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN,
10237c4e1119SPeter Rosin 					 PCM512x_GREF, gpio);
10247c4e1119SPeter Rosin 		if (ret != 0) {
10255bdef14aSKuninori Morimoto 			dev_err(component->dev,
10267c4e1119SPeter Rosin 				"Failed to set gpio %d as dacin: %d\n",
10277c4e1119SPeter Rosin 				pcm512x->pll_in, ret);
10287c4e1119SPeter Rosin 			return ret;
10297c4e1119SPeter Rosin 		}
10307c4e1119SPeter Rosin 
10317c4e1119SPeter Rosin 		dacsrc_rate = pllin_rate;
10327c4e1119SPeter Rosin 	} else {
103381249307SPeter Rosin 		/* run DAC no faster than 6144000 Hz */
1034f29933c9SPeter Rosin 		unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
1035f29933c9SPeter Rosin 			/ osr_rate;
10367c4e1119SPeter Rosin 		unsigned long sck_mul = sck_rate / osr_rate;
10377c4e1119SPeter Rosin 
103881249307SPeter Rosin 		for (; dac_mul; dac_mul--) {
103981249307SPeter Rosin 			if (!(sck_mul % dac_mul))
104081249307SPeter Rosin 				break;
104181249307SPeter Rosin 		}
104281249307SPeter Rosin 		if (!dac_mul) {
104381249307SPeter Rosin 			dev_err(dev, "Failed to find DAC rate\n");
104481249307SPeter Rosin 			return -EINVAL;
104581249307SPeter Rosin 		}
104681249307SPeter Rosin 
104781249307SPeter Rosin 		dac_rate = dac_mul * osr_rate;
10487c4e1119SPeter Rosin 		dev_dbg(dev, "dac_rate %lu sample_rate %lu\n",
10497c4e1119SPeter Rosin 			dac_rate, sample_rate);
105081249307SPeter Rosin 
10517c4e1119SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
10527c4e1119SPeter Rosin 					 PCM512x_SDAC, PCM512x_SDAC_SCK);
10537c4e1119SPeter Rosin 		if (ret != 0) {
10545bdef14aSKuninori Morimoto 			dev_err(component->dev,
10557c4e1119SPeter Rosin 				"Failed to set sck as dacref: %d\n", ret);
10567c4e1119SPeter Rosin 			return ret;
10577c4e1119SPeter Rosin 		}
10587c4e1119SPeter Rosin 
10597c4e1119SPeter Rosin 		dacsrc_rate = sck_rate;
10607c4e1119SPeter Rosin 	}
10617c4e1119SPeter Rosin 
10625890bd52SPeter Rosin 	osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
10635890bd52SPeter Rosin 	if (osr_div > 128) {
10645890bd52SPeter Rosin 		dev_err(dev, "Failed to find OSR divider\n");
10655890bd52SPeter Rosin 		return -EINVAL;
10665890bd52SPeter Rosin 	}
10675890bd52SPeter Rosin 
10687c4e1119SPeter Rosin 	dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
106981249307SPeter Rosin 	if (dac_div > 128) {
107081249307SPeter Rosin 		dev_err(dev, "Failed to find DAC divider\n");
107181249307SPeter Rosin 		return -EINVAL;
107281249307SPeter Rosin 	}
10735890bd52SPeter Rosin 	dac_rate = dacsrc_rate / dac_div;
107481249307SPeter Rosin 
1075f29933c9SPeter Rosin 	ncp_div = DIV_ROUND_CLOSEST(dac_rate,
1076f29933c9SPeter Rosin 				    pcm512x_ncp_target(pcm512x, dac_rate));
10775890bd52SPeter Rosin 	if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
107881249307SPeter Rosin 		/* run NCP no faster than 2048000 Hz, but why? */
10795890bd52SPeter Rosin 		ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
108081249307SPeter Rosin 		if (ncp_div > 128) {
108181249307SPeter Rosin 			dev_err(dev, "Failed to find NCP divider\n");
108281249307SPeter Rosin 			return -EINVAL;
108381249307SPeter Rosin 		}
108481249307SPeter Rosin 	}
108581249307SPeter Rosin 
108681249307SPeter Rosin 	idac = mck_rate / (dsp_div * sample_rate);
108781249307SPeter Rosin 
108881249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1);
108981249307SPeter Rosin 	if (ret != 0) {
109081249307SPeter Rosin 		dev_err(dev, "Failed to write DSP divider: %d\n", ret);
109181249307SPeter Rosin 		return ret;
109281249307SPeter Rosin 	}
109381249307SPeter Rosin 
109481249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1);
109581249307SPeter Rosin 	if (ret != 0) {
109681249307SPeter Rosin 		dev_err(dev, "Failed to write DAC divider: %d\n", ret);
109781249307SPeter Rosin 		return ret;
109881249307SPeter Rosin 	}
109981249307SPeter Rosin 
110081249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1);
110181249307SPeter Rosin 	if (ret != 0) {
110281249307SPeter Rosin 		dev_err(dev, "Failed to write NCP divider: %d\n", ret);
110381249307SPeter Rosin 		return ret;
110481249307SPeter Rosin 	}
110581249307SPeter Rosin 
110681249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1);
110781249307SPeter Rosin 	if (ret != 0) {
110881249307SPeter Rosin 		dev_err(dev, "Failed to write OSR divider: %d\n", ret);
110981249307SPeter Rosin 		return ret;
111081249307SPeter Rosin 	}
111181249307SPeter Rosin 
111281249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap,
111381249307SPeter Rosin 			   PCM512x_MASTER_CLKDIV_1, bclk_div - 1);
111481249307SPeter Rosin 	if (ret != 0) {
111581249307SPeter Rosin 		dev_err(dev, "Failed to write BCLK divider: %d\n", ret);
111681249307SPeter Rosin 		return ret;
111781249307SPeter Rosin 	}
111881249307SPeter Rosin 
111981249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap,
112081249307SPeter Rosin 			   PCM512x_MASTER_CLKDIV_2, lrclk_div - 1);
112181249307SPeter Rosin 	if (ret != 0) {
112281249307SPeter Rosin 		dev_err(dev, "Failed to write LRCLK divider: %d\n", ret);
112381249307SPeter Rosin 		return ret;
112481249307SPeter Rosin 	}
112581249307SPeter Rosin 
112681249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8);
112781249307SPeter Rosin 	if (ret != 0) {
112881249307SPeter Rosin 		dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret);
112981249307SPeter Rosin 		return ret;
113081249307SPeter Rosin 	}
113181249307SPeter Rosin 
113281249307SPeter Rosin 	ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff);
113381249307SPeter Rosin 	if (ret != 0) {
113481249307SPeter Rosin 		dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret);
113581249307SPeter Rosin 		return ret;
113681249307SPeter Rosin 	}
113781249307SPeter Rosin 
1138f29933c9SPeter Rosin 	if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
113981249307SPeter Rosin 		fssp = PCM512x_FSSP_48KHZ;
1140f29933c9SPeter Rosin 	else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
114181249307SPeter Rosin 		fssp = PCM512x_FSSP_96KHZ;
1142f29933c9SPeter Rosin 	else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
114381249307SPeter Rosin 		fssp = PCM512x_FSSP_192KHZ;
114481249307SPeter Rosin 	else
114581249307SPeter Rosin 		fssp = PCM512x_FSSP_384KHZ;
114681249307SPeter Rosin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE,
114781249307SPeter Rosin 				 PCM512x_FSSP, fssp);
114881249307SPeter Rosin 	if (ret != 0) {
11495bdef14aSKuninori Morimoto 		dev_err(component->dev, "Failed to set fs speed: %d\n", ret);
115081249307SPeter Rosin 		return ret;
115181249307SPeter Rosin 	}
115281249307SPeter Rosin 
11535bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "DSP divider %d\n", dsp_div);
11545bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "DAC divider %d\n", dac_div);
11555bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "NCP divider %d\n", ncp_div);
11565bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "OSR divider %d\n", osr_div);
11575bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "BCK divider %d\n", bclk_div);
11585bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "LRCK divider %d\n", lrclk_div);
11595bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "IDAC %d\n", idac);
11605bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "1<<FSSP %d\n", 1 << fssp);
116181249307SPeter Rosin 
116281249307SPeter Rosin 	return 0;
116381249307SPeter Rosin }
116481249307SPeter Rosin 
pcm512x_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)116581249307SPeter Rosin static int pcm512x_hw_params(struct snd_pcm_substream *substream,
116681249307SPeter Rosin 			     struct snd_pcm_hw_params *params,
116781249307SPeter Rosin 			     struct snd_soc_dai *dai)
116881249307SPeter Rosin {
11695bdef14aSKuninori Morimoto 	struct snd_soc_component *component = dai->component;
11705bdef14aSKuninori Morimoto 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
117181249307SPeter Rosin 	int alen;
1172f086ba9dSPeter Rosin 	int gpio;
117381249307SPeter Rosin 	int ret;
117481249307SPeter Rosin 
11755bdef14aSKuninori Morimoto 	dev_dbg(component->dev, "hw_params %u Hz, %u channels\n",
117681249307SPeter Rosin 		params_rate(params),
117781249307SPeter Rosin 		params_channels(params));
117881249307SPeter Rosin 
11790a3dcb50SAxel Lin 	switch (params_width(params)) {
118081249307SPeter Rosin 	case 16:
118181249307SPeter Rosin 		alen = PCM512x_ALEN_16;
118281249307SPeter Rosin 		break;
118381249307SPeter Rosin 	case 20:
118481249307SPeter Rosin 		alen = PCM512x_ALEN_20;
118581249307SPeter Rosin 		break;
118681249307SPeter Rosin 	case 24:
118781249307SPeter Rosin 		alen = PCM512x_ALEN_24;
118881249307SPeter Rosin 		break;
118981249307SPeter Rosin 	case 32:
119081249307SPeter Rosin 		alen = PCM512x_ALEN_32;
119181249307SPeter Rosin 		break;
119281249307SPeter Rosin 	default:
11935bdef14aSKuninori Morimoto 		dev_err(component->dev, "Bad frame size: %d\n",
11940a3dcb50SAxel Lin 			params_width(params));
119581249307SPeter Rosin 		return -EINVAL;
119681249307SPeter Rosin 	}
119781249307SPeter Rosin 
11986feaaa7cSKirill Marinushkin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
11996feaaa7cSKirill Marinushkin 				 PCM512x_ALEN, alen);
12006feaaa7cSKirill Marinushkin 	if (ret != 0) {
12016feaaa7cSKirill Marinushkin 		dev_err(component->dev, "Failed to set frame size: %d\n", ret);
12026feaaa7cSKirill Marinushkin 		return ret;
12036feaaa7cSKirill Marinushkin 	}
12046feaaa7cSKirill Marinushkin 
1205e0dab089SMark Brown 	if ((pcm512x->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) ==
1206e0dab089SMark Brown 	    SND_SOC_DAIFMT_CBC_CFC) {
120781249307SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
120881249307SPeter Rosin 					 PCM512x_DCAS, 0);
120981249307SPeter Rosin 		if (ret != 0) {
12105bdef14aSKuninori Morimoto 			dev_err(component->dev,
121181249307SPeter Rosin 				"Failed to enable clock divider autoset: %d\n",
121281249307SPeter Rosin 				ret);
121381249307SPeter Rosin 			return ret;
121481249307SPeter Rosin 		}
1215798714b6SKirill Marinushkin 		goto skip_pll;
121681249307SPeter Rosin 	}
121781249307SPeter Rosin 
1218f086ba9dSPeter Rosin 	if (pcm512x->pll_out) {
1219f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11);
1220f086ba9dSPeter Rosin 		if (ret != 0) {
12215bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to set FLEX_A: %d\n", ret);
1222f086ba9dSPeter Rosin 			return ret;
1223f086ba9dSPeter Rosin 		}
1224f086ba9dSPeter Rosin 
1225f086ba9dSPeter Rosin 		ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff);
1226f086ba9dSPeter Rosin 		if (ret != 0) {
12275bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to set FLEX_B: %d\n", ret);
1228f086ba9dSPeter Rosin 			return ret;
1229f086ba9dSPeter Rosin 		}
1230f086ba9dSPeter Rosin 
1231f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
1232f086ba9dSPeter Rosin 					 PCM512x_IDFS | PCM512x_IDBK
1233f086ba9dSPeter Rosin 					 | PCM512x_IDSK | PCM512x_IDCH
1234f086ba9dSPeter Rosin 					 | PCM512x_IDCM | PCM512x_DCAS
1235f086ba9dSPeter Rosin 					 | PCM512x_IPLK,
1236f086ba9dSPeter Rosin 					 PCM512x_IDFS | PCM512x_IDBK
1237f086ba9dSPeter Rosin 					 | PCM512x_IDSK | PCM512x_IDCH
1238f086ba9dSPeter Rosin 					 | PCM512x_DCAS);
1239f086ba9dSPeter Rosin 		if (ret != 0) {
12405bdef14aSKuninori Morimoto 			dev_err(component->dev,
1241f086ba9dSPeter Rosin 				"Failed to ignore auto-clock failures: %d\n",
1242f086ba9dSPeter Rosin 				ret);
1243f086ba9dSPeter Rosin 			return ret;
1244f086ba9dSPeter Rosin 		}
1245f086ba9dSPeter Rosin 	} else {
124681249307SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
124781249307SPeter Rosin 					 PCM512x_IDFS | PCM512x_IDBK
124881249307SPeter Rosin 					 | PCM512x_IDSK | PCM512x_IDCH
124981249307SPeter Rosin 					 | PCM512x_IDCM | PCM512x_DCAS
125081249307SPeter Rosin 					 | PCM512x_IPLK,
125181249307SPeter Rosin 					 PCM512x_IDFS | PCM512x_IDBK
125281249307SPeter Rosin 					 | PCM512x_IDSK | PCM512x_IDCH
125381249307SPeter Rosin 					 | PCM512x_DCAS | PCM512x_IPLK);
125481249307SPeter Rosin 		if (ret != 0) {
12555bdef14aSKuninori Morimoto 			dev_err(component->dev,
125681249307SPeter Rosin 				"Failed to ignore auto-clock failures: %d\n",
125781249307SPeter Rosin 				ret);
125881249307SPeter Rosin 			return ret;
125981249307SPeter Rosin 		}
126081249307SPeter Rosin 
126181249307SPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
126281249307SPeter Rosin 					 PCM512x_PLLE, 0);
126381249307SPeter Rosin 		if (ret != 0) {
12645bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to disable pll: %d\n", ret);
126581249307SPeter Rosin 			return ret;
126681249307SPeter Rosin 		}
1267f086ba9dSPeter Rosin 	}
126881249307SPeter Rosin 
126981249307SPeter Rosin 	ret = pcm512x_set_dividers(dai, params);
127081249307SPeter Rosin 	if (ret != 0)
127181249307SPeter Rosin 		return ret;
127281249307SPeter Rosin 
1273f086ba9dSPeter Rosin 	if (pcm512x->pll_out) {
1274f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF,
1275f086ba9dSPeter Rosin 					 PCM512x_SREF, PCM512x_SREF_GPIO);
1276f086ba9dSPeter Rosin 		if (ret != 0) {
12775bdef14aSKuninori Morimoto 			dev_err(component->dev,
1278f086ba9dSPeter Rosin 				"Failed to set gpio as pllref: %d\n", ret);
1279f086ba9dSPeter Rosin 			return ret;
1280f086ba9dSPeter Rosin 		}
1281f086ba9dSPeter Rosin 
1282f086ba9dSPeter Rosin 		gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
1283f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN,
1284f086ba9dSPeter Rosin 					 PCM512x_GREF, gpio);
1285f086ba9dSPeter Rosin 		if (ret != 0) {
12865bdef14aSKuninori Morimoto 			dev_err(component->dev,
1287f086ba9dSPeter Rosin 				"Failed to set gpio %d as pllin: %d\n",
1288f086ba9dSPeter Rosin 				pcm512x->pll_in, ret);
1289f086ba9dSPeter Rosin 			return ret;
1290f086ba9dSPeter Rosin 		}
1291f086ba9dSPeter Rosin 
1292f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
1293f086ba9dSPeter Rosin 					 PCM512x_PLLE, PCM512x_PLLE);
1294f086ba9dSPeter Rosin 		if (ret != 0) {
12955bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to enable pll: %d\n", ret);
1296f086ba9dSPeter Rosin 			return ret;
1297f086ba9dSPeter Rosin 		}
1298f086ba9dSPeter Rosin 
1299f086ba9dSPeter Rosin 		gpio = PCM512x_G1OE << (pcm512x->pll_out - 1);
1300f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN,
1301f086ba9dSPeter Rosin 					 gpio, gpio);
1302f086ba9dSPeter Rosin 		if (ret != 0) {
13035bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to enable gpio %d: %d\n",
1304f086ba9dSPeter Rosin 				pcm512x->pll_out, ret);
1305f086ba9dSPeter Rosin 			return ret;
1306f086ba9dSPeter Rosin 		}
1307f086ba9dSPeter Rosin 
1308f086ba9dSPeter Rosin 		gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1;
1309f086ba9dSPeter Rosin 		ret = regmap_update_bits(pcm512x->regmap, gpio,
1310f086ba9dSPeter Rosin 					 PCM512x_GxSL, PCM512x_GxSL_PLLCK);
1311f086ba9dSPeter Rosin 		if (ret != 0) {
13125bdef14aSKuninori Morimoto 			dev_err(component->dev, "Failed to output pll on %d: %d\n",
1313f086ba9dSPeter Rosin 				ret, pcm512x->pll_out);
1314f086ba9dSPeter Rosin 			return ret;
1315f086ba9dSPeter Rosin 		}
1316f086ba9dSPeter Rosin 	}
1317f086ba9dSPeter Rosin 
131881249307SPeter Rosin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
131981249307SPeter Rosin 				 PCM512x_RQSY, PCM512x_RQSY_HALT);
132081249307SPeter Rosin 	if (ret != 0) {
13215bdef14aSKuninori Morimoto 		dev_err(component->dev, "Failed to halt clocks: %d\n", ret);
132281249307SPeter Rosin 		return ret;
132381249307SPeter Rosin 	}
132481249307SPeter Rosin 
132581249307SPeter Rosin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
132681249307SPeter Rosin 				 PCM512x_RQSY, PCM512x_RQSY_RESUME);
132781249307SPeter Rosin 	if (ret != 0) {
13285bdef14aSKuninori Morimoto 		dev_err(component->dev, "Failed to resume clocks: %d\n", ret);
132981249307SPeter Rosin 		return ret;
133081249307SPeter Rosin 	}
133181249307SPeter Rosin 
1332798714b6SKirill Marinushkin skip_pll:
133326b97d95SKirill Marinushkin 	return 0;
133426b97d95SKirill Marinushkin }
133526b97d95SKirill Marinushkin 
pcm512x_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)133626b97d95SKirill Marinushkin static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
133726b97d95SKirill Marinushkin {
133826b97d95SKirill Marinushkin 	struct snd_soc_component *component = dai->component;
133926b97d95SKirill Marinushkin 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
134025d27c4fSKirill Marinushkin 	int afmt;
134125d27c4fSKirill Marinushkin 	int offset = 0;
134226b97d95SKirill Marinushkin 	int clock_output;
1343e0dab089SMark Brown 	int provider_mode;
134426b97d95SKirill Marinushkin 	int ret;
134526b97d95SKirill Marinushkin 
1346e0dab089SMark Brown 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
1347e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBC_CFC:
134826b97d95SKirill Marinushkin 		clock_output = 0;
1349e0dab089SMark Brown 		provider_mode = 0;
135026b97d95SKirill Marinushkin 		break;
1351e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBP_CFP:
135226b97d95SKirill Marinushkin 		clock_output = PCM512x_BCKO | PCM512x_LRKO;
1353e0dab089SMark Brown 		provider_mode = PCM512x_RLRK | PCM512x_RBCK;
135426b97d95SKirill Marinushkin 		break;
1355e0dab089SMark Brown 	case SND_SOC_DAIFMT_CBP_CFC:
135626b97d95SKirill Marinushkin 		clock_output = PCM512x_BCKO;
1357e0dab089SMark Brown 		provider_mode = PCM512x_RBCK;
135826b97d95SKirill Marinushkin 		break;
135926b97d95SKirill Marinushkin 	default:
136026b97d95SKirill Marinushkin 		return -EINVAL;
136126b97d95SKirill Marinushkin 	}
136226b97d95SKirill Marinushkin 
1363798714b6SKirill Marinushkin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG,
1364798714b6SKirill Marinushkin 				 PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO,
1365798714b6SKirill Marinushkin 				 clock_output);
1366798714b6SKirill Marinushkin 	if (ret != 0) {
1367798714b6SKirill Marinushkin 		dev_err(component->dev, "Failed to enable clock output: %d\n", ret);
1368798714b6SKirill Marinushkin 		return ret;
1369798714b6SKirill Marinushkin 	}
1370798714b6SKirill Marinushkin 
1371798714b6SKirill Marinushkin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE,
1372798714b6SKirill Marinushkin 				 PCM512x_RLRK | PCM512x_RBCK,
1373e0dab089SMark Brown 				 provider_mode);
1374798714b6SKirill Marinushkin 	if (ret != 0) {
1375e0dab089SMark Brown 		dev_err(component->dev, "Failed to enable provider mode: %d\n", ret);
1376798714b6SKirill Marinushkin 		return ret;
1377798714b6SKirill Marinushkin 	}
1378798714b6SKirill Marinushkin 
137925d27c4fSKirill Marinushkin 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
138025d27c4fSKirill Marinushkin 	case SND_SOC_DAIFMT_I2S:
138125d27c4fSKirill Marinushkin 		afmt = PCM512x_AFMT_I2S;
138225d27c4fSKirill Marinushkin 		break;
138325d27c4fSKirill Marinushkin 	case SND_SOC_DAIFMT_RIGHT_J:
138425d27c4fSKirill Marinushkin 		afmt = PCM512x_AFMT_RTJ;
138525d27c4fSKirill Marinushkin 		break;
138625d27c4fSKirill Marinushkin 	case SND_SOC_DAIFMT_LEFT_J:
138725d27c4fSKirill Marinushkin 		afmt = PCM512x_AFMT_LTJ;
138825d27c4fSKirill Marinushkin 		break;
138925d27c4fSKirill Marinushkin 	case SND_SOC_DAIFMT_DSP_A:
139025d27c4fSKirill Marinushkin 		offset = 1;
139125d27c4fSKirill Marinushkin 		fallthrough;
139225d27c4fSKirill Marinushkin 	case SND_SOC_DAIFMT_DSP_B:
139325d27c4fSKirill Marinushkin 		afmt = PCM512x_AFMT_DSP;
139425d27c4fSKirill Marinushkin 		break;
139525d27c4fSKirill Marinushkin 	default:
139625d27c4fSKirill Marinushkin 		dev_err(component->dev, "unsupported DAI format: 0x%x\n",
139725d27c4fSKirill Marinushkin 			pcm512x->fmt);
139825d27c4fSKirill Marinushkin 		return -EINVAL;
139925d27c4fSKirill Marinushkin 	}
140025d27c4fSKirill Marinushkin 
140125d27c4fSKirill Marinushkin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
140225d27c4fSKirill Marinushkin 				 PCM512x_AFMT, afmt);
140325d27c4fSKirill Marinushkin 	if (ret != 0) {
140425d27c4fSKirill Marinushkin 		dev_err(component->dev, "Failed to set data format: %d\n", ret);
140525d27c4fSKirill Marinushkin 		return ret;
140625d27c4fSKirill Marinushkin 	}
140725d27c4fSKirill Marinushkin 
140825d27c4fSKirill Marinushkin 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_2,
140925d27c4fSKirill Marinushkin 				 0xFF, offset);
141025d27c4fSKirill Marinushkin 	if (ret != 0) {
141125d27c4fSKirill Marinushkin 		dev_err(component->dev, "Failed to set data offset: %d\n", ret);
141225d27c4fSKirill Marinushkin 		return ret;
141325d27c4fSKirill Marinushkin 	}
141425d27c4fSKirill Marinushkin 
141581249307SPeter Rosin 	pcm512x->fmt = fmt;
141681249307SPeter Rosin 
141781249307SPeter Rosin 	return 0;
141881249307SPeter Rosin }
141981249307SPeter Rosin 
pcm512x_set_bclk_ratio(struct snd_soc_dai * dai,unsigned int ratio)1420ccc8d6c7SDimitris Papavasiliou static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
1421ccc8d6c7SDimitris Papavasiliou {
1422ccc8d6c7SDimitris Papavasiliou 	struct snd_soc_component *component = dai->component;
1423ccc8d6c7SDimitris Papavasiliou 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
1424ccc8d6c7SDimitris Papavasiliou 
1425ccc8d6c7SDimitris Papavasiliou 	if (ratio > 256)
1426ccc8d6c7SDimitris Papavasiliou 		return -EINVAL;
1427ccc8d6c7SDimitris Papavasiliou 
1428ccc8d6c7SDimitris Papavasiliou 	pcm512x->bclk_ratio = ratio;
1429ccc8d6c7SDimitris Papavasiliou 
1430ccc8d6c7SDimitris Papavasiliou 	return 0;
1431ccc8d6c7SDimitris Papavasiliou }
1432ccc8d6c7SDimitris Papavasiliou 
pcm512x_mute(struct snd_soc_dai * dai,int mute,int direction)14331eb2c43dSKuninori Morimoto static int pcm512x_mute(struct snd_soc_dai *dai, int mute, int direction)
14343500f1c5SDimitris Papavasiliou {
14353500f1c5SDimitris Papavasiliou 	struct snd_soc_component *component = dai->component;
14363500f1c5SDimitris Papavasiliou 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
14373500f1c5SDimitris Papavasiliou 	int ret;
14383500f1c5SDimitris Papavasiliou 	unsigned int mute_det;
14393500f1c5SDimitris Papavasiliou 
14403500f1c5SDimitris Papavasiliou 	mutex_lock(&pcm512x->mutex);
14413500f1c5SDimitris Papavasiliou 
14423500f1c5SDimitris Papavasiliou 	if (mute) {
14433500f1c5SDimitris Papavasiliou 		pcm512x->mute |= 0x1;
14443500f1c5SDimitris Papavasiliou 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
14453500f1c5SDimitris Papavasiliou 					 PCM512x_RQML | PCM512x_RQMR,
14463500f1c5SDimitris Papavasiliou 					 PCM512x_RQML | PCM512x_RQMR);
14473500f1c5SDimitris Papavasiliou 		if (ret != 0) {
14483500f1c5SDimitris Papavasiliou 			dev_err(component->dev,
14493500f1c5SDimitris Papavasiliou 				"Failed to set digital mute: %d\n", ret);
145028b698b7SDan Carpenter 			goto unlock;
14513500f1c5SDimitris Papavasiliou 		}
14523500f1c5SDimitris Papavasiliou 
14533500f1c5SDimitris Papavasiliou 		regmap_read_poll_timeout(pcm512x->regmap,
14543500f1c5SDimitris Papavasiliou 					 PCM512x_ANALOG_MUTE_DET,
14553500f1c5SDimitris Papavasiliou 					 mute_det, (mute_det & 0x3) == 0,
14563500f1c5SDimitris Papavasiliou 					 200, 10000);
14573500f1c5SDimitris Papavasiliou 	} else {
14583500f1c5SDimitris Papavasiliou 		pcm512x->mute &= ~0x1;
14593500f1c5SDimitris Papavasiliou 		ret = pcm512x_update_mute(pcm512x);
14603500f1c5SDimitris Papavasiliou 		if (ret != 0) {
14613500f1c5SDimitris Papavasiliou 			dev_err(component->dev,
14623500f1c5SDimitris Papavasiliou 				"Failed to update digital mute: %d\n", ret);
146328b698b7SDan Carpenter 			goto unlock;
14643500f1c5SDimitris Papavasiliou 		}
14653500f1c5SDimitris Papavasiliou 
14663500f1c5SDimitris Papavasiliou 		regmap_read_poll_timeout(pcm512x->regmap,
14673500f1c5SDimitris Papavasiliou 					 PCM512x_ANALOG_MUTE_DET,
14683500f1c5SDimitris Papavasiliou 					 mute_det,
14693500f1c5SDimitris Papavasiliou 					 (mute_det & 0x3)
14703500f1c5SDimitris Papavasiliou 					 == ((~pcm512x->mute >> 1) & 0x3),
14713500f1c5SDimitris Papavasiliou 					 200, 10000);
14723500f1c5SDimitris Papavasiliou 	}
14733500f1c5SDimitris Papavasiliou 
147428b698b7SDan Carpenter unlock:
14753500f1c5SDimitris Papavasiliou 	mutex_unlock(&pcm512x->mutex);
14763500f1c5SDimitris Papavasiliou 
147728b698b7SDan Carpenter 	return ret;
14783500f1c5SDimitris Papavasiliou }
14793500f1c5SDimitris Papavasiliou 
148081249307SPeter Rosin static const struct snd_soc_dai_ops pcm512x_dai_ops = {
148181249307SPeter Rosin 	.startup = pcm512x_dai_startup,
148281249307SPeter Rosin 	.hw_params = pcm512x_hw_params,
148381249307SPeter Rosin 	.set_fmt = pcm512x_set_fmt,
14841eb2c43dSKuninori Morimoto 	.mute_stream = pcm512x_mute,
1485ccc8d6c7SDimitris Papavasiliou 	.set_bclk_ratio = pcm512x_set_bclk_ratio,
14861eb2c43dSKuninori Morimoto 	.no_capture_mute = 1,
148781249307SPeter Rosin };
148881249307SPeter Rosin 
14895a3af129SMark Brown static struct snd_soc_dai_driver pcm512x_dai = {
14905a3af129SMark Brown 	.name = "pcm512x-hifi",
14915a3af129SMark Brown 	.playback = {
14925a3af129SMark Brown 		.stream_name = "Playback",
14935a3af129SMark Brown 		.channels_min = 2,
14945a3af129SMark Brown 		.channels_max = 2,
149581249307SPeter Rosin 		.rates = SNDRV_PCM_RATE_CONTINUOUS,
149681249307SPeter Rosin 		.rate_min = 8000,
149781249307SPeter Rosin 		.rate_max = 384000,
14985a3af129SMark Brown 		.formats = SNDRV_PCM_FMTBIT_S16_LE |
14995a3af129SMark Brown 			   SNDRV_PCM_FMTBIT_S24_LE |
15005a3af129SMark Brown 			   SNDRV_PCM_FMTBIT_S32_LE
15015a3af129SMark Brown 	},
150281249307SPeter Rosin 	.ops = &pcm512x_dai_ops,
15035a3af129SMark Brown };
15045a3af129SMark Brown 
15055bdef14aSKuninori Morimoto static const struct snd_soc_component_driver pcm512x_component_driver = {
15065a3af129SMark Brown 	.set_bias_level		= pcm512x_set_bias_level,
15075a3af129SMark Brown 	.controls		= pcm512x_controls,
15085a3af129SMark Brown 	.num_controls		= ARRAY_SIZE(pcm512x_controls),
15095a3af129SMark Brown 	.dapm_widgets		= pcm512x_dapm_widgets,
15105a3af129SMark Brown 	.num_dapm_widgets	= ARRAY_SIZE(pcm512x_dapm_widgets),
15115a3af129SMark Brown 	.dapm_routes		= pcm512x_dapm_routes,
15125a3af129SMark Brown 	.num_dapm_routes	= ARRAY_SIZE(pcm512x_dapm_routes),
15135bdef14aSKuninori Morimoto 	.use_pmdown_time	= 1,
15145bdef14aSKuninori Morimoto 	.endianness		= 1,
15155a3af129SMark Brown };
15165a3af129SMark Brown 
1517806d6466SMark Brown static const struct regmap_range_cfg pcm512x_range = {
1518806d6466SMark Brown 	.name = "Pages", .range_min = PCM512x_VIRT_BASE,
1519806d6466SMark Brown 	.range_max = PCM512x_MAX_REGISTER,
1520806d6466SMark Brown 	.selector_reg = PCM512x_PAGE,
1521806d6466SMark Brown 	.selector_mask = 0xff,
1522806d6466SMark Brown 	.window_start = 0, .window_len = 0x100,
1523806d6466SMark Brown };
1524806d6466SMark Brown 
152522066226SMark Brown const struct regmap_config pcm512x_regmap = {
15265a3af129SMark Brown 	.reg_bits = 8,
15275a3af129SMark Brown 	.val_bits = 8,
15285a3af129SMark Brown 
15295a3af129SMark Brown 	.readable_reg = pcm512x_readable,
15305a3af129SMark Brown 	.volatile_reg = pcm512x_volatile,
15315a3af129SMark Brown 
1532806d6466SMark Brown 	.ranges = &pcm512x_range,
1533806d6466SMark Brown 	.num_ranges = 1,
1534806d6466SMark Brown 
15355a3af129SMark Brown 	.max_register = PCM512x_MAX_REGISTER,
15365a3af129SMark Brown 	.reg_defaults = pcm512x_reg_defaults,
15375a3af129SMark Brown 	.num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
15385a3af129SMark Brown 	.cache_type = REGCACHE_RBTREE,
15395a3af129SMark Brown };
154022066226SMark Brown EXPORT_SYMBOL_GPL(pcm512x_regmap);
15415a3af129SMark Brown 
pcm512x_probe(struct device * dev,struct regmap * regmap)154222066226SMark Brown int pcm512x_probe(struct device *dev, struct regmap *regmap)
15435a3af129SMark Brown {
15445a3af129SMark Brown 	struct pcm512x_priv *pcm512x;
15455a3af129SMark Brown 	int i, ret;
15465a3af129SMark Brown 
15475a3af129SMark Brown 	pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
15485a3af129SMark Brown 	if (!pcm512x)
15495a3af129SMark Brown 		return -ENOMEM;
15505a3af129SMark Brown 
15513500f1c5SDimitris Papavasiliou 	mutex_init(&pcm512x->mutex);
15523500f1c5SDimitris Papavasiliou 
15535a3af129SMark Brown 	dev_set_drvdata(dev, pcm512x);
15545a3af129SMark Brown 	pcm512x->regmap = regmap;
15555a3af129SMark Brown 
15565a3af129SMark Brown 	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
15575a3af129SMark Brown 		pcm512x->supplies[i].supply = pcm512x_supply_names[i];
15585a3af129SMark Brown 
15595a3af129SMark Brown 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
15605a3af129SMark Brown 				      pcm512x->supplies);
15615a3af129SMark Brown 	if (ret != 0) {
15625a3af129SMark Brown 		dev_err(dev, "Failed to get supplies: %d\n", ret);
15635a3af129SMark Brown 		return ret;
15645a3af129SMark Brown 	}
15655a3af129SMark Brown 
15665a3af129SMark Brown 	pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
15675a3af129SMark Brown 	pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
15685a3af129SMark Brown 	pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
15695a3af129SMark Brown 
15705a3af129SMark Brown 	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
15710bb423f2SGuennadi Liakhovetski 		ret = devm_regulator_register_notifier(
15720bb423f2SGuennadi Liakhovetski 						pcm512x->supplies[i].consumer,
15735a3af129SMark Brown 						&pcm512x->supply_nb[i]);
15745a3af129SMark Brown 		if (ret != 0) {
15755a3af129SMark Brown 			dev_err(dev,
15765a3af129SMark Brown 				"Failed to register regulator notifier: %d\n",
15775a3af129SMark Brown 				ret);
15785a3af129SMark Brown 		}
15795a3af129SMark Brown 	}
15805a3af129SMark Brown 
15815a3af129SMark Brown 	ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
15825a3af129SMark Brown 				    pcm512x->supplies);
15835a3af129SMark Brown 	if (ret != 0) {
15845a3af129SMark Brown 		dev_err(dev, "Failed to enable supplies: %d\n", ret);
15855a3af129SMark Brown 		return ret;
15865a3af129SMark Brown 	}
15875a3af129SMark Brown 
15885a3af129SMark Brown 	/* Reset the device, verifying I/O in the process for I2C */
15895a3af129SMark Brown 	ret = regmap_write(regmap, PCM512x_RESET,
15905a3af129SMark Brown 			   PCM512x_RSTM | PCM512x_RSTR);
15915a3af129SMark Brown 	if (ret != 0) {
15925a3af129SMark Brown 		dev_err(dev, "Failed to reset device: %d\n", ret);
15935a3af129SMark Brown 		goto err;
15945a3af129SMark Brown 	}
15955a3af129SMark Brown 
15965a3af129SMark Brown 	ret = regmap_write(regmap, PCM512x_RESET, 0);
15975a3af129SMark Brown 	if (ret != 0) {
15985a3af129SMark Brown 		dev_err(dev, "Failed to reset device: %d\n", ret);
15995a3af129SMark Brown 		goto err;
16005a3af129SMark Brown 	}
16015a3af129SMark Brown 
16025a3af129SMark Brown 	pcm512x->sclk = devm_clk_get(dev, NULL);
1603ac0a6899SMatthias Reichl 	if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) {
1604ac0a6899SMatthias Reichl 		ret = -EPROBE_DEFER;
1605ac0a6899SMatthias Reichl 		goto err;
1606ac0a6899SMatthias Reichl 	}
160781249307SPeter Rosin 	if (!IS_ERR(pcm512x->sclk)) {
16085a3af129SMark Brown 		ret = clk_prepare_enable(pcm512x->sclk);
16095a3af129SMark Brown 		if (ret != 0) {
16105a3af129SMark Brown 			dev_err(dev, "Failed to enable SCLK: %d\n", ret);
1611ac0a6899SMatthias Reichl 			goto err;
16125a3af129SMark Brown 		}
16135a3af129SMark Brown 	}
16145a3af129SMark Brown 
16155a3af129SMark Brown 	/* Default to standby mode */
16165a3af129SMark Brown 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
16175a3af129SMark Brown 				 PCM512x_RQST, PCM512x_RQST);
16185a3af129SMark Brown 	if (ret != 0) {
16195a3af129SMark Brown 		dev_err(dev, "Failed to request standby: %d\n",
16205a3af129SMark Brown 			ret);
16215a3af129SMark Brown 		goto err_clk;
16225a3af129SMark Brown 	}
16235a3af129SMark Brown 
16245a3af129SMark Brown 	pm_runtime_set_active(dev);
16255a3af129SMark Brown 	pm_runtime_enable(dev);
16265a3af129SMark Brown 	pm_runtime_idle(dev);
16275a3af129SMark Brown 
1628f086ba9dSPeter Rosin #ifdef CONFIG_OF
1629f086ba9dSPeter Rosin 	if (dev->of_node) {
1630f086ba9dSPeter Rosin 		const struct device_node *np = dev->of_node;
16312599a960SPeter Rosin 		u32 val;
1632f086ba9dSPeter Rosin 
1633f086ba9dSPeter Rosin 		if (of_property_read_u32(np, "pll-in", &val) >= 0) {
1634f086ba9dSPeter Rosin 			if (val > 6) {
1635f086ba9dSPeter Rosin 				dev_err(dev, "Invalid pll-in\n");
1636f086ba9dSPeter Rosin 				ret = -EINVAL;
1637*97b801beSZhang Qilong 				goto err_pm;
1638f086ba9dSPeter Rosin 			}
1639f086ba9dSPeter Rosin 			pcm512x->pll_in = val;
1640f086ba9dSPeter Rosin 		}
1641f086ba9dSPeter Rosin 
1642f086ba9dSPeter Rosin 		if (of_property_read_u32(np, "pll-out", &val) >= 0) {
1643f086ba9dSPeter Rosin 			if (val > 6) {
1644f086ba9dSPeter Rosin 				dev_err(dev, "Invalid pll-out\n");
1645f086ba9dSPeter Rosin 				ret = -EINVAL;
1646*97b801beSZhang Qilong 				goto err_pm;
1647f086ba9dSPeter Rosin 			}
1648f086ba9dSPeter Rosin 			pcm512x->pll_out = val;
1649f086ba9dSPeter Rosin 		}
1650f086ba9dSPeter Rosin 
1651f086ba9dSPeter Rosin 		if (!pcm512x->pll_in != !pcm512x->pll_out) {
1652f086ba9dSPeter Rosin 			dev_err(dev,
1653f086ba9dSPeter Rosin 				"Error: both pll-in and pll-out, or none\n");
1654f086ba9dSPeter Rosin 			ret = -EINVAL;
1655*97b801beSZhang Qilong 			goto err_pm;
1656f086ba9dSPeter Rosin 		}
1657f086ba9dSPeter Rosin 		if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) {
1658f086ba9dSPeter Rosin 			dev_err(dev, "Error: pll-in == pll-out\n");
1659f086ba9dSPeter Rosin 			ret = -EINVAL;
1660*97b801beSZhang Qilong 			goto err_pm;
1661f086ba9dSPeter Rosin 		}
1662f086ba9dSPeter Rosin 	}
1663f086ba9dSPeter Rosin #endif
1664f086ba9dSPeter Rosin 
16655bdef14aSKuninori Morimoto 	ret = devm_snd_soc_register_component(dev, &pcm512x_component_driver,
16665a3af129SMark Brown 				    &pcm512x_dai, 1);
16675a3af129SMark Brown 	if (ret != 0) {
16685a3af129SMark Brown 		dev_err(dev, "Failed to register CODEC: %d\n", ret);
16695a3af129SMark Brown 		goto err_pm;
16705a3af129SMark Brown 	}
16715a3af129SMark Brown 
16725a3af129SMark Brown 	return 0;
16735a3af129SMark Brown 
16745a3af129SMark Brown err_pm:
16755a3af129SMark Brown 	pm_runtime_disable(dev);
16765a3af129SMark Brown err_clk:
16775a3af129SMark Brown 	if (!IS_ERR(pcm512x->sclk))
16785a3af129SMark Brown 		clk_disable_unprepare(pcm512x->sclk);
16795a3af129SMark Brown err:
16805a3af129SMark Brown 	regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
16815a3af129SMark Brown 				     pcm512x->supplies);
16825a3af129SMark Brown 	return ret;
16835a3af129SMark Brown }
168422066226SMark Brown EXPORT_SYMBOL_GPL(pcm512x_probe);
16855a3af129SMark Brown 
pcm512x_remove(struct device * dev)168622066226SMark Brown void pcm512x_remove(struct device *dev)
16875a3af129SMark Brown {
16885a3af129SMark Brown 	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
16895a3af129SMark Brown 
16905a3af129SMark Brown 	pm_runtime_disable(dev);
16915a3af129SMark Brown 	if (!IS_ERR(pcm512x->sclk))
16925a3af129SMark Brown 		clk_disable_unprepare(pcm512x->sclk);
16935a3af129SMark Brown 	regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
16945a3af129SMark Brown 			       pcm512x->supplies);
16955a3af129SMark Brown }
169622066226SMark Brown EXPORT_SYMBOL_GPL(pcm512x_remove);
16975a3af129SMark Brown 
1698641d334bSRafael J. Wysocki #ifdef CONFIG_PM
pcm512x_suspend(struct device * dev)16995a3af129SMark Brown static int pcm512x_suspend(struct device *dev)
17005a3af129SMark Brown {
17015a3af129SMark Brown 	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
17025a3af129SMark Brown 	int ret;
17035a3af129SMark Brown 
17045a3af129SMark Brown 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
17055a3af129SMark Brown 				 PCM512x_RQPD, PCM512x_RQPD);
17065a3af129SMark Brown 	if (ret != 0) {
17075a3af129SMark Brown 		dev_err(dev, "Failed to request power down: %d\n", ret);
17085a3af129SMark Brown 		return ret;
17095a3af129SMark Brown 	}
17105a3af129SMark Brown 
17115a3af129SMark Brown 	ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
17125a3af129SMark Brown 				     pcm512x->supplies);
17135a3af129SMark Brown 	if (ret != 0) {
17145a3af129SMark Brown 		dev_err(dev, "Failed to disable supplies: %d\n", ret);
17155a3af129SMark Brown 		return ret;
17165a3af129SMark Brown 	}
17175a3af129SMark Brown 
17185a3af129SMark Brown 	if (!IS_ERR(pcm512x->sclk))
17195a3af129SMark Brown 		clk_disable_unprepare(pcm512x->sclk);
17205a3af129SMark Brown 
17215a3af129SMark Brown 	return 0;
17225a3af129SMark Brown }
17235a3af129SMark Brown 
pcm512x_resume(struct device * dev)17245a3af129SMark Brown static int pcm512x_resume(struct device *dev)
17255a3af129SMark Brown {
17265a3af129SMark Brown 	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
17275a3af129SMark Brown 	int ret;
17285a3af129SMark Brown 
17295a3af129SMark Brown 	if (!IS_ERR(pcm512x->sclk)) {
17305a3af129SMark Brown 		ret = clk_prepare_enable(pcm512x->sclk);
17315a3af129SMark Brown 		if (ret != 0) {
17325a3af129SMark Brown 			dev_err(dev, "Failed to enable SCLK: %d\n", ret);
17335a3af129SMark Brown 			return ret;
17345a3af129SMark Brown 		}
17355a3af129SMark Brown 	}
17365a3af129SMark Brown 
17375a3af129SMark Brown 	ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
17385a3af129SMark Brown 				    pcm512x->supplies);
17395a3af129SMark Brown 	if (ret != 0) {
17405a3af129SMark Brown 		dev_err(dev, "Failed to enable supplies: %d\n", ret);
17415a3af129SMark Brown 		return ret;
17425a3af129SMark Brown 	}
17435a3af129SMark Brown 
17445a3af129SMark Brown 	regcache_cache_only(pcm512x->regmap, false);
17455a3af129SMark Brown 	ret = regcache_sync(pcm512x->regmap);
17465a3af129SMark Brown 	if (ret != 0) {
17475a3af129SMark Brown 		dev_err(dev, "Failed to sync cache: %d\n", ret);
17485a3af129SMark Brown 		return ret;
17495a3af129SMark Brown 	}
17505a3af129SMark Brown 
17515a3af129SMark Brown 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
17525a3af129SMark Brown 				 PCM512x_RQPD, 0);
17535a3af129SMark Brown 	if (ret != 0) {
17545a3af129SMark Brown 		dev_err(dev, "Failed to remove power down: %d\n", ret);
17555a3af129SMark Brown 		return ret;
17565a3af129SMark Brown 	}
17575a3af129SMark Brown 
17585a3af129SMark Brown 	return 0;
17595a3af129SMark Brown }
1760ccffbd27SSachin Kamat #endif
17615a3af129SMark Brown 
176222066226SMark Brown const struct dev_pm_ops pcm512x_pm_ops = {
17635a3af129SMark Brown 	SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
17645a3af129SMark Brown };
176522066226SMark Brown EXPORT_SYMBOL_GPL(pcm512x_pm_ops);
17665a3af129SMark Brown 
17675a3af129SMark Brown MODULE_DESCRIPTION("ASoC PCM512x codec driver");
1768da924c3aSMark Brown MODULE_AUTHOR("Mark Brown <broonie@kernel.org>");
17695a3af129SMark Brown MODULE_LICENSE("GPL v2");
1770