18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for the PCM512x CODECs
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author:	Mark Brown <broonie@kernel.org>
68c2ecf20Sopenharmony_ci *		Copyright 2014 Linaro Ltd
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/clk.h>
138c2ecf20Sopenharmony_ci#include <linux/kernel.h>
148c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
158c2ecf20Sopenharmony_ci#include <linux/regmap.h>
168c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
178c2ecf20Sopenharmony_ci#include <linux/gcd.h>
188c2ecf20Sopenharmony_ci#include <sound/soc.h>
198c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
208c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
218c2ecf20Sopenharmony_ci#include <sound/tlv.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "pcm512x.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define PCM512x_NUM_SUPPLIES 3
268c2ecf20Sopenharmony_cistatic const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
278c2ecf20Sopenharmony_ci	"AVDD",
288c2ecf20Sopenharmony_ci	"DVDD",
298c2ecf20Sopenharmony_ci	"CPVDD",
308c2ecf20Sopenharmony_ci};
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistruct pcm512x_priv {
338c2ecf20Sopenharmony_ci	struct regmap *regmap;
348c2ecf20Sopenharmony_ci	struct clk *sclk;
358c2ecf20Sopenharmony_ci	struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
368c2ecf20Sopenharmony_ci	struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
378c2ecf20Sopenharmony_ci	int fmt;
388c2ecf20Sopenharmony_ci	int pll_in;
398c2ecf20Sopenharmony_ci	int pll_out;
408c2ecf20Sopenharmony_ci	int pll_r;
418c2ecf20Sopenharmony_ci	int pll_j;
428c2ecf20Sopenharmony_ci	int pll_d;
438c2ecf20Sopenharmony_ci	int pll_p;
448c2ecf20Sopenharmony_ci	unsigned long real_pll;
458c2ecf20Sopenharmony_ci	unsigned long overclock_pll;
468c2ecf20Sopenharmony_ci	unsigned long overclock_dac;
478c2ecf20Sopenharmony_ci	unsigned long overclock_dsp;
488c2ecf20Sopenharmony_ci	int mute;
498c2ecf20Sopenharmony_ci	struct mutex mutex;
508c2ecf20Sopenharmony_ci	unsigned int bclk_ratio;
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * We can't use the same notifier block for more than one supply and
558c2ecf20Sopenharmony_ci * there's no way I can see to get from a callback to the caller
568c2ecf20Sopenharmony_ci * except container_of().
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_ci#define PCM512x_REGULATOR_EVENT(n) \
598c2ecf20Sopenharmony_cistatic int pcm512x_regulator_event_##n(struct notifier_block *nb, \
608c2ecf20Sopenharmony_ci				      unsigned long event, void *data)    \
618c2ecf20Sopenharmony_ci{ \
628c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
638c2ecf20Sopenharmony_ci						    supply_nb[n]); \
648c2ecf20Sopenharmony_ci	if (event & REGULATOR_EVENT_DISABLE) { \
658c2ecf20Sopenharmony_ci		regcache_mark_dirty(pcm512x->regmap);	\
668c2ecf20Sopenharmony_ci		regcache_cache_only(pcm512x->regmap, true);	\
678c2ecf20Sopenharmony_ci	} \
688c2ecf20Sopenharmony_ci	return 0; \
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciPCM512x_REGULATOR_EVENT(0)
728c2ecf20Sopenharmony_ciPCM512x_REGULATOR_EVENT(1)
738c2ecf20Sopenharmony_ciPCM512x_REGULATOR_EVENT(2)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic const struct reg_default pcm512x_reg_defaults[] = {
768c2ecf20Sopenharmony_ci	{ PCM512x_RESET,             0x00 },
778c2ecf20Sopenharmony_ci	{ PCM512x_POWER,             0x00 },
788c2ecf20Sopenharmony_ci	{ PCM512x_MUTE,              0x00 },
798c2ecf20Sopenharmony_ci	{ PCM512x_DSP,               0x00 },
808c2ecf20Sopenharmony_ci	{ PCM512x_PLL_REF,           0x00 },
818c2ecf20Sopenharmony_ci	{ PCM512x_DAC_REF,           0x00 },
828c2ecf20Sopenharmony_ci	{ PCM512x_DAC_ROUTING,       0x11 },
838c2ecf20Sopenharmony_ci	{ PCM512x_DSP_PROGRAM,       0x01 },
848c2ecf20Sopenharmony_ci	{ PCM512x_CLKDET,            0x00 },
858c2ecf20Sopenharmony_ci	{ PCM512x_AUTO_MUTE,         0x00 },
868c2ecf20Sopenharmony_ci	{ PCM512x_ERROR_DETECT,      0x00 },
878c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_VOLUME_1,  0x00 },
888c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_VOLUME_2,  0x30 },
898c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_VOLUME_3,  0x30 },
908c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_MUTE_1,    0x22 },
918c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_MUTE_2,    0x00 },
928c2ecf20Sopenharmony_ci	{ PCM512x_DIGITAL_MUTE_3,    0x07 },
938c2ecf20Sopenharmony_ci	{ PCM512x_OUTPUT_AMPLITUDE,  0x00 },
948c2ecf20Sopenharmony_ci	{ PCM512x_ANALOG_GAIN_CTRL,  0x00 },
958c2ecf20Sopenharmony_ci	{ PCM512x_UNDERVOLTAGE_PROT, 0x00 },
968c2ecf20Sopenharmony_ci	{ PCM512x_ANALOG_MUTE_CTRL,  0x00 },
978c2ecf20Sopenharmony_ci	{ PCM512x_ANALOG_GAIN_BOOST, 0x00 },
988c2ecf20Sopenharmony_ci	{ PCM512x_VCOM_CTRL_1,       0x00 },
998c2ecf20Sopenharmony_ci	{ PCM512x_VCOM_CTRL_2,       0x01 },
1008c2ecf20Sopenharmony_ci	{ PCM512x_BCLK_LRCLK_CFG,    0x00 },
1018c2ecf20Sopenharmony_ci	{ PCM512x_MASTER_MODE,       0x7c },
1028c2ecf20Sopenharmony_ci	{ PCM512x_GPIO_DACIN,        0x00 },
1038c2ecf20Sopenharmony_ci	{ PCM512x_GPIO_PLLIN,        0x00 },
1048c2ecf20Sopenharmony_ci	{ PCM512x_SYNCHRONIZE,       0x10 },
1058c2ecf20Sopenharmony_ci	{ PCM512x_PLL_COEFF_0,       0x00 },
1068c2ecf20Sopenharmony_ci	{ PCM512x_PLL_COEFF_1,       0x00 },
1078c2ecf20Sopenharmony_ci	{ PCM512x_PLL_COEFF_2,       0x00 },
1088c2ecf20Sopenharmony_ci	{ PCM512x_PLL_COEFF_3,       0x00 },
1098c2ecf20Sopenharmony_ci	{ PCM512x_PLL_COEFF_4,       0x00 },
1108c2ecf20Sopenharmony_ci	{ PCM512x_DSP_CLKDIV,        0x00 },
1118c2ecf20Sopenharmony_ci	{ PCM512x_DAC_CLKDIV,        0x00 },
1128c2ecf20Sopenharmony_ci	{ PCM512x_NCP_CLKDIV,        0x00 },
1138c2ecf20Sopenharmony_ci	{ PCM512x_OSR_CLKDIV,        0x00 },
1148c2ecf20Sopenharmony_ci	{ PCM512x_MASTER_CLKDIV_1,   0x00 },
1158c2ecf20Sopenharmony_ci	{ PCM512x_MASTER_CLKDIV_2,   0x00 },
1168c2ecf20Sopenharmony_ci	{ PCM512x_FS_SPEED_MODE,     0x00 },
1178c2ecf20Sopenharmony_ci	{ PCM512x_IDAC_1,            0x01 },
1188c2ecf20Sopenharmony_ci	{ PCM512x_IDAC_2,            0x00 },
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic bool pcm512x_readable(struct device *dev, unsigned int reg)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	switch (reg) {
1248c2ecf20Sopenharmony_ci	case PCM512x_RESET:
1258c2ecf20Sopenharmony_ci	case PCM512x_POWER:
1268c2ecf20Sopenharmony_ci	case PCM512x_MUTE:
1278c2ecf20Sopenharmony_ci	case PCM512x_PLL_EN:
1288c2ecf20Sopenharmony_ci	case PCM512x_SPI_MISO_FUNCTION:
1298c2ecf20Sopenharmony_ci	case PCM512x_DSP:
1308c2ecf20Sopenharmony_ci	case PCM512x_GPIO_EN:
1318c2ecf20Sopenharmony_ci	case PCM512x_BCLK_LRCLK_CFG:
1328c2ecf20Sopenharmony_ci	case PCM512x_DSP_GPIO_INPUT:
1338c2ecf20Sopenharmony_ci	case PCM512x_MASTER_MODE:
1348c2ecf20Sopenharmony_ci	case PCM512x_PLL_REF:
1358c2ecf20Sopenharmony_ci	case PCM512x_DAC_REF:
1368c2ecf20Sopenharmony_ci	case PCM512x_GPIO_DACIN:
1378c2ecf20Sopenharmony_ci	case PCM512x_GPIO_PLLIN:
1388c2ecf20Sopenharmony_ci	case PCM512x_SYNCHRONIZE:
1398c2ecf20Sopenharmony_ci	case PCM512x_PLL_COEFF_0:
1408c2ecf20Sopenharmony_ci	case PCM512x_PLL_COEFF_1:
1418c2ecf20Sopenharmony_ci	case PCM512x_PLL_COEFF_2:
1428c2ecf20Sopenharmony_ci	case PCM512x_PLL_COEFF_3:
1438c2ecf20Sopenharmony_ci	case PCM512x_PLL_COEFF_4:
1448c2ecf20Sopenharmony_ci	case PCM512x_DSP_CLKDIV:
1458c2ecf20Sopenharmony_ci	case PCM512x_DAC_CLKDIV:
1468c2ecf20Sopenharmony_ci	case PCM512x_NCP_CLKDIV:
1478c2ecf20Sopenharmony_ci	case PCM512x_OSR_CLKDIV:
1488c2ecf20Sopenharmony_ci	case PCM512x_MASTER_CLKDIV_1:
1498c2ecf20Sopenharmony_ci	case PCM512x_MASTER_CLKDIV_2:
1508c2ecf20Sopenharmony_ci	case PCM512x_FS_SPEED_MODE:
1518c2ecf20Sopenharmony_ci	case PCM512x_IDAC_1:
1528c2ecf20Sopenharmony_ci	case PCM512x_IDAC_2:
1538c2ecf20Sopenharmony_ci	case PCM512x_ERROR_DETECT:
1548c2ecf20Sopenharmony_ci	case PCM512x_I2S_1:
1558c2ecf20Sopenharmony_ci	case PCM512x_I2S_2:
1568c2ecf20Sopenharmony_ci	case PCM512x_DAC_ROUTING:
1578c2ecf20Sopenharmony_ci	case PCM512x_DSP_PROGRAM:
1588c2ecf20Sopenharmony_ci	case PCM512x_CLKDET:
1598c2ecf20Sopenharmony_ci	case PCM512x_AUTO_MUTE:
1608c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_VOLUME_1:
1618c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_VOLUME_2:
1628c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_VOLUME_3:
1638c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_MUTE_1:
1648c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_MUTE_2:
1658c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_MUTE_3:
1668c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_1:
1678c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_2:
1688c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_3:
1698c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_4:
1708c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_5:
1718c2ecf20Sopenharmony_ci	case PCM512x_GPIO_OUTPUT_6:
1728c2ecf20Sopenharmony_ci	case PCM512x_GPIO_CONTROL_1:
1738c2ecf20Sopenharmony_ci	case PCM512x_GPIO_CONTROL_2:
1748c2ecf20Sopenharmony_ci	case PCM512x_OVERFLOW:
1758c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_1:
1768c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_2:
1778c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_3:
1788c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_4:
1798c2ecf20Sopenharmony_ci	case PCM512x_CLOCK_STATUS:
1808c2ecf20Sopenharmony_ci	case PCM512x_ANALOG_MUTE_DET:
1818c2ecf20Sopenharmony_ci	case PCM512x_GPIN:
1828c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_MUTE_DET:
1838c2ecf20Sopenharmony_ci	case PCM512x_OUTPUT_AMPLITUDE:
1848c2ecf20Sopenharmony_ci	case PCM512x_ANALOG_GAIN_CTRL:
1858c2ecf20Sopenharmony_ci	case PCM512x_UNDERVOLTAGE_PROT:
1868c2ecf20Sopenharmony_ci	case PCM512x_ANALOG_MUTE_CTRL:
1878c2ecf20Sopenharmony_ci	case PCM512x_ANALOG_GAIN_BOOST:
1888c2ecf20Sopenharmony_ci	case PCM512x_VCOM_CTRL_1:
1898c2ecf20Sopenharmony_ci	case PCM512x_VCOM_CTRL_2:
1908c2ecf20Sopenharmony_ci	case PCM512x_CRAM_CTRL:
1918c2ecf20Sopenharmony_ci	case PCM512x_FLEX_A:
1928c2ecf20Sopenharmony_ci	case PCM512x_FLEX_B:
1938c2ecf20Sopenharmony_ci		return true;
1948c2ecf20Sopenharmony_ci	default:
1958c2ecf20Sopenharmony_ci		/* There are 256 raw register addresses */
1968c2ecf20Sopenharmony_ci		return reg < 0xff;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic bool pcm512x_volatile(struct device *dev, unsigned int reg)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	switch (reg) {
2038c2ecf20Sopenharmony_ci	case PCM512x_PLL_EN:
2048c2ecf20Sopenharmony_ci	case PCM512x_OVERFLOW:
2058c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_1:
2068c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_2:
2078c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_3:
2088c2ecf20Sopenharmony_ci	case PCM512x_RATE_DET_4:
2098c2ecf20Sopenharmony_ci	case PCM512x_CLOCK_STATUS:
2108c2ecf20Sopenharmony_ci	case PCM512x_ANALOG_MUTE_DET:
2118c2ecf20Sopenharmony_ci	case PCM512x_GPIN:
2128c2ecf20Sopenharmony_ci	case PCM512x_DIGITAL_MUTE_DET:
2138c2ecf20Sopenharmony_ci	case PCM512x_CRAM_CTRL:
2148c2ecf20Sopenharmony_ci		return true;
2158c2ecf20Sopenharmony_ci	default:
2168c2ecf20Sopenharmony_ci		/* There are 256 raw register addresses */
2178c2ecf20Sopenharmony_ci		return reg < 0xff;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
2228c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2258c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
2288c2ecf20Sopenharmony_ci	return 0;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
2328c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2358c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	switch (snd_soc_component_get_bias_level(component)) {
2388c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_OFF:
2398c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
2408c2ecf20Sopenharmony_ci		break;
2418c2ecf20Sopenharmony_ci	default:
2428c2ecf20Sopenharmony_ci		return -EBUSY;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	pcm512x->overclock_pll = ucontrol->value.integer.value[0];
2468c2ecf20Sopenharmony_ci	return 0;
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
2508c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2538c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
2568c2ecf20Sopenharmony_ci	return 0;
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistatic int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
2608c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2638c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	switch (snd_soc_component_get_bias_level(component)) {
2668c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_OFF:
2678c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
2688c2ecf20Sopenharmony_ci		break;
2698c2ecf20Sopenharmony_ci	default:
2708c2ecf20Sopenharmony_ci		return -EBUSY;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
2748c2ecf20Sopenharmony_ci	return 0;
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
2788c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2818c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
2848c2ecf20Sopenharmony_ci	return 0;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
2888c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
2918c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	switch (snd_soc_component_get_bias_level(component)) {
2948c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_OFF:
2958c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
2968c2ecf20Sopenharmony_ci		break;
2978c2ecf20Sopenharmony_ci	default:
2988c2ecf20Sopenharmony_ci		return -EBUSY;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	pcm512x->overclock_dac = ucontrol->value.integer.value[0];
3028c2ecf20Sopenharmony_ci	return 0;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
3068c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
3078c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic const char * const pcm512x_dsp_program_texts[] = {
3108c2ecf20Sopenharmony_ci	"FIR interpolation with de-emphasis",
3118c2ecf20Sopenharmony_ci	"Low latency IIR with de-emphasis",
3128c2ecf20Sopenharmony_ci	"High attenuation with de-emphasis",
3138c2ecf20Sopenharmony_ci	"Fixed process flow",
3148c2ecf20Sopenharmony_ci	"Ringing-less low latency FIR",
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const unsigned int pcm512x_dsp_program_values[] = {
3188c2ecf20Sopenharmony_ci	1,
3198c2ecf20Sopenharmony_ci	2,
3208c2ecf20Sopenharmony_ci	3,
3218c2ecf20Sopenharmony_ci	5,
3228c2ecf20Sopenharmony_ci	7,
3238c2ecf20Sopenharmony_ci};
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
3268c2ecf20Sopenharmony_ci				  PCM512x_DSP_PROGRAM, 0, 0x1f,
3278c2ecf20Sopenharmony_ci				  pcm512x_dsp_program_texts,
3288c2ecf20Sopenharmony_ci				  pcm512x_dsp_program_values);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic const char * const pcm512x_clk_missing_text[] = {
3318c2ecf20Sopenharmony_ci	"1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_clk_missing =
3358c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_CLKDET, 0,  8, pcm512x_clk_missing_text);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic const char * const pcm512x_autom_text[] = {
3388c2ecf20Sopenharmony_ci	"21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
3398c2ecf20Sopenharmony_ci};
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_autom_l =
3428c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
3438c2ecf20Sopenharmony_ci			pcm512x_autom_text);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_autom_r =
3468c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
3478c2ecf20Sopenharmony_ci			pcm512x_autom_text);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic const char * const pcm512x_ramp_rate_text[] = {
3508c2ecf20Sopenharmony_ci	"1 sample/update", "2 samples/update", "4 samples/update",
3518c2ecf20Sopenharmony_ci	"Immediate"
3528c2ecf20Sopenharmony_ci};
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_vndf =
3558c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
3568c2ecf20Sopenharmony_ci			pcm512x_ramp_rate_text);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_vnuf =
3598c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
3608c2ecf20Sopenharmony_ci			pcm512x_ramp_rate_text);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_vedf =
3638c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
3648c2ecf20Sopenharmony_ci			pcm512x_ramp_rate_text);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic const char * const pcm512x_ramp_step_text[] = {
3678c2ecf20Sopenharmony_ci	"4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
3688c2ecf20Sopenharmony_ci};
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_vnds =
3718c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
3728c2ecf20Sopenharmony_ci			pcm512x_ramp_step_text);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_vnus =
3758c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
3768c2ecf20Sopenharmony_ci			pcm512x_ramp_step_text);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic const struct soc_enum pcm512x_veds =
3798c2ecf20Sopenharmony_ci	SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
3808c2ecf20Sopenharmony_ci			pcm512x_ramp_step_text);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic int pcm512x_update_mute(struct pcm512x_priv *pcm512x)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	return regmap_update_bits(
3858c2ecf20Sopenharmony_ci		pcm512x->regmap, PCM512x_MUTE, PCM512x_RQML | PCM512x_RQMR,
3868c2ecf20Sopenharmony_ci		(!!(pcm512x->mute & 0x5) << PCM512x_RQML_SHIFT)
3878c2ecf20Sopenharmony_ci		| (!!(pcm512x->mute & 0x3) << PCM512x_RQMR_SHIFT));
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic int pcm512x_digital_playback_switch_get(struct snd_kcontrol *kcontrol,
3918c2ecf20Sopenharmony_ci					       struct snd_ctl_elem_value *ucontrol)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3948c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	mutex_lock(&pcm512x->mutex);
3978c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = !(pcm512x->mute & 0x4);
3988c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[1] = !(pcm512x->mute & 0x2);
3998c2ecf20Sopenharmony_ci	mutex_unlock(&pcm512x->mutex);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	return 0;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic int pcm512x_digital_playback_switch_put(struct snd_kcontrol *kcontrol,
4058c2ecf20Sopenharmony_ci					       struct snd_ctl_elem_value *ucontrol)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
4088c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
4098c2ecf20Sopenharmony_ci	int ret, changed = 0;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	mutex_lock(&pcm512x->mutex);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if ((pcm512x->mute & 0x4) == (ucontrol->value.integer.value[0] << 2)) {
4148c2ecf20Sopenharmony_ci		pcm512x->mute ^= 0x4;
4158c2ecf20Sopenharmony_ci		changed = 1;
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci	if ((pcm512x->mute & 0x2) == (ucontrol->value.integer.value[1] << 1)) {
4188c2ecf20Sopenharmony_ci		pcm512x->mute ^= 0x2;
4198c2ecf20Sopenharmony_ci		changed = 1;
4208c2ecf20Sopenharmony_ci	}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (changed) {
4238c2ecf20Sopenharmony_ci		ret = pcm512x_update_mute(pcm512x);
4248c2ecf20Sopenharmony_ci		if (ret != 0) {
4258c2ecf20Sopenharmony_ci			dev_err(component->dev,
4268c2ecf20Sopenharmony_ci				"Failed to update digital mute: %d\n", ret);
4278c2ecf20Sopenharmony_ci			mutex_unlock(&pcm512x->mutex);
4288c2ecf20Sopenharmony_ci			return ret;
4298c2ecf20Sopenharmony_ci		}
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	mutex_unlock(&pcm512x->mutex);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	return changed;
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new pcm512x_controls[] = {
4388c2ecf20Sopenharmony_ciSOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
4398c2ecf20Sopenharmony_ci		 PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
4408c2ecf20Sopenharmony_ciSOC_DOUBLE_TLV("Analogue Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
4418c2ecf20Sopenharmony_ci	       PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
4428c2ecf20Sopenharmony_ciSOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
4438c2ecf20Sopenharmony_ci	       PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
4448c2ecf20Sopenharmony_ci{
4458c2ecf20Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4468c2ecf20Sopenharmony_ci	.name = "Digital Playback Switch",
4478c2ecf20Sopenharmony_ci	.index = 0,
4488c2ecf20Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
4498c2ecf20Sopenharmony_ci	.info = snd_ctl_boolean_stereo_info,
4508c2ecf20Sopenharmony_ci	.get = pcm512x_digital_playback_switch_get,
4518c2ecf20Sopenharmony_ci	.put = pcm512x_digital_playback_switch_put
4528c2ecf20Sopenharmony_ci},
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ciSOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
4558c2ecf20Sopenharmony_ciSOC_ENUM("DSP Program", pcm512x_dsp_program),
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ciSOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
4588c2ecf20Sopenharmony_ciSOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
4598c2ecf20Sopenharmony_ciSOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
4608c2ecf20Sopenharmony_ciSOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
4618c2ecf20Sopenharmony_ci	   PCM512x_ACTL_SHIFT, 1, 0),
4628c2ecf20Sopenharmony_ciSOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
4638c2ecf20Sopenharmony_ci	   PCM512x_AMRE_SHIFT, 1, 0),
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
4668c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
4678c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
4688c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
4698c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
4708c2ecf20Sopenharmony_ciSOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ciSOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
4738c2ecf20Sopenharmony_ci	       pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
4748c2ecf20Sopenharmony_ciSOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
4758c2ecf20Sopenharmony_ci	       pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
4768c2ecf20Sopenharmony_ciSOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
4778c2ecf20Sopenharmony_ci	       pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
4788c2ecf20Sopenharmony_ci};
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
4818c2ecf20Sopenharmony_ciSND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
4828c2ecf20Sopenharmony_ciSND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ciSND_SOC_DAPM_OUTPUT("OUTL"),
4858c2ecf20Sopenharmony_ciSND_SOC_DAPM_OUTPUT("OUTR"),
4868c2ecf20Sopenharmony_ci};
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
4898c2ecf20Sopenharmony_ci	{ "DACL", NULL, "Playback" },
4908c2ecf20Sopenharmony_ci	{ "DACR", NULL, "Playback" },
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	{ "OUTL", NULL, "DACL" },
4938c2ecf20Sopenharmony_ci	{ "OUTR", NULL, "DACR" },
4948c2ecf20Sopenharmony_ci};
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cistatic unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
5078c2ecf20Sopenharmony_ci				     unsigned long rate)
5088c2ecf20Sopenharmony_ci{
5098c2ecf20Sopenharmony_ci	return rate + rate * pcm512x->overclock_dac / 100;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	if (!pcm512x->pll_out)
5158c2ecf20Sopenharmony_ci		return 25000000;
5168c2ecf20Sopenharmony_ci	return pcm512x_pll_max(pcm512x);
5178c2ecf20Sopenharmony_ci}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
5208c2ecf20Sopenharmony_ci					unsigned long dac_rate)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	/*
5238c2ecf20Sopenharmony_ci	 * If the DAC is not actually overclocked, use the good old
5248c2ecf20Sopenharmony_ci	 * NCP target rate...
5258c2ecf20Sopenharmony_ci	 */
5268c2ecf20Sopenharmony_ci	if (dac_rate <= 6144000)
5278c2ecf20Sopenharmony_ci		return 1536000;
5288c2ecf20Sopenharmony_ci	/*
5298c2ecf20Sopenharmony_ci	 * ...but if the DAC is in fact overclocked, bump the NCP target
5308c2ecf20Sopenharmony_ci	 * rate to get the recommended dividers even when overclocking.
5318c2ecf20Sopenharmony_ci	 */
5328c2ecf20Sopenharmony_ci	return pcm512x_dac_max(pcm512x, 1536000);
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_cistatic const u32 pcm512x_dai_rates[] = {
5368c2ecf20Sopenharmony_ci	8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
5378c2ecf20Sopenharmony_ci	88200, 96000, 176400, 192000, 384000,
5388c2ecf20Sopenharmony_ci};
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list constraints_slave = {
5418c2ecf20Sopenharmony_ci	.count = ARRAY_SIZE(pcm512x_dai_rates),
5428c2ecf20Sopenharmony_ci	.list  = pcm512x_dai_rates,
5438c2ecf20Sopenharmony_ci};
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
5468c2ecf20Sopenharmony_ci				struct snd_pcm_hw_rule *rule)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = rule->private;
5498c2ecf20Sopenharmony_ci	struct snd_interval ranges[2];
5508c2ecf20Sopenharmony_ci	int frame_size;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	frame_size = snd_soc_params_to_frame_size(params);
5538c2ecf20Sopenharmony_ci	if (frame_size < 0)
5548c2ecf20Sopenharmony_ci		return frame_size;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	switch (frame_size) {
5578c2ecf20Sopenharmony_ci	case 32:
5588c2ecf20Sopenharmony_ci		/* No hole when the frame size is 32. */
5598c2ecf20Sopenharmony_ci		return 0;
5608c2ecf20Sopenharmony_ci	case 48:
5618c2ecf20Sopenharmony_ci	case 64:
5628c2ecf20Sopenharmony_ci		/* There is only one hole in the range of supported
5638c2ecf20Sopenharmony_ci		 * rates, but it moves with the frame size.
5648c2ecf20Sopenharmony_ci		 */
5658c2ecf20Sopenharmony_ci		memset(ranges, 0, sizeof(ranges));
5668c2ecf20Sopenharmony_ci		ranges[0].min = 8000;
5678c2ecf20Sopenharmony_ci		ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
5688c2ecf20Sopenharmony_ci		ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
5698c2ecf20Sopenharmony_ci		ranges[1].max = 384000;
5708c2ecf20Sopenharmony_ci		break;
5718c2ecf20Sopenharmony_ci	default:
5728c2ecf20Sopenharmony_ci		return -EINVAL;
5738c2ecf20Sopenharmony_ci	}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	return snd_interval_ranges(hw_param_interval(params, rule->var),
5768c2ecf20Sopenharmony_ci				   ARRAY_SIZE(ranges), ranges, 0);
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_cistatic int pcm512x_dai_startup_master(struct snd_pcm_substream *substream,
5808c2ecf20Sopenharmony_ci				      struct snd_soc_dai *dai)
5818c2ecf20Sopenharmony_ci{
5828c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
5838c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
5848c2ecf20Sopenharmony_ci	struct device *dev = dai->dev;
5858c2ecf20Sopenharmony_ci	struct snd_pcm_hw_constraint_ratnums *constraints_no_pll;
5868c2ecf20Sopenharmony_ci	struct snd_ratnum *rats_no_pll;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	if (IS_ERR(pcm512x->sclk)) {
5898c2ecf20Sopenharmony_ci		dev_err(dev, "Need SCLK for master mode: %ld\n",
5908c2ecf20Sopenharmony_ci			PTR_ERR(pcm512x->sclk));
5918c2ecf20Sopenharmony_ci		return PTR_ERR(pcm512x->sclk);
5928c2ecf20Sopenharmony_ci	}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	if (pcm512x->pll_out)
5958c2ecf20Sopenharmony_ci		return snd_pcm_hw_rule_add(substream->runtime, 0,
5968c2ecf20Sopenharmony_ci					   SNDRV_PCM_HW_PARAM_RATE,
5978c2ecf20Sopenharmony_ci					   pcm512x_hw_rule_rate,
5988c2ecf20Sopenharmony_ci					   pcm512x,
5998c2ecf20Sopenharmony_ci					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
6008c2ecf20Sopenharmony_ci					   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	constraints_no_pll = devm_kzalloc(dev, sizeof(*constraints_no_pll),
6038c2ecf20Sopenharmony_ci					  GFP_KERNEL);
6048c2ecf20Sopenharmony_ci	if (!constraints_no_pll)
6058c2ecf20Sopenharmony_ci		return -ENOMEM;
6068c2ecf20Sopenharmony_ci	constraints_no_pll->nrats = 1;
6078c2ecf20Sopenharmony_ci	rats_no_pll = devm_kzalloc(dev, sizeof(*rats_no_pll), GFP_KERNEL);
6088c2ecf20Sopenharmony_ci	if (!rats_no_pll)
6098c2ecf20Sopenharmony_ci		return -ENOMEM;
6108c2ecf20Sopenharmony_ci	constraints_no_pll->rats = rats_no_pll;
6118c2ecf20Sopenharmony_ci	rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
6128c2ecf20Sopenharmony_ci	rats_no_pll->den_min = 1;
6138c2ecf20Sopenharmony_ci	rats_no_pll->den_max = 128;
6148c2ecf20Sopenharmony_ci	rats_no_pll->den_step = 1;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
6178c2ecf20Sopenharmony_ci					     SNDRV_PCM_HW_PARAM_RATE,
6188c2ecf20Sopenharmony_ci					     constraints_no_pll);
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_cistatic int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream,
6228c2ecf20Sopenharmony_ci				     struct snd_soc_dai *dai)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
6258c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
6268c2ecf20Sopenharmony_ci	struct device *dev = dai->dev;
6278c2ecf20Sopenharmony_ci	struct regmap *regmap = pcm512x->regmap;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (IS_ERR(pcm512x->sclk)) {
6308c2ecf20Sopenharmony_ci		dev_info(dev, "No SCLK, using BCLK: %ld\n",
6318c2ecf20Sopenharmony_ci			 PTR_ERR(pcm512x->sclk));
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci		/* Disable reporting of missing SCLK as an error */
6348c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
6358c2ecf20Sopenharmony_ci				   PCM512x_IDCH, PCM512x_IDCH);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci		/* Switch PLL input to BCLK */
6388c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, PCM512x_PLL_REF,
6398c2ecf20Sopenharmony_ci				   PCM512x_SREF, PCM512x_SREF_BCK);
6408c2ecf20Sopenharmony_ci	}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	return snd_pcm_hw_constraint_list(substream->runtime, 0,
6438c2ecf20Sopenharmony_ci					  SNDRV_PCM_HW_PARAM_RATE,
6448c2ecf20Sopenharmony_ci					  &constraints_slave);
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistatic int pcm512x_dai_startup(struct snd_pcm_substream *substream,
6488c2ecf20Sopenharmony_ci			       struct snd_soc_dai *dai)
6498c2ecf20Sopenharmony_ci{
6508c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
6518c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
6548c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
6558c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFS:
6568c2ecf20Sopenharmony_ci		return pcm512x_dai_startup_master(substream, dai);
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBS_CFS:
6598c2ecf20Sopenharmony_ci		return pcm512x_dai_startup_slave(substream, dai);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	default:
6628c2ecf20Sopenharmony_ci		return -EINVAL;
6638c2ecf20Sopenharmony_ci	}
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_cistatic int pcm512x_set_bias_level(struct snd_soc_component *component,
6678c2ecf20Sopenharmony_ci				  enum snd_soc_bias_level level)
6688c2ecf20Sopenharmony_ci{
6698c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = dev_get_drvdata(component->dev);
6708c2ecf20Sopenharmony_ci	int ret;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	switch (level) {
6738c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_ON:
6748c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
6758c2ecf20Sopenharmony_ci		break;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
6788c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
6798c2ecf20Sopenharmony_ci					 PCM512x_RQST, 0);
6808c2ecf20Sopenharmony_ci		if (ret != 0) {
6818c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to remove standby: %d\n",
6828c2ecf20Sopenharmony_ci				ret);
6838c2ecf20Sopenharmony_ci			return ret;
6848c2ecf20Sopenharmony_ci		}
6858c2ecf20Sopenharmony_ci		break;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_OFF:
6888c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
6898c2ecf20Sopenharmony_ci					 PCM512x_RQST, PCM512x_RQST);
6908c2ecf20Sopenharmony_ci		if (ret != 0) {
6918c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to request standby: %d\n",
6928c2ecf20Sopenharmony_ci				ret);
6938c2ecf20Sopenharmony_ci			return ret;
6948c2ecf20Sopenharmony_ci		}
6958c2ecf20Sopenharmony_ci		break;
6968c2ecf20Sopenharmony_ci	}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	return 0;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic unsigned long pcm512x_find_sck(struct snd_soc_dai *dai,
7028c2ecf20Sopenharmony_ci				      unsigned long bclk_rate)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	struct device *dev = dai->dev;
7058c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
7068c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7078c2ecf20Sopenharmony_ci	unsigned long sck_rate;
7088c2ecf20Sopenharmony_ci	int pow2;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	/* 64 MHz <= pll_rate <= 100 MHz, VREF mode */
7118c2ecf20Sopenharmony_ci	/* 16 MHz <= sck_rate <=  25 MHz, VREF mode */
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/* select sck_rate as a multiple of bclk_rate but still with
7148c2ecf20Sopenharmony_ci	 * as many factors of 2 as possible, as that makes it easier
7158c2ecf20Sopenharmony_ci	 * to find a fast DAC rate
7168c2ecf20Sopenharmony_ci	 */
7178c2ecf20Sopenharmony_ci	pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
7188c2ecf20Sopenharmony_ci	for (; pow2; pow2 >>= 1) {
7198c2ecf20Sopenharmony_ci		sck_rate = rounddown(pcm512x_pll_max(pcm512x),
7208c2ecf20Sopenharmony_ci				     bclk_rate * pow2);
7218c2ecf20Sopenharmony_ci		if (sck_rate >= 16000000)
7228c2ecf20Sopenharmony_ci			break;
7238c2ecf20Sopenharmony_ci	}
7248c2ecf20Sopenharmony_ci	if (!pow2) {
7258c2ecf20Sopenharmony_ci		dev_err(dev, "Impossible to generate a suitable SCK\n");
7268c2ecf20Sopenharmony_ci		return 0;
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	dev_dbg(dev, "sck_rate %lu\n", sck_rate);
7308c2ecf20Sopenharmony_ci	return sck_rate;
7318c2ecf20Sopenharmony_ci}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci/* pll_rate = pllin_rate * R * J.D / P
7348c2ecf20Sopenharmony_ci * 1 <= R <= 16
7358c2ecf20Sopenharmony_ci * 1 <= J <= 63
7368c2ecf20Sopenharmony_ci * 0 <= D <= 9999
7378c2ecf20Sopenharmony_ci * 1 <= P <= 15
7388c2ecf20Sopenharmony_ci * 64 MHz <= pll_rate <= 100 MHz
7398c2ecf20Sopenharmony_ci * if D == 0
7408c2ecf20Sopenharmony_ci *     1 MHz <= pllin_rate / P <= 20 MHz
7418c2ecf20Sopenharmony_ci * else if D > 0
7428c2ecf20Sopenharmony_ci *     6.667 MHz <= pllin_rate / P <= 20 MHz
7438c2ecf20Sopenharmony_ci *     4 <= J <= 11
7448c2ecf20Sopenharmony_ci *     R = 1
7458c2ecf20Sopenharmony_ci */
7468c2ecf20Sopenharmony_cistatic int pcm512x_find_pll_coeff(struct snd_soc_dai *dai,
7478c2ecf20Sopenharmony_ci				  unsigned long pllin_rate,
7488c2ecf20Sopenharmony_ci				  unsigned long pll_rate)
7498c2ecf20Sopenharmony_ci{
7508c2ecf20Sopenharmony_ci	struct device *dev = dai->dev;
7518c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
7528c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
7538c2ecf20Sopenharmony_ci	unsigned long common;
7548c2ecf20Sopenharmony_ci	int R, J, D, P;
7558c2ecf20Sopenharmony_ci	unsigned long K; /* 10000 * J.D */
7568c2ecf20Sopenharmony_ci	unsigned long num;
7578c2ecf20Sopenharmony_ci	unsigned long den;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	common = gcd(pll_rate, pllin_rate);
7608c2ecf20Sopenharmony_ci	dev_dbg(dev, "pll %lu pllin %lu common %lu\n",
7618c2ecf20Sopenharmony_ci		pll_rate, pllin_rate, common);
7628c2ecf20Sopenharmony_ci	num = pll_rate / common;
7638c2ecf20Sopenharmony_ci	den = pllin_rate / common;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* pllin_rate / P (or here, den) cannot be greater than 20 MHz */
7668c2ecf20Sopenharmony_ci	if (pllin_rate / den > 20000000 && num < 8) {
7678c2ecf20Sopenharmony_ci		num *= DIV_ROUND_UP(pllin_rate / den, 20000000);
7688c2ecf20Sopenharmony_ci		den *= DIV_ROUND_UP(pllin_rate / den, 20000000);
7698c2ecf20Sopenharmony_ci	}
7708c2ecf20Sopenharmony_ci	dev_dbg(dev, "num / den = %lu / %lu\n", num, den);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	P = den;
7738c2ecf20Sopenharmony_ci	if (den <= 15 && num <= 16 * 63
7748c2ecf20Sopenharmony_ci	    && 1000000 <= pllin_rate / P && pllin_rate / P <= 20000000) {
7758c2ecf20Sopenharmony_ci		/* Try the case with D = 0 */
7768c2ecf20Sopenharmony_ci		D = 0;
7778c2ecf20Sopenharmony_ci		/* factor 'num' into J and R, such that R <= 16 and J <= 63 */
7788c2ecf20Sopenharmony_ci		for (R = 16; R; R--) {
7798c2ecf20Sopenharmony_ci			if (num % R)
7808c2ecf20Sopenharmony_ci				continue;
7818c2ecf20Sopenharmony_ci			J = num / R;
7828c2ecf20Sopenharmony_ci			if (J == 0 || J > 63)
7838c2ecf20Sopenharmony_ci				continue;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci			dev_dbg(dev, "R * J / P = %d * %d / %d\n", R, J, P);
7868c2ecf20Sopenharmony_ci			pcm512x->real_pll = pll_rate;
7878c2ecf20Sopenharmony_ci			goto done;
7888c2ecf20Sopenharmony_ci		}
7898c2ecf20Sopenharmony_ci		/* no luck */
7908c2ecf20Sopenharmony_ci	}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	R = 1;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	if (num > 0xffffffffUL / 10000)
7958c2ecf20Sopenharmony_ci		goto fallback;
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	/* Try to find an exact pll_rate using the D > 0 case */
7988c2ecf20Sopenharmony_ci	common = gcd(10000 * num, den);
7998c2ecf20Sopenharmony_ci	num = 10000 * num / common;
8008c2ecf20Sopenharmony_ci	den /= common;
8018c2ecf20Sopenharmony_ci	dev_dbg(dev, "num %lu den %lu common %lu\n", num, den, common);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	for (P = den; P <= 15; P++) {
8048c2ecf20Sopenharmony_ci		if (pllin_rate / P < 6667000 || 200000000 < pllin_rate / P)
8058c2ecf20Sopenharmony_ci			continue;
8068c2ecf20Sopenharmony_ci		if (num * P % den)
8078c2ecf20Sopenharmony_ci			continue;
8088c2ecf20Sopenharmony_ci		K = num * P / den;
8098c2ecf20Sopenharmony_ci		/* J == 12 is ok if D == 0 */
8108c2ecf20Sopenharmony_ci		if (K < 40000 || K > 120000)
8118c2ecf20Sopenharmony_ci			continue;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		J = K / 10000;
8148c2ecf20Sopenharmony_ci		D = K % 10000;
8158c2ecf20Sopenharmony_ci		dev_dbg(dev, "J.D / P = %d.%04d / %d\n", J, D, P);
8168c2ecf20Sopenharmony_ci		pcm512x->real_pll = pll_rate;
8178c2ecf20Sopenharmony_ci		goto done;
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	/* Fall back to an approximate pll_rate */
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_cifallback:
8238c2ecf20Sopenharmony_ci	/* find smallest possible P */
8248c2ecf20Sopenharmony_ci	P = DIV_ROUND_UP(pllin_rate, 20000000);
8258c2ecf20Sopenharmony_ci	if (!P)
8268c2ecf20Sopenharmony_ci		P = 1;
8278c2ecf20Sopenharmony_ci	else if (P > 15) {
8288c2ecf20Sopenharmony_ci		dev_err(dev, "Need a slower clock as pll-input\n");
8298c2ecf20Sopenharmony_ci		return -EINVAL;
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci	if (pllin_rate / P < 6667000) {
8328c2ecf20Sopenharmony_ci		dev_err(dev, "Need a faster clock as pll-input\n");
8338c2ecf20Sopenharmony_ci		return -EINVAL;
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci	K = DIV_ROUND_CLOSEST_ULL(10000ULL * pll_rate * P, pllin_rate);
8368c2ecf20Sopenharmony_ci	if (K < 40000)
8378c2ecf20Sopenharmony_ci		K = 40000;
8388c2ecf20Sopenharmony_ci	/* J == 12 is ok if D == 0 */
8398c2ecf20Sopenharmony_ci	if (K > 120000)
8408c2ecf20Sopenharmony_ci		K = 120000;
8418c2ecf20Sopenharmony_ci	J = K / 10000;
8428c2ecf20Sopenharmony_ci	D = K % 10000;
8438c2ecf20Sopenharmony_ci	dev_dbg(dev, "J.D / P ~ %d.%04d / %d\n", J, D, P);
8448c2ecf20Sopenharmony_ci	pcm512x->real_pll = DIV_ROUND_DOWN_ULL((u64)K * pllin_rate, 10000 * P);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_cidone:
8478c2ecf20Sopenharmony_ci	pcm512x->pll_r = R;
8488c2ecf20Sopenharmony_ci	pcm512x->pll_j = J;
8498c2ecf20Sopenharmony_ci	pcm512x->pll_d = D;
8508c2ecf20Sopenharmony_ci	pcm512x->pll_p = P;
8518c2ecf20Sopenharmony_ci	return 0;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_cistatic unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
8558c2ecf20Sopenharmony_ci					    unsigned long osr_rate,
8568c2ecf20Sopenharmony_ci					    unsigned long pllin_rate)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
8598c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
8608c2ecf20Sopenharmony_ci	unsigned long dac_rate;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	if (!pcm512x->pll_out)
8638c2ecf20Sopenharmony_ci		return 0; /* no PLL to bypass, force SCK as DAC input */
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	if (pllin_rate % osr_rate)
8668c2ecf20Sopenharmony_ci		return 0; /* futile, quit early */
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	/* run DAC no faster than 6144000 Hz */
8698c2ecf20Sopenharmony_ci	for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
8708c2ecf20Sopenharmony_ci	     dac_rate;
8718c2ecf20Sopenharmony_ci	     dac_rate -= osr_rate) {
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci		if (pllin_rate / dac_rate > 128)
8748c2ecf20Sopenharmony_ci			return 0; /* DAC divider would be too big */
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci		if (!(pllin_rate % dac_rate))
8778c2ecf20Sopenharmony_ci			return dac_rate;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci		dac_rate -= osr_rate;
8808c2ecf20Sopenharmony_ci	}
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	return 0;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_cistatic int pcm512x_set_dividers(struct snd_soc_dai *dai,
8868c2ecf20Sopenharmony_ci				struct snd_pcm_hw_params *params)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	struct device *dev = dai->dev;
8898c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
8908c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
8918c2ecf20Sopenharmony_ci	unsigned long pllin_rate = 0;
8928c2ecf20Sopenharmony_ci	unsigned long pll_rate;
8938c2ecf20Sopenharmony_ci	unsigned long sck_rate;
8948c2ecf20Sopenharmony_ci	unsigned long mck_rate;
8958c2ecf20Sopenharmony_ci	unsigned long bclk_rate;
8968c2ecf20Sopenharmony_ci	unsigned long sample_rate;
8978c2ecf20Sopenharmony_ci	unsigned long osr_rate;
8988c2ecf20Sopenharmony_ci	unsigned long dacsrc_rate;
8998c2ecf20Sopenharmony_ci	int bclk_div;
9008c2ecf20Sopenharmony_ci	int lrclk_div;
9018c2ecf20Sopenharmony_ci	int dsp_div;
9028c2ecf20Sopenharmony_ci	int dac_div;
9038c2ecf20Sopenharmony_ci	unsigned long dac_rate;
9048c2ecf20Sopenharmony_ci	int ncp_div;
9058c2ecf20Sopenharmony_ci	int osr_div;
9068c2ecf20Sopenharmony_ci	int ret;
9078c2ecf20Sopenharmony_ci	int idac;
9088c2ecf20Sopenharmony_ci	int fssp;
9098c2ecf20Sopenharmony_ci	int gpio;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	if (pcm512x->bclk_ratio > 0) {
9128c2ecf20Sopenharmony_ci		lrclk_div = pcm512x->bclk_ratio;
9138c2ecf20Sopenharmony_ci	} else {
9148c2ecf20Sopenharmony_ci		lrclk_div = snd_soc_params_to_frame_size(params);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci		if (lrclk_div == 0) {
9178c2ecf20Sopenharmony_ci			dev_err(dev, "No LRCLK?\n");
9188c2ecf20Sopenharmony_ci			return -EINVAL;
9198c2ecf20Sopenharmony_ci		}
9208c2ecf20Sopenharmony_ci	}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	if (!pcm512x->pll_out) {
9238c2ecf20Sopenharmony_ci		sck_rate = clk_get_rate(pcm512x->sclk);
9248c2ecf20Sopenharmony_ci		bclk_rate = params_rate(params) * lrclk_div;
9258c2ecf20Sopenharmony_ci		bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci		mck_rate = sck_rate;
9288c2ecf20Sopenharmony_ci	} else {
9298c2ecf20Sopenharmony_ci		ret = snd_soc_params_to_bclk(params);
9308c2ecf20Sopenharmony_ci		if (ret < 0) {
9318c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to find suitable BCLK: %d\n", ret);
9328c2ecf20Sopenharmony_ci			return ret;
9338c2ecf20Sopenharmony_ci		}
9348c2ecf20Sopenharmony_ci		if (ret == 0) {
9358c2ecf20Sopenharmony_ci			dev_err(dev, "No BCLK?\n");
9368c2ecf20Sopenharmony_ci			return -EINVAL;
9378c2ecf20Sopenharmony_ci		}
9388c2ecf20Sopenharmony_ci		bclk_rate = ret;
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci		pllin_rate = clk_get_rate(pcm512x->sclk);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci		sck_rate = pcm512x_find_sck(dai, bclk_rate);
9438c2ecf20Sopenharmony_ci		if (!sck_rate)
9448c2ecf20Sopenharmony_ci			return -EINVAL;
9458c2ecf20Sopenharmony_ci		pll_rate = 4 * sck_rate;
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci		ret = pcm512x_find_pll_coeff(dai, pllin_rate, pll_rate);
9488c2ecf20Sopenharmony_ci		if (ret != 0)
9498c2ecf20Sopenharmony_ci			return ret;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap,
9528c2ecf20Sopenharmony_ci				   PCM512x_PLL_COEFF_0, pcm512x->pll_p - 1);
9538c2ecf20Sopenharmony_ci		if (ret != 0) {
9548c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to write PLL P: %d\n", ret);
9558c2ecf20Sopenharmony_ci			return ret;
9568c2ecf20Sopenharmony_ci		}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap,
9598c2ecf20Sopenharmony_ci				   PCM512x_PLL_COEFF_1, pcm512x->pll_j);
9608c2ecf20Sopenharmony_ci		if (ret != 0) {
9618c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to write PLL J: %d\n", ret);
9628c2ecf20Sopenharmony_ci			return ret;
9638c2ecf20Sopenharmony_ci		}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap,
9668c2ecf20Sopenharmony_ci				   PCM512x_PLL_COEFF_2, pcm512x->pll_d >> 8);
9678c2ecf20Sopenharmony_ci		if (ret != 0) {
9688c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to write PLL D msb: %d\n", ret);
9698c2ecf20Sopenharmony_ci			return ret;
9708c2ecf20Sopenharmony_ci		}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap,
9738c2ecf20Sopenharmony_ci				   PCM512x_PLL_COEFF_3, pcm512x->pll_d & 0xff);
9748c2ecf20Sopenharmony_ci		if (ret != 0) {
9758c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to write PLL D lsb: %d\n", ret);
9768c2ecf20Sopenharmony_ci			return ret;
9778c2ecf20Sopenharmony_ci		}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap,
9808c2ecf20Sopenharmony_ci				   PCM512x_PLL_COEFF_4, pcm512x->pll_r - 1);
9818c2ecf20Sopenharmony_ci		if (ret != 0) {
9828c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to write PLL R: %d\n", ret);
9838c2ecf20Sopenharmony_ci			return ret;
9848c2ecf20Sopenharmony_ci		}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci		mck_rate = pcm512x->real_pll;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci		bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
9898c2ecf20Sopenharmony_ci	}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	if (bclk_div > 128) {
9928c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to find BCLK divider\n");
9938c2ecf20Sopenharmony_ci		return -EINVAL;
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	/* the actual rate */
9978c2ecf20Sopenharmony_ci	sample_rate = sck_rate / bclk_div / lrclk_div;
9988c2ecf20Sopenharmony_ci	osr_rate = 16 * sample_rate;
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	/* run DSP no faster than 50 MHz */
10018c2ecf20Sopenharmony_ci	dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
10048c2ecf20Sopenharmony_ci	if (dac_rate) {
10058c2ecf20Sopenharmony_ci		/* the desired clock rate is "compatible" with the pll input
10068c2ecf20Sopenharmony_ci		 * clock, so use that clock as dac input instead of the pll
10078c2ecf20Sopenharmony_ci		 * output clock since the pll will introduce jitter and thus
10088c2ecf20Sopenharmony_ci		 * noise.
10098c2ecf20Sopenharmony_ci		 */
10108c2ecf20Sopenharmony_ci		dev_dbg(dev, "using pll input as dac input\n");
10118c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
10128c2ecf20Sopenharmony_ci					 PCM512x_SDAC, PCM512x_SDAC_GPIO);
10138c2ecf20Sopenharmony_ci		if (ret != 0) {
10148c2ecf20Sopenharmony_ci			dev_err(component->dev,
10158c2ecf20Sopenharmony_ci				"Failed to set gpio as dacref: %d\n", ret);
10168c2ecf20Sopenharmony_ci			return ret;
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci		gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
10208c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN,
10218c2ecf20Sopenharmony_ci					 PCM512x_GREF, gpio);
10228c2ecf20Sopenharmony_ci		if (ret != 0) {
10238c2ecf20Sopenharmony_ci			dev_err(component->dev,
10248c2ecf20Sopenharmony_ci				"Failed to set gpio %d as dacin: %d\n",
10258c2ecf20Sopenharmony_ci				pcm512x->pll_in, ret);
10268c2ecf20Sopenharmony_ci			return ret;
10278c2ecf20Sopenharmony_ci		}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci		dacsrc_rate = pllin_rate;
10308c2ecf20Sopenharmony_ci	} else {
10318c2ecf20Sopenharmony_ci		/* run DAC no faster than 6144000 Hz */
10328c2ecf20Sopenharmony_ci		unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
10338c2ecf20Sopenharmony_ci			/ osr_rate;
10348c2ecf20Sopenharmony_ci		unsigned long sck_mul = sck_rate / osr_rate;
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci		for (; dac_mul; dac_mul--) {
10378c2ecf20Sopenharmony_ci			if (!(sck_mul % dac_mul))
10388c2ecf20Sopenharmony_ci				break;
10398c2ecf20Sopenharmony_ci		}
10408c2ecf20Sopenharmony_ci		if (!dac_mul) {
10418c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to find DAC rate\n");
10428c2ecf20Sopenharmony_ci			return -EINVAL;
10438c2ecf20Sopenharmony_ci		}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci		dac_rate = dac_mul * osr_rate;
10468c2ecf20Sopenharmony_ci		dev_dbg(dev, "dac_rate %lu sample_rate %lu\n",
10478c2ecf20Sopenharmony_ci			dac_rate, sample_rate);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
10508c2ecf20Sopenharmony_ci					 PCM512x_SDAC, PCM512x_SDAC_SCK);
10518c2ecf20Sopenharmony_ci		if (ret != 0) {
10528c2ecf20Sopenharmony_ci			dev_err(component->dev,
10538c2ecf20Sopenharmony_ci				"Failed to set sck as dacref: %d\n", ret);
10548c2ecf20Sopenharmony_ci			return ret;
10558c2ecf20Sopenharmony_ci		}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci		dacsrc_rate = sck_rate;
10588c2ecf20Sopenharmony_ci	}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate);
10618c2ecf20Sopenharmony_ci	if (osr_div > 128) {
10628c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to find OSR divider\n");
10638c2ecf20Sopenharmony_ci		return -EINVAL;
10648c2ecf20Sopenharmony_ci	}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
10678c2ecf20Sopenharmony_ci	if (dac_div > 128) {
10688c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to find DAC divider\n");
10698c2ecf20Sopenharmony_ci		return -EINVAL;
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci	dac_rate = dacsrc_rate / dac_div;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	ncp_div = DIV_ROUND_CLOSEST(dac_rate,
10748c2ecf20Sopenharmony_ci				    pcm512x_ncp_target(pcm512x, dac_rate));
10758c2ecf20Sopenharmony_ci	if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
10768c2ecf20Sopenharmony_ci		/* run NCP no faster than 2048000 Hz, but why? */
10778c2ecf20Sopenharmony_ci		ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
10788c2ecf20Sopenharmony_ci		if (ncp_div > 128) {
10798c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to find NCP divider\n");
10808c2ecf20Sopenharmony_ci			return -EINVAL;
10818c2ecf20Sopenharmony_ci		}
10828c2ecf20Sopenharmony_ci	}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	idac = mck_rate / (dsp_div * sample_rate);
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1);
10878c2ecf20Sopenharmony_ci	if (ret != 0) {
10888c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write DSP divider: %d\n", ret);
10898c2ecf20Sopenharmony_ci		return ret;
10908c2ecf20Sopenharmony_ci	}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1);
10938c2ecf20Sopenharmony_ci	if (ret != 0) {
10948c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write DAC divider: %d\n", ret);
10958c2ecf20Sopenharmony_ci		return ret;
10968c2ecf20Sopenharmony_ci	}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1);
10998c2ecf20Sopenharmony_ci	if (ret != 0) {
11008c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write NCP divider: %d\n", ret);
11018c2ecf20Sopenharmony_ci		return ret;
11028c2ecf20Sopenharmony_ci	}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1);
11058c2ecf20Sopenharmony_ci	if (ret != 0) {
11068c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write OSR divider: %d\n", ret);
11078c2ecf20Sopenharmony_ci		return ret;
11088c2ecf20Sopenharmony_ci	}
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap,
11118c2ecf20Sopenharmony_ci			   PCM512x_MASTER_CLKDIV_1, bclk_div - 1);
11128c2ecf20Sopenharmony_ci	if (ret != 0) {
11138c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write BCLK divider: %d\n", ret);
11148c2ecf20Sopenharmony_ci		return ret;
11158c2ecf20Sopenharmony_ci	}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap,
11188c2ecf20Sopenharmony_ci			   PCM512x_MASTER_CLKDIV_2, lrclk_div - 1);
11198c2ecf20Sopenharmony_ci	if (ret != 0) {
11208c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write LRCLK divider: %d\n", ret);
11218c2ecf20Sopenharmony_ci		return ret;
11228c2ecf20Sopenharmony_ci	}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8);
11258c2ecf20Sopenharmony_ci	if (ret != 0) {
11268c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret);
11278c2ecf20Sopenharmony_ci		return ret;
11288c2ecf20Sopenharmony_ci	}
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff);
11318c2ecf20Sopenharmony_ci	if (ret != 0) {
11328c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret);
11338c2ecf20Sopenharmony_ci		return ret;
11348c2ecf20Sopenharmony_ci	}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
11378c2ecf20Sopenharmony_ci		fssp = PCM512x_FSSP_48KHZ;
11388c2ecf20Sopenharmony_ci	else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
11398c2ecf20Sopenharmony_ci		fssp = PCM512x_FSSP_96KHZ;
11408c2ecf20Sopenharmony_ci	else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
11418c2ecf20Sopenharmony_ci		fssp = PCM512x_FSSP_192KHZ;
11428c2ecf20Sopenharmony_ci	else
11438c2ecf20Sopenharmony_ci		fssp = PCM512x_FSSP_384KHZ;
11448c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE,
11458c2ecf20Sopenharmony_ci				 PCM512x_FSSP, fssp);
11468c2ecf20Sopenharmony_ci	if (ret != 0) {
11478c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set fs speed: %d\n", ret);
11488c2ecf20Sopenharmony_ci		return ret;
11498c2ecf20Sopenharmony_ci	}
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "DSP divider %d\n", dsp_div);
11528c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "DAC divider %d\n", dac_div);
11538c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "NCP divider %d\n", ncp_div);
11548c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "OSR divider %d\n", osr_div);
11558c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "BCK divider %d\n", bclk_div);
11568c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "LRCK divider %d\n", lrclk_div);
11578c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "IDAC %d\n", idac);
11588c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "1<<FSSP %d\n", 1 << fssp);
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	return 0;
11618c2ecf20Sopenharmony_ci}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_cistatic int pcm512x_hw_params(struct snd_pcm_substream *substream,
11648c2ecf20Sopenharmony_ci			     struct snd_pcm_hw_params *params,
11658c2ecf20Sopenharmony_ci			     struct snd_soc_dai *dai)
11668c2ecf20Sopenharmony_ci{
11678c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
11688c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
11698c2ecf20Sopenharmony_ci	int alen;
11708c2ecf20Sopenharmony_ci	int gpio;
11718c2ecf20Sopenharmony_ci	int clock_output;
11728c2ecf20Sopenharmony_ci	int master_mode;
11738c2ecf20Sopenharmony_ci	int ret;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "hw_params %u Hz, %u channels\n",
11768c2ecf20Sopenharmony_ci		params_rate(params),
11778c2ecf20Sopenharmony_ci		params_channels(params));
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	switch (params_width(params)) {
11808c2ecf20Sopenharmony_ci	case 16:
11818c2ecf20Sopenharmony_ci		alen = PCM512x_ALEN_16;
11828c2ecf20Sopenharmony_ci		break;
11838c2ecf20Sopenharmony_ci	case 20:
11848c2ecf20Sopenharmony_ci		alen = PCM512x_ALEN_20;
11858c2ecf20Sopenharmony_ci		break;
11868c2ecf20Sopenharmony_ci	case 24:
11878c2ecf20Sopenharmony_ci		alen = PCM512x_ALEN_24;
11888c2ecf20Sopenharmony_ci		break;
11898c2ecf20Sopenharmony_ci	case 32:
11908c2ecf20Sopenharmony_ci		alen = PCM512x_ALEN_32;
11918c2ecf20Sopenharmony_ci		break;
11928c2ecf20Sopenharmony_ci	default:
11938c2ecf20Sopenharmony_ci		dev_err(component->dev, "Bad frame size: %d\n",
11948c2ecf20Sopenharmony_ci			params_width(params));
11958c2ecf20Sopenharmony_ci		return -EINVAL;
11968c2ecf20Sopenharmony_ci	}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
11998c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBS_CFS:
12008c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap,
12018c2ecf20Sopenharmony_ci					 PCM512x_BCLK_LRCLK_CFG,
12028c2ecf20Sopenharmony_ci					 PCM512x_BCKP
12038c2ecf20Sopenharmony_ci					 | PCM512x_BCKO | PCM512x_LRKO,
12048c2ecf20Sopenharmony_ci					 0);
12058c2ecf20Sopenharmony_ci		if (ret != 0) {
12068c2ecf20Sopenharmony_ci			dev_err(component->dev,
12078c2ecf20Sopenharmony_ci				"Failed to enable slave mode: %d\n", ret);
12088c2ecf20Sopenharmony_ci			return ret;
12098c2ecf20Sopenharmony_ci		}
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
12128c2ecf20Sopenharmony_ci					 PCM512x_DCAS, 0);
12138c2ecf20Sopenharmony_ci		if (ret != 0) {
12148c2ecf20Sopenharmony_ci			dev_err(component->dev,
12158c2ecf20Sopenharmony_ci				"Failed to enable clock divider autoset: %d\n",
12168c2ecf20Sopenharmony_ci				ret);
12178c2ecf20Sopenharmony_ci			return ret;
12188c2ecf20Sopenharmony_ci		}
12198c2ecf20Sopenharmony_ci		return 0;
12208c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
12218c2ecf20Sopenharmony_ci		clock_output = PCM512x_BCKO | PCM512x_LRKO;
12228c2ecf20Sopenharmony_ci		master_mode = PCM512x_RLRK | PCM512x_RBCK;
12238c2ecf20Sopenharmony_ci		break;
12248c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFS:
12258c2ecf20Sopenharmony_ci		clock_output = PCM512x_BCKO;
12268c2ecf20Sopenharmony_ci		master_mode = PCM512x_RBCK;
12278c2ecf20Sopenharmony_ci		break;
12288c2ecf20Sopenharmony_ci	default:
12298c2ecf20Sopenharmony_ci		return -EINVAL;
12308c2ecf20Sopenharmony_ci	}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
12338c2ecf20Sopenharmony_ci				 PCM512x_ALEN, alen);
12348c2ecf20Sopenharmony_ci	if (ret != 0) {
12358c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set frame size: %d\n", ret);
12368c2ecf20Sopenharmony_ci		return ret;
12378c2ecf20Sopenharmony_ci	}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	if (pcm512x->pll_out) {
12408c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11);
12418c2ecf20Sopenharmony_ci		if (ret != 0) {
12428c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to set FLEX_A: %d\n", ret);
12438c2ecf20Sopenharmony_ci			return ret;
12448c2ecf20Sopenharmony_ci		}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci		ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff);
12478c2ecf20Sopenharmony_ci		if (ret != 0) {
12488c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to set FLEX_B: %d\n", ret);
12498c2ecf20Sopenharmony_ci			return ret;
12508c2ecf20Sopenharmony_ci		}
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
12538c2ecf20Sopenharmony_ci					 PCM512x_IDFS | PCM512x_IDBK
12548c2ecf20Sopenharmony_ci					 | PCM512x_IDSK | PCM512x_IDCH
12558c2ecf20Sopenharmony_ci					 | PCM512x_IDCM | PCM512x_DCAS
12568c2ecf20Sopenharmony_ci					 | PCM512x_IPLK,
12578c2ecf20Sopenharmony_ci					 PCM512x_IDFS | PCM512x_IDBK
12588c2ecf20Sopenharmony_ci					 | PCM512x_IDSK | PCM512x_IDCH
12598c2ecf20Sopenharmony_ci					 | PCM512x_DCAS);
12608c2ecf20Sopenharmony_ci		if (ret != 0) {
12618c2ecf20Sopenharmony_ci			dev_err(component->dev,
12628c2ecf20Sopenharmony_ci				"Failed to ignore auto-clock failures: %d\n",
12638c2ecf20Sopenharmony_ci				ret);
12648c2ecf20Sopenharmony_ci			return ret;
12658c2ecf20Sopenharmony_ci		}
12668c2ecf20Sopenharmony_ci	} else {
12678c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT,
12688c2ecf20Sopenharmony_ci					 PCM512x_IDFS | PCM512x_IDBK
12698c2ecf20Sopenharmony_ci					 | PCM512x_IDSK | PCM512x_IDCH
12708c2ecf20Sopenharmony_ci					 | PCM512x_IDCM | PCM512x_DCAS
12718c2ecf20Sopenharmony_ci					 | PCM512x_IPLK,
12728c2ecf20Sopenharmony_ci					 PCM512x_IDFS | PCM512x_IDBK
12738c2ecf20Sopenharmony_ci					 | PCM512x_IDSK | PCM512x_IDCH
12748c2ecf20Sopenharmony_ci					 | PCM512x_DCAS | PCM512x_IPLK);
12758c2ecf20Sopenharmony_ci		if (ret != 0) {
12768c2ecf20Sopenharmony_ci			dev_err(component->dev,
12778c2ecf20Sopenharmony_ci				"Failed to ignore auto-clock failures: %d\n",
12788c2ecf20Sopenharmony_ci				ret);
12798c2ecf20Sopenharmony_ci			return ret;
12808c2ecf20Sopenharmony_ci		}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
12838c2ecf20Sopenharmony_ci					 PCM512x_PLLE, 0);
12848c2ecf20Sopenharmony_ci		if (ret != 0) {
12858c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to disable pll: %d\n", ret);
12868c2ecf20Sopenharmony_ci			return ret;
12878c2ecf20Sopenharmony_ci		}
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	ret = pcm512x_set_dividers(dai, params);
12918c2ecf20Sopenharmony_ci	if (ret != 0)
12928c2ecf20Sopenharmony_ci		return ret;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	if (pcm512x->pll_out) {
12958c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF,
12968c2ecf20Sopenharmony_ci					 PCM512x_SREF, PCM512x_SREF_GPIO);
12978c2ecf20Sopenharmony_ci		if (ret != 0) {
12988c2ecf20Sopenharmony_ci			dev_err(component->dev,
12998c2ecf20Sopenharmony_ci				"Failed to set gpio as pllref: %d\n", ret);
13008c2ecf20Sopenharmony_ci			return ret;
13018c2ecf20Sopenharmony_ci		}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci		gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
13048c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN,
13058c2ecf20Sopenharmony_ci					 PCM512x_GREF, gpio);
13068c2ecf20Sopenharmony_ci		if (ret != 0) {
13078c2ecf20Sopenharmony_ci			dev_err(component->dev,
13088c2ecf20Sopenharmony_ci				"Failed to set gpio %d as pllin: %d\n",
13098c2ecf20Sopenharmony_ci				pcm512x->pll_in, ret);
13108c2ecf20Sopenharmony_ci			return ret;
13118c2ecf20Sopenharmony_ci		}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN,
13148c2ecf20Sopenharmony_ci					 PCM512x_PLLE, PCM512x_PLLE);
13158c2ecf20Sopenharmony_ci		if (ret != 0) {
13168c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to enable pll: %d\n", ret);
13178c2ecf20Sopenharmony_ci			return ret;
13188c2ecf20Sopenharmony_ci		}
13198c2ecf20Sopenharmony_ci	}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG,
13228c2ecf20Sopenharmony_ci				 PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO,
13238c2ecf20Sopenharmony_ci				 clock_output);
13248c2ecf20Sopenharmony_ci	if (ret != 0) {
13258c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to enable clock output: %d\n", ret);
13268c2ecf20Sopenharmony_ci		return ret;
13278c2ecf20Sopenharmony_ci	}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE,
13308c2ecf20Sopenharmony_ci				 PCM512x_RLRK | PCM512x_RBCK,
13318c2ecf20Sopenharmony_ci				 master_mode);
13328c2ecf20Sopenharmony_ci	if (ret != 0) {
13338c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to enable master mode: %d\n", ret);
13348c2ecf20Sopenharmony_ci		return ret;
13358c2ecf20Sopenharmony_ci	}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	if (pcm512x->pll_out) {
13388c2ecf20Sopenharmony_ci		gpio = PCM512x_G1OE << (pcm512x->pll_out - 1);
13398c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN,
13408c2ecf20Sopenharmony_ci					 gpio, gpio);
13418c2ecf20Sopenharmony_ci		if (ret != 0) {
13428c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to enable gpio %d: %d\n",
13438c2ecf20Sopenharmony_ci				pcm512x->pll_out, ret);
13448c2ecf20Sopenharmony_ci			return ret;
13458c2ecf20Sopenharmony_ci		}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci		gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1;
13488c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, gpio,
13498c2ecf20Sopenharmony_ci					 PCM512x_GxSL, PCM512x_GxSL_PLLCK);
13508c2ecf20Sopenharmony_ci		if (ret != 0) {
13518c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to output pll on %d: %d\n",
13528c2ecf20Sopenharmony_ci				ret, pcm512x->pll_out);
13538c2ecf20Sopenharmony_ci			return ret;
13548c2ecf20Sopenharmony_ci		}
13558c2ecf20Sopenharmony_ci	}
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
13588c2ecf20Sopenharmony_ci				 PCM512x_RQSY, PCM512x_RQSY_HALT);
13598c2ecf20Sopenharmony_ci	if (ret != 0) {
13608c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to halt clocks: %d\n", ret);
13618c2ecf20Sopenharmony_ci		return ret;
13628c2ecf20Sopenharmony_ci	}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE,
13658c2ecf20Sopenharmony_ci				 PCM512x_RQSY, PCM512x_RQSY_RESUME);
13668c2ecf20Sopenharmony_ci	if (ret != 0) {
13678c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to resume clocks: %d\n", ret);
13688c2ecf20Sopenharmony_ci		return ret;
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	return 0;
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_cistatic int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
13758c2ecf20Sopenharmony_ci{
13768c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
13778c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	pcm512x->fmt = fmt;
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	return 0;
13828c2ecf20Sopenharmony_ci}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_cistatic int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
13858c2ecf20Sopenharmony_ci{
13868c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
13878c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	if (ratio > 256)
13908c2ecf20Sopenharmony_ci		return -EINVAL;
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	pcm512x->bclk_ratio = ratio;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	return 0;
13958c2ecf20Sopenharmony_ci}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_cistatic int pcm512x_mute(struct snd_soc_dai *dai, int mute, int direction)
13988c2ecf20Sopenharmony_ci{
13998c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
14008c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
14018c2ecf20Sopenharmony_ci	int ret;
14028c2ecf20Sopenharmony_ci	unsigned int mute_det;
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	mutex_lock(&pcm512x->mutex);
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	if (mute) {
14078c2ecf20Sopenharmony_ci		pcm512x->mute |= 0x1;
14088c2ecf20Sopenharmony_ci		ret = regmap_update_bits(pcm512x->regmap, PCM512x_MUTE,
14098c2ecf20Sopenharmony_ci					 PCM512x_RQML | PCM512x_RQMR,
14108c2ecf20Sopenharmony_ci					 PCM512x_RQML | PCM512x_RQMR);
14118c2ecf20Sopenharmony_ci		if (ret != 0) {
14128c2ecf20Sopenharmony_ci			dev_err(component->dev,
14138c2ecf20Sopenharmony_ci				"Failed to set digital mute: %d\n", ret);
14148c2ecf20Sopenharmony_ci			goto unlock;
14158c2ecf20Sopenharmony_ci		}
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci		regmap_read_poll_timeout(pcm512x->regmap,
14188c2ecf20Sopenharmony_ci					 PCM512x_ANALOG_MUTE_DET,
14198c2ecf20Sopenharmony_ci					 mute_det, (mute_det & 0x3) == 0,
14208c2ecf20Sopenharmony_ci					 200, 10000);
14218c2ecf20Sopenharmony_ci	} else {
14228c2ecf20Sopenharmony_ci		pcm512x->mute &= ~0x1;
14238c2ecf20Sopenharmony_ci		ret = pcm512x_update_mute(pcm512x);
14248c2ecf20Sopenharmony_ci		if (ret != 0) {
14258c2ecf20Sopenharmony_ci			dev_err(component->dev,
14268c2ecf20Sopenharmony_ci				"Failed to update digital mute: %d\n", ret);
14278c2ecf20Sopenharmony_ci			goto unlock;
14288c2ecf20Sopenharmony_ci		}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci		regmap_read_poll_timeout(pcm512x->regmap,
14318c2ecf20Sopenharmony_ci					 PCM512x_ANALOG_MUTE_DET,
14328c2ecf20Sopenharmony_ci					 mute_det,
14338c2ecf20Sopenharmony_ci					 (mute_det & 0x3)
14348c2ecf20Sopenharmony_ci					 == ((~pcm512x->mute >> 1) & 0x3),
14358c2ecf20Sopenharmony_ci					 200, 10000);
14368c2ecf20Sopenharmony_ci	}
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ciunlock:
14398c2ecf20Sopenharmony_ci	mutex_unlock(&pcm512x->mutex);
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	return ret;
14428c2ecf20Sopenharmony_ci}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops pcm512x_dai_ops = {
14458c2ecf20Sopenharmony_ci	.startup = pcm512x_dai_startup,
14468c2ecf20Sopenharmony_ci	.hw_params = pcm512x_hw_params,
14478c2ecf20Sopenharmony_ci	.set_fmt = pcm512x_set_fmt,
14488c2ecf20Sopenharmony_ci	.mute_stream = pcm512x_mute,
14498c2ecf20Sopenharmony_ci	.set_bclk_ratio = pcm512x_set_bclk_ratio,
14508c2ecf20Sopenharmony_ci	.no_capture_mute = 1,
14518c2ecf20Sopenharmony_ci};
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver pcm512x_dai = {
14548c2ecf20Sopenharmony_ci	.name = "pcm512x-hifi",
14558c2ecf20Sopenharmony_ci	.playback = {
14568c2ecf20Sopenharmony_ci		.stream_name = "Playback",
14578c2ecf20Sopenharmony_ci		.channels_min = 2,
14588c2ecf20Sopenharmony_ci		.channels_max = 2,
14598c2ecf20Sopenharmony_ci		.rates = SNDRV_PCM_RATE_CONTINUOUS,
14608c2ecf20Sopenharmony_ci		.rate_min = 8000,
14618c2ecf20Sopenharmony_ci		.rate_max = 384000,
14628c2ecf20Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE |
14638c2ecf20Sopenharmony_ci			   SNDRV_PCM_FMTBIT_S24_LE |
14648c2ecf20Sopenharmony_ci			   SNDRV_PCM_FMTBIT_S32_LE
14658c2ecf20Sopenharmony_ci	},
14668c2ecf20Sopenharmony_ci	.ops = &pcm512x_dai_ops,
14678c2ecf20Sopenharmony_ci};
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver pcm512x_component_driver = {
14708c2ecf20Sopenharmony_ci	.set_bias_level		= pcm512x_set_bias_level,
14718c2ecf20Sopenharmony_ci	.controls		= pcm512x_controls,
14728c2ecf20Sopenharmony_ci	.num_controls		= ARRAY_SIZE(pcm512x_controls),
14738c2ecf20Sopenharmony_ci	.dapm_widgets		= pcm512x_dapm_widgets,
14748c2ecf20Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(pcm512x_dapm_widgets),
14758c2ecf20Sopenharmony_ci	.dapm_routes		= pcm512x_dapm_routes,
14768c2ecf20Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(pcm512x_dapm_routes),
14778c2ecf20Sopenharmony_ci	.use_pmdown_time	= 1,
14788c2ecf20Sopenharmony_ci	.endianness		= 1,
14798c2ecf20Sopenharmony_ci	.non_legacy_dai_naming	= 1,
14808c2ecf20Sopenharmony_ci};
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_cistatic const struct regmap_range_cfg pcm512x_range = {
14838c2ecf20Sopenharmony_ci	.name = "Pages", .range_min = PCM512x_VIRT_BASE,
14848c2ecf20Sopenharmony_ci	.range_max = PCM512x_MAX_REGISTER,
14858c2ecf20Sopenharmony_ci	.selector_reg = PCM512x_PAGE,
14868c2ecf20Sopenharmony_ci	.selector_mask = 0xff,
14878c2ecf20Sopenharmony_ci	.window_start = 0, .window_len = 0x100,
14888c2ecf20Sopenharmony_ci};
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ciconst struct regmap_config pcm512x_regmap = {
14918c2ecf20Sopenharmony_ci	.reg_bits = 8,
14928c2ecf20Sopenharmony_ci	.val_bits = 8,
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	.readable_reg = pcm512x_readable,
14958c2ecf20Sopenharmony_ci	.volatile_reg = pcm512x_volatile,
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	.ranges = &pcm512x_range,
14988c2ecf20Sopenharmony_ci	.num_ranges = 1,
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	.max_register = PCM512x_MAX_REGISTER,
15018c2ecf20Sopenharmony_ci	.reg_defaults = pcm512x_reg_defaults,
15028c2ecf20Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
15038c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
15048c2ecf20Sopenharmony_ci};
15058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pcm512x_regmap);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ciint pcm512x_probe(struct device *dev, struct regmap *regmap)
15088c2ecf20Sopenharmony_ci{
15098c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x;
15108c2ecf20Sopenharmony_ci	int i, ret;
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
15138c2ecf20Sopenharmony_ci	if (!pcm512x)
15148c2ecf20Sopenharmony_ci		return -ENOMEM;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	mutex_init(&pcm512x->mutex);
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, pcm512x);
15198c2ecf20Sopenharmony_ci	pcm512x->regmap = regmap;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
15228c2ecf20Sopenharmony_ci		pcm512x->supplies[i].supply = pcm512x_supply_names[i];
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
15258c2ecf20Sopenharmony_ci				      pcm512x->supplies);
15268c2ecf20Sopenharmony_ci	if (ret != 0) {
15278c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to get supplies: %d\n", ret);
15288c2ecf20Sopenharmony_ci		return ret;
15298c2ecf20Sopenharmony_ci	}
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
15328c2ecf20Sopenharmony_ci	pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
15338c2ecf20Sopenharmony_ci	pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
15368c2ecf20Sopenharmony_ci		ret = devm_regulator_register_notifier(
15378c2ecf20Sopenharmony_ci						pcm512x->supplies[i].consumer,
15388c2ecf20Sopenharmony_ci						&pcm512x->supply_nb[i]);
15398c2ecf20Sopenharmony_ci		if (ret != 0) {
15408c2ecf20Sopenharmony_ci			dev_err(dev,
15418c2ecf20Sopenharmony_ci				"Failed to register regulator notifier: %d\n",
15428c2ecf20Sopenharmony_ci				ret);
15438c2ecf20Sopenharmony_ci		}
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
15478c2ecf20Sopenharmony_ci				    pcm512x->supplies);
15488c2ecf20Sopenharmony_ci	if (ret != 0) {
15498c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable supplies: %d\n", ret);
15508c2ecf20Sopenharmony_ci		return ret;
15518c2ecf20Sopenharmony_ci	}
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	/* Reset the device, verifying I/O in the process for I2C */
15548c2ecf20Sopenharmony_ci	ret = regmap_write(regmap, PCM512x_RESET,
15558c2ecf20Sopenharmony_ci			   PCM512x_RSTM | PCM512x_RSTR);
15568c2ecf20Sopenharmony_ci	if (ret != 0) {
15578c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to reset device: %d\n", ret);
15588c2ecf20Sopenharmony_ci		goto err;
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	ret = regmap_write(regmap, PCM512x_RESET, 0);
15628c2ecf20Sopenharmony_ci	if (ret != 0) {
15638c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to reset device: %d\n", ret);
15648c2ecf20Sopenharmony_ci		goto err;
15658c2ecf20Sopenharmony_ci	}
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	pcm512x->sclk = devm_clk_get(dev, NULL);
15688c2ecf20Sopenharmony_ci	if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) {
15698c2ecf20Sopenharmony_ci		ret = -EPROBE_DEFER;
15708c2ecf20Sopenharmony_ci		goto err;
15718c2ecf20Sopenharmony_ci	}
15728c2ecf20Sopenharmony_ci	if (!IS_ERR(pcm512x->sclk)) {
15738c2ecf20Sopenharmony_ci		ret = clk_prepare_enable(pcm512x->sclk);
15748c2ecf20Sopenharmony_ci		if (ret != 0) {
15758c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to enable SCLK: %d\n", ret);
15768c2ecf20Sopenharmony_ci			goto err;
15778c2ecf20Sopenharmony_ci		}
15788c2ecf20Sopenharmony_ci	}
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci	/* Default to standby mode */
15818c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
15828c2ecf20Sopenharmony_ci				 PCM512x_RQST, PCM512x_RQST);
15838c2ecf20Sopenharmony_ci	if (ret != 0) {
15848c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request standby: %d\n",
15858c2ecf20Sopenharmony_ci			ret);
15868c2ecf20Sopenharmony_ci		goto err_clk;
15878c2ecf20Sopenharmony_ci	}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	pm_runtime_set_active(dev);
15908c2ecf20Sopenharmony_ci	pm_runtime_enable(dev);
15918c2ecf20Sopenharmony_ci	pm_runtime_idle(dev);
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
15948c2ecf20Sopenharmony_ci	if (dev->of_node) {
15958c2ecf20Sopenharmony_ci		const struct device_node *np = dev->of_node;
15968c2ecf20Sopenharmony_ci		u32 val;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci		if (of_property_read_u32(np, "pll-in", &val) >= 0) {
15998c2ecf20Sopenharmony_ci			if (val > 6) {
16008c2ecf20Sopenharmony_ci				dev_err(dev, "Invalid pll-in\n");
16018c2ecf20Sopenharmony_ci				ret = -EINVAL;
16028c2ecf20Sopenharmony_ci				goto err_pm;
16038c2ecf20Sopenharmony_ci			}
16048c2ecf20Sopenharmony_ci			pcm512x->pll_in = val;
16058c2ecf20Sopenharmony_ci		}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci		if (of_property_read_u32(np, "pll-out", &val) >= 0) {
16088c2ecf20Sopenharmony_ci			if (val > 6) {
16098c2ecf20Sopenharmony_ci				dev_err(dev, "Invalid pll-out\n");
16108c2ecf20Sopenharmony_ci				ret = -EINVAL;
16118c2ecf20Sopenharmony_ci				goto err_pm;
16128c2ecf20Sopenharmony_ci			}
16138c2ecf20Sopenharmony_ci			pcm512x->pll_out = val;
16148c2ecf20Sopenharmony_ci		}
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci		if (!pcm512x->pll_in != !pcm512x->pll_out) {
16178c2ecf20Sopenharmony_ci			dev_err(dev,
16188c2ecf20Sopenharmony_ci				"Error: both pll-in and pll-out, or none\n");
16198c2ecf20Sopenharmony_ci			ret = -EINVAL;
16208c2ecf20Sopenharmony_ci			goto err_pm;
16218c2ecf20Sopenharmony_ci		}
16228c2ecf20Sopenharmony_ci		if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) {
16238c2ecf20Sopenharmony_ci			dev_err(dev, "Error: pll-in == pll-out\n");
16248c2ecf20Sopenharmony_ci			ret = -EINVAL;
16258c2ecf20Sopenharmony_ci			goto err_pm;
16268c2ecf20Sopenharmony_ci		}
16278c2ecf20Sopenharmony_ci	}
16288c2ecf20Sopenharmony_ci#endif
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	ret = devm_snd_soc_register_component(dev, &pcm512x_component_driver,
16318c2ecf20Sopenharmony_ci				    &pcm512x_dai, 1);
16328c2ecf20Sopenharmony_ci	if (ret != 0) {
16338c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to register CODEC: %d\n", ret);
16348c2ecf20Sopenharmony_ci		goto err_pm;
16358c2ecf20Sopenharmony_ci	}
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	return 0;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_cierr_pm:
16408c2ecf20Sopenharmony_ci	pm_runtime_disable(dev);
16418c2ecf20Sopenharmony_cierr_clk:
16428c2ecf20Sopenharmony_ci	if (!IS_ERR(pcm512x->sclk))
16438c2ecf20Sopenharmony_ci		clk_disable_unprepare(pcm512x->sclk);
16448c2ecf20Sopenharmony_cierr:
16458c2ecf20Sopenharmony_ci	regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
16468c2ecf20Sopenharmony_ci				     pcm512x->supplies);
16478c2ecf20Sopenharmony_ci	return ret;
16488c2ecf20Sopenharmony_ci}
16498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pcm512x_probe);
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_civoid pcm512x_remove(struct device *dev)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	pm_runtime_disable(dev);
16568c2ecf20Sopenharmony_ci	if (!IS_ERR(pcm512x->sclk))
16578c2ecf20Sopenharmony_ci		clk_disable_unprepare(pcm512x->sclk);
16588c2ecf20Sopenharmony_ci	regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
16598c2ecf20Sopenharmony_ci			       pcm512x->supplies);
16608c2ecf20Sopenharmony_ci}
16618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pcm512x_remove);
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
16648c2ecf20Sopenharmony_cistatic int pcm512x_suspend(struct device *dev)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
16678c2ecf20Sopenharmony_ci	int ret;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
16708c2ecf20Sopenharmony_ci				 PCM512x_RQPD, PCM512x_RQPD);
16718c2ecf20Sopenharmony_ci	if (ret != 0) {
16728c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request power down: %d\n", ret);
16738c2ecf20Sopenharmony_ci		return ret;
16748c2ecf20Sopenharmony_ci	}
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
16778c2ecf20Sopenharmony_ci				     pcm512x->supplies);
16788c2ecf20Sopenharmony_ci	if (ret != 0) {
16798c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to disable supplies: %d\n", ret);
16808c2ecf20Sopenharmony_ci		return ret;
16818c2ecf20Sopenharmony_ci	}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	if (!IS_ERR(pcm512x->sclk))
16848c2ecf20Sopenharmony_ci		clk_disable_unprepare(pcm512x->sclk);
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	return 0;
16878c2ecf20Sopenharmony_ci}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_cistatic int pcm512x_resume(struct device *dev)
16908c2ecf20Sopenharmony_ci{
16918c2ecf20Sopenharmony_ci	struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
16928c2ecf20Sopenharmony_ci	int ret;
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	if (!IS_ERR(pcm512x->sclk)) {
16958c2ecf20Sopenharmony_ci		ret = clk_prepare_enable(pcm512x->sclk);
16968c2ecf20Sopenharmony_ci		if (ret != 0) {
16978c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to enable SCLK: %d\n", ret);
16988c2ecf20Sopenharmony_ci			return ret;
16998c2ecf20Sopenharmony_ci		}
17008c2ecf20Sopenharmony_ci	}
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
17038c2ecf20Sopenharmony_ci				    pcm512x->supplies);
17048c2ecf20Sopenharmony_ci	if (ret != 0) {
17058c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable supplies: %d\n", ret);
17068c2ecf20Sopenharmony_ci		return ret;
17078c2ecf20Sopenharmony_ci	}
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	regcache_cache_only(pcm512x->regmap, false);
17108c2ecf20Sopenharmony_ci	ret = regcache_sync(pcm512x->regmap);
17118c2ecf20Sopenharmony_ci	if (ret != 0) {
17128c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to sync cache: %d\n", ret);
17138c2ecf20Sopenharmony_ci		return ret;
17148c2ecf20Sopenharmony_ci	}
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
17178c2ecf20Sopenharmony_ci				 PCM512x_RQPD, 0);
17188c2ecf20Sopenharmony_ci	if (ret != 0) {
17198c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to remove power down: %d\n", ret);
17208c2ecf20Sopenharmony_ci		return ret;
17218c2ecf20Sopenharmony_ci	}
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	return 0;
17248c2ecf20Sopenharmony_ci}
17258c2ecf20Sopenharmony_ci#endif
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ciconst struct dev_pm_ops pcm512x_pm_ops = {
17288c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
17298c2ecf20Sopenharmony_ci};
17308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pcm512x_pm_ops);
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC PCM512x codec driver");
17338c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mark Brown <broonie@kernel.org>");
17348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1735