18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * cs35l35.c -- CS35L35 ALSA SoC audio driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2017 Cirrus Logic, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Brian Austin <brian.austin@cirrus.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
128c2ecf20Sopenharmony_ci#include <linux/version.h>
138c2ecf20Sopenharmony_ci#include <linux/kernel.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/delay.h>
168c2ecf20Sopenharmony_ci#include <linux/i2c.h>
178c2ecf20Sopenharmony_ci#include <linux/slab.h>
188c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
198c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
208c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
218c2ecf20Sopenharmony_ci#include <linux/of_device.h>
228c2ecf20Sopenharmony_ci#include <linux/of_gpio.h>
238c2ecf20Sopenharmony_ci#include <linux/regmap.h>
248c2ecf20Sopenharmony_ci#include <sound/core.h>
258c2ecf20Sopenharmony_ci#include <sound/pcm.h>
268c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
278c2ecf20Sopenharmony_ci#include <sound/soc.h>
288c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
298c2ecf20Sopenharmony_ci#include <linux/gpio.h>
308c2ecf20Sopenharmony_ci#include <sound/initval.h>
318c2ecf20Sopenharmony_ci#include <sound/tlv.h>
328c2ecf20Sopenharmony_ci#include <sound/cs35l35.h>
338c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
348c2ecf20Sopenharmony_ci#include <linux/completion.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include "cs35l35.h"
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Some fields take zero as a valid value so use a high bit flag that won't
408c2ecf20Sopenharmony_ci * get written to the device to mark those.
418c2ecf20Sopenharmony_ci */
428c2ecf20Sopenharmony_ci#define CS35L35_VALID_PDATA 0x80000000
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic const struct reg_default cs35l35_reg[] = {
458c2ecf20Sopenharmony_ci	{CS35L35_PWRCTL1,		0x01},
468c2ecf20Sopenharmony_ci	{CS35L35_PWRCTL2,		0x11},
478c2ecf20Sopenharmony_ci	{CS35L35_PWRCTL3,		0x00},
488c2ecf20Sopenharmony_ci	{CS35L35_CLK_CTL1,		0x04},
498c2ecf20Sopenharmony_ci	{CS35L35_CLK_CTL2,		0x12},
508c2ecf20Sopenharmony_ci	{CS35L35_CLK_CTL3,		0xCF},
518c2ecf20Sopenharmony_ci	{CS35L35_SP_FMT_CTL1,		0x20},
528c2ecf20Sopenharmony_ci	{CS35L35_SP_FMT_CTL2,		0x00},
538c2ecf20Sopenharmony_ci	{CS35L35_SP_FMT_CTL3,		0x02},
548c2ecf20Sopenharmony_ci	{CS35L35_MAG_COMP_CTL,		0x00},
558c2ecf20Sopenharmony_ci	{CS35L35_AMP_INP_DRV_CTL,	0x01},
568c2ecf20Sopenharmony_ci	{CS35L35_AMP_DIG_VOL_CTL,	0x12},
578c2ecf20Sopenharmony_ci	{CS35L35_AMP_DIG_VOL,		0x00},
588c2ecf20Sopenharmony_ci	{CS35L35_ADV_DIG_VOL,		0x00},
598c2ecf20Sopenharmony_ci	{CS35L35_PROTECT_CTL,		0x06},
608c2ecf20Sopenharmony_ci	{CS35L35_AMP_GAIN_AUD_CTL,	0x13},
618c2ecf20Sopenharmony_ci	{CS35L35_AMP_GAIN_PDM_CTL,	0x00},
628c2ecf20Sopenharmony_ci	{CS35L35_AMP_GAIN_ADV_CTL,	0x00},
638c2ecf20Sopenharmony_ci	{CS35L35_GPI_CTL,		0x00},
648c2ecf20Sopenharmony_ci	{CS35L35_BST_CVTR_V_CTL,	0x00},
658c2ecf20Sopenharmony_ci	{CS35L35_BST_PEAK_I,		0x07},
668c2ecf20Sopenharmony_ci	{CS35L35_BST_RAMP_CTL,		0x85},
678c2ecf20Sopenharmony_ci	{CS35L35_BST_CONV_COEF_1,	0x24},
688c2ecf20Sopenharmony_ci	{CS35L35_BST_CONV_COEF_2,	0x24},
698c2ecf20Sopenharmony_ci	{CS35L35_BST_CONV_SLOPE_COMP,	0x4E},
708c2ecf20Sopenharmony_ci	{CS35L35_BST_CONV_SW_FREQ,	0x04},
718c2ecf20Sopenharmony_ci	{CS35L35_CLASS_H_CTL,		0x0B},
728c2ecf20Sopenharmony_ci	{CS35L35_CLASS_H_HEADRM_CTL,	0x0B},
738c2ecf20Sopenharmony_ci	{CS35L35_CLASS_H_RELEASE_RATE,	0x08},
748c2ecf20Sopenharmony_ci	{CS35L35_CLASS_H_FET_DRIVE_CTL, 0x41},
758c2ecf20Sopenharmony_ci	{CS35L35_CLASS_H_VP_CTL,	0xC5},
768c2ecf20Sopenharmony_ci	{CS35L35_VPBR_CTL,		0x0A},
778c2ecf20Sopenharmony_ci	{CS35L35_VPBR_VOL_CTL,		0x90},
788c2ecf20Sopenharmony_ci	{CS35L35_VPBR_TIMING_CTL,	0x6A},
798c2ecf20Sopenharmony_ci	{CS35L35_VPBR_MODE_VOL_CTL,	0x00},
808c2ecf20Sopenharmony_ci	{CS35L35_SPKR_MON_CTL,		0xC0},
818c2ecf20Sopenharmony_ci	{CS35L35_IMON_SCALE_CTL,	0x30},
828c2ecf20Sopenharmony_ci	{CS35L35_AUDIN_RXLOC_CTL,	0x00},
838c2ecf20Sopenharmony_ci	{CS35L35_ADVIN_RXLOC_CTL,	0x80},
848c2ecf20Sopenharmony_ci	{CS35L35_VMON_TXLOC_CTL,	0x00},
858c2ecf20Sopenharmony_ci	{CS35L35_IMON_TXLOC_CTL,	0x80},
868c2ecf20Sopenharmony_ci	{CS35L35_VPMON_TXLOC_CTL,	0x04},
878c2ecf20Sopenharmony_ci	{CS35L35_VBSTMON_TXLOC_CTL,	0x84},
888c2ecf20Sopenharmony_ci	{CS35L35_VPBR_STATUS_TXLOC_CTL,	0x04},
898c2ecf20Sopenharmony_ci	{CS35L35_ZERO_FILL_LOC_CTL,	0x00},
908c2ecf20Sopenharmony_ci	{CS35L35_AUDIN_DEPTH_CTL,	0x0F},
918c2ecf20Sopenharmony_ci	{CS35L35_SPKMON_DEPTH_CTL,	0x0F},
928c2ecf20Sopenharmony_ci	{CS35L35_SUPMON_DEPTH_CTL,	0x0F},
938c2ecf20Sopenharmony_ci	{CS35L35_ZEROFILL_DEPTH_CTL,	0x00},
948c2ecf20Sopenharmony_ci	{CS35L35_MULT_DEV_SYNCH1,	0x02},
958c2ecf20Sopenharmony_ci	{CS35L35_MULT_DEV_SYNCH2,	0x80},
968c2ecf20Sopenharmony_ci	{CS35L35_PROT_RELEASE_CTL,	0x00},
978c2ecf20Sopenharmony_ci	{CS35L35_DIAG_MODE_REG_LOCK,	0x00},
988c2ecf20Sopenharmony_ci	{CS35L35_DIAG_MODE_CTL_1,	0x40},
998c2ecf20Sopenharmony_ci	{CS35L35_DIAG_MODE_CTL_2,	0x00},
1008c2ecf20Sopenharmony_ci	{CS35L35_INT_MASK_1,		0xFF},
1018c2ecf20Sopenharmony_ci	{CS35L35_INT_MASK_2,		0xFF},
1028c2ecf20Sopenharmony_ci	{CS35L35_INT_MASK_3,		0xFF},
1038c2ecf20Sopenharmony_ci	{CS35L35_INT_MASK_4,		0xFF},
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic bool cs35l35_volatile_register(struct device *dev, unsigned int reg)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	switch (reg) {
1108c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_1:
1118c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_2:
1128c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_3:
1138c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_4:
1148c2ecf20Sopenharmony_ci	case CS35L35_PLL_STATUS:
1158c2ecf20Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
1168c2ecf20Sopenharmony_ci		return true;
1178c2ecf20Sopenharmony_ci	default:
1188c2ecf20Sopenharmony_ci		return false;
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic bool cs35l35_readable_register(struct device *dev, unsigned int reg)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	switch (reg) {
1258c2ecf20Sopenharmony_ci	case CS35L35_DEVID_AB ... CS35L35_PWRCTL3:
1268c2ecf20Sopenharmony_ci	case CS35L35_CLK_CTL1 ... CS35L35_SP_FMT_CTL3:
1278c2ecf20Sopenharmony_ci	case CS35L35_MAG_COMP_CTL ... CS35L35_AMP_GAIN_AUD_CTL:
1288c2ecf20Sopenharmony_ci	case CS35L35_AMP_GAIN_PDM_CTL ... CS35L35_BST_PEAK_I:
1298c2ecf20Sopenharmony_ci	case CS35L35_BST_RAMP_CTL ... CS35L35_BST_CONV_SW_FREQ:
1308c2ecf20Sopenharmony_ci	case CS35L35_CLASS_H_CTL ... CS35L35_CLASS_H_VP_CTL:
1318c2ecf20Sopenharmony_ci	case CS35L35_CLASS_H_STATUS:
1328c2ecf20Sopenharmony_ci	case CS35L35_VPBR_CTL ... CS35L35_VPBR_MODE_VOL_CTL:
1338c2ecf20Sopenharmony_ci	case CS35L35_VPBR_ATTEN_STATUS:
1348c2ecf20Sopenharmony_ci	case CS35L35_SPKR_MON_CTL:
1358c2ecf20Sopenharmony_ci	case CS35L35_IMON_SCALE_CTL ... CS35L35_ZEROFILL_DEPTH_CTL:
1368c2ecf20Sopenharmony_ci	case CS35L35_MULT_DEV_SYNCH1 ... CS35L35_PROT_RELEASE_CTL:
1378c2ecf20Sopenharmony_ci	case CS35L35_DIAG_MODE_REG_LOCK ... CS35L35_DIAG_MODE_CTL_2:
1388c2ecf20Sopenharmony_ci	case CS35L35_INT_MASK_1 ... CS35L35_PLL_STATUS:
1398c2ecf20Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
1408c2ecf20Sopenharmony_ci		return true;
1418c2ecf20Sopenharmony_ci	default:
1428c2ecf20Sopenharmony_ci		return false;
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic bool cs35l35_precious_register(struct device *dev, unsigned int reg)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	switch (reg) {
1498c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_1:
1508c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_2:
1518c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_3:
1528c2ecf20Sopenharmony_ci	case CS35L35_INT_STATUS_4:
1538c2ecf20Sopenharmony_ci	case CS35L35_PLL_STATUS:
1548c2ecf20Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
1558c2ecf20Sopenharmony_ci		return true;
1568c2ecf20Sopenharmony_ci	default:
1578c2ecf20Sopenharmony_ci		return false;
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void cs35l35_reset(struct cs35l35_private *cs35l35)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
1648c2ecf20Sopenharmony_ci	usleep_range(2000, 2100);
1658c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
1668c2ecf20Sopenharmony_ci	usleep_range(1000, 1100);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	int ret;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (cs35l35->pdata.ext_bst) {
1748c2ecf20Sopenharmony_ci		usleep_range(5000, 5500);
1758c2ecf20Sopenharmony_ci		return 0;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	reinit_completion(&cs35l35->pdn_done);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	ret = wait_for_completion_timeout(&cs35l35->pdn_done,
1818c2ecf20Sopenharmony_ci					  msecs_to_jiffies(100));
1828c2ecf20Sopenharmony_ci	if (ret == 0) {
1838c2ecf20Sopenharmony_ci		dev_err(cs35l35->dev, "PDN_DONE did not complete\n");
1848c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	return 0;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
1918c2ecf20Sopenharmony_ci		struct snd_kcontrol *kcontrol, int event)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
1948c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
1958c2ecf20Sopenharmony_ci	int ret = 0;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	switch (event) {
1988c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
1998c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
2008c2ecf20Sopenharmony_ci					CS35L35_MCLK_DIS_MASK,
2018c2ecf20Sopenharmony_ci					0 << CS35L35_MCLK_DIS_SHIFT);
2028c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
2038c2ecf20Sopenharmony_ci					CS35L35_DISCHG_FILT_MASK,
2048c2ecf20Sopenharmony_ci					0 << CS35L35_DISCHG_FILT_SHIFT);
2058c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
2068c2ecf20Sopenharmony_ci					CS35L35_PDN_ALL_MASK, 0);
2078c2ecf20Sopenharmony_ci		break;
2088c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
2098c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
2108c2ecf20Sopenharmony_ci					CS35L35_DISCHG_FILT_MASK,
2118c2ecf20Sopenharmony_ci					1 << CS35L35_DISCHG_FILT_SHIFT);
2128c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
2138c2ecf20Sopenharmony_ci					  CS35L35_PDN_ALL_MASK, 1);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		/* Already muted, so disable volume ramp for faster shutdown */
2168c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
2178c2ecf20Sopenharmony_ci				   CS35L35_AMP_DIGSFT_MASK, 0);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci		ret = cs35l35_wait_for_pdn(cs35l35);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
2228c2ecf20Sopenharmony_ci					CS35L35_MCLK_DIS_MASK,
2238c2ecf20Sopenharmony_ci					1 << CS35L35_MCLK_DIS_SHIFT);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
2268c2ecf20Sopenharmony_ci				   CS35L35_AMP_DIGSFT_MASK,
2278c2ecf20Sopenharmony_ci				   1 << CS35L35_AMP_DIGSFT_SHIFT);
2288c2ecf20Sopenharmony_ci		break;
2298c2ecf20Sopenharmony_ci	default:
2308c2ecf20Sopenharmony_ci		dev_err(component->dev, "Invalid event = 0x%x\n", event);
2318c2ecf20Sopenharmony_ci		ret = -EINVAL;
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci	return ret;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic int cs35l35_main_amp_event(struct snd_soc_dapm_widget *w,
2378c2ecf20Sopenharmony_ci		struct snd_kcontrol *kcontrol, int event)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2408c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
2418c2ecf20Sopenharmony_ci	unsigned int reg[4];
2428c2ecf20Sopenharmony_ci	int i;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	switch (event) {
2458c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
2468c2ecf20Sopenharmony_ci		if (cs35l35->pdata.bst_pdn_fet_on)
2478c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
2488c2ecf20Sopenharmony_ci				CS35L35_PDN_BST_MASK,
2498c2ecf20Sopenharmony_ci				0 << CS35L35_PDN_BST_FETON_SHIFT);
2508c2ecf20Sopenharmony_ci		else
2518c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
2528c2ecf20Sopenharmony_ci				CS35L35_PDN_BST_MASK,
2538c2ecf20Sopenharmony_ci				0 << CS35L35_PDN_BST_FETOFF_SHIFT);
2548c2ecf20Sopenharmony_ci		break;
2558c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
2568c2ecf20Sopenharmony_ci		usleep_range(5000, 5100);
2578c2ecf20Sopenharmony_ci		/* If in PDM mode we must use VP for Voltage control */
2588c2ecf20Sopenharmony_ci		if (cs35l35->pdm_mode)
2598c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
2608c2ecf20Sopenharmony_ci					CS35L35_BST_CVTR_V_CTL,
2618c2ecf20Sopenharmony_ci					CS35L35_BST_CTL_MASK,
2628c2ecf20Sopenharmony_ci					0 << CS35L35_BST_CTL_SHIFT);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
2658c2ecf20Sopenharmony_ci			CS35L35_AMP_MUTE_MASK, 0);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci		for (i = 0; i < 2; i++)
2688c2ecf20Sopenharmony_ci			regmap_bulk_read(cs35l35->regmap, CS35L35_INT_STATUS_1,
2698c2ecf20Sopenharmony_ci					&reg, ARRAY_SIZE(reg));
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci		break;
2728c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
2738c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
2748c2ecf20Sopenharmony_ci				CS35L35_AMP_MUTE_MASK,
2758c2ecf20Sopenharmony_ci				1 << CS35L35_AMP_MUTE_SHIFT);
2768c2ecf20Sopenharmony_ci		if (cs35l35->pdata.bst_pdn_fet_on)
2778c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
2788c2ecf20Sopenharmony_ci				CS35L35_PDN_BST_MASK,
2798c2ecf20Sopenharmony_ci				1 << CS35L35_PDN_BST_FETON_SHIFT);
2808c2ecf20Sopenharmony_ci		else
2818c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
2828c2ecf20Sopenharmony_ci				CS35L35_PDN_BST_MASK,
2838c2ecf20Sopenharmony_ci				1 << CS35L35_PDN_BST_FETOFF_SHIFT);
2848c2ecf20Sopenharmony_ci		break;
2858c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
2868c2ecf20Sopenharmony_ci		usleep_range(5000, 5100);
2878c2ecf20Sopenharmony_ci		/*
2888c2ecf20Sopenharmony_ci		 * If PDM mode we should switch back to pdata value
2898c2ecf20Sopenharmony_ci		 * for Voltage control when we go down
2908c2ecf20Sopenharmony_ci		 */
2918c2ecf20Sopenharmony_ci		if (cs35l35->pdm_mode)
2928c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
2938c2ecf20Sopenharmony_ci					CS35L35_BST_CVTR_V_CTL,
2948c2ecf20Sopenharmony_ci					CS35L35_BST_CTL_MASK,
2958c2ecf20Sopenharmony_ci					cs35l35->pdata.bst_vctl
2968c2ecf20Sopenharmony_ci					<< CS35L35_BST_CTL_SHIFT);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci		break;
2998c2ecf20Sopenharmony_ci	default:
3008c2ecf20Sopenharmony_ci		dev_err(component->dev, "Invalid event = 0x%x\n", event);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci	return 0;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
3068c2ecf20Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 50, 0);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cs35l35_aud_controls[] = {
3098c2ecf20Sopenharmony_ci	SOC_SINGLE_SX_TLV("Digital Audio Volume", CS35L35_AMP_DIG_VOL,
3108c2ecf20Sopenharmony_ci		      0, 0x34, 0xE4, dig_vol_tlv),
3118c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Analog Audio Volume", CS35L35_AMP_GAIN_AUD_CTL, 0, 19, 0,
3128c2ecf20Sopenharmony_ci			amp_gain_tlv),
3138c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("PDM Volume", CS35L35_AMP_GAIN_PDM_CTL, 0, 19, 0,
3148c2ecf20Sopenharmony_ci			amp_gain_tlv),
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cs35l35_adv_controls[] = {
3188c2ecf20Sopenharmony_ci	SOC_SINGLE_SX_TLV("Digital Advisory Volume", CS35L35_ADV_DIG_VOL,
3198c2ecf20Sopenharmony_ci		      0, 0x34, 0xE4, dig_vol_tlv),
3208c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Analog Advisory Volume", CS35L35_AMP_GAIN_ADV_CTL, 0, 19, 0,
3218c2ecf20Sopenharmony_ci			amp_gain_tlv),
3228c2ecf20Sopenharmony_ci};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget cs35l35_dapm_widgets[] = {
3258c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L35_PWRCTL3, 1, 1,
3268c2ecf20Sopenharmony_ci				cs35l35_sdin_event, SND_SOC_DAPM_PRE_PMU |
3278c2ecf20Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
3288c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L35_PWRCTL3, 2, 1),
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPK"),
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("VP"),
3338c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("VBST"),
3348c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("ISENSE"),
3358c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("VSENSE"),
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L35_PWRCTL2, 7, 1),
3388c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L35_PWRCTL2, 6, 1),
3398c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L35_PWRCTL3, 3, 1),
3408c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L35_PWRCTL3, 4, 1),
3418c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L35_PWRCTL2, 5, 1),
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L35_PWRCTL2, 0, 1, NULL, 0,
3448c2ecf20Sopenharmony_ci		cs35l35_main_amp_event, SND_SOC_DAPM_PRE_PMU |
3458c2ecf20Sopenharmony_ci				SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU |
3468c2ecf20Sopenharmony_ci				SND_SOC_DAPM_PRE_PMD),
3478c2ecf20Sopenharmony_ci};
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route cs35l35_audio_map[] = {
3508c2ecf20Sopenharmony_ci	{"VPMON ADC", NULL, "VP"},
3518c2ecf20Sopenharmony_ci	{"VBSTMON ADC", NULL, "VBST"},
3528c2ecf20Sopenharmony_ci	{"IMON ADC", NULL, "ISENSE"},
3538c2ecf20Sopenharmony_ci	{"VMON ADC", NULL, "VSENSE"},
3548c2ecf20Sopenharmony_ci	{"SDOUT", NULL, "IMON ADC"},
3558c2ecf20Sopenharmony_ci	{"SDOUT", NULL, "VMON ADC"},
3568c2ecf20Sopenharmony_ci	{"SDOUT", NULL, "VBSTMON ADC"},
3578c2ecf20Sopenharmony_ci	{"SDOUT", NULL, "VPMON ADC"},
3588c2ecf20Sopenharmony_ci	{"AMP Capture", NULL, "SDOUT"},
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	{"SDIN", NULL, "AMP Playback"},
3618c2ecf20Sopenharmony_ci	{"CLASS H", NULL, "SDIN"},
3628c2ecf20Sopenharmony_ci	{"Main AMP", NULL, "CLASS H"},
3638c2ecf20Sopenharmony_ci	{"SPK", NULL, "Main AMP"},
3648c2ecf20Sopenharmony_ci};
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic int cs35l35_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
3698c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
3728c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
3738c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
3748c2ecf20Sopenharmony_ci				    CS35L35_MS_MASK, 1 << CS35L35_MS_SHIFT);
3758c2ecf20Sopenharmony_ci		cs35l35->slave_mode = false;
3768c2ecf20Sopenharmony_ci		break;
3778c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBS_CFS:
3788c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
3798c2ecf20Sopenharmony_ci				    CS35L35_MS_MASK, 0 << CS35L35_MS_SHIFT);
3808c2ecf20Sopenharmony_ci		cs35l35->slave_mode = true;
3818c2ecf20Sopenharmony_ci		break;
3828c2ecf20Sopenharmony_ci	default:
3838c2ecf20Sopenharmony_ci		return -EINVAL;
3848c2ecf20Sopenharmony_ci	}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
3878c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
3888c2ecf20Sopenharmony_ci		cs35l35->i2s_mode = true;
3898c2ecf20Sopenharmony_ci		cs35l35->pdm_mode = false;
3908c2ecf20Sopenharmony_ci		break;
3918c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_PDM:
3928c2ecf20Sopenharmony_ci		cs35l35->pdm_mode = true;
3938c2ecf20Sopenharmony_ci		cs35l35->i2s_mode = false;
3948c2ecf20Sopenharmony_ci		break;
3958c2ecf20Sopenharmony_ci	default:
3968c2ecf20Sopenharmony_ci		return -EINVAL;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	return 0;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistruct cs35l35_sysclk_config {
4038c2ecf20Sopenharmony_ci	int sysclk;
4048c2ecf20Sopenharmony_ci	int srate;
4058c2ecf20Sopenharmony_ci	u8 clk_cfg;
4068c2ecf20Sopenharmony_ci};
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic struct cs35l35_sysclk_config cs35l35_clk_ctl[] = {
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* SYSCLK, Sample Rate, Serial Port Cfg */
4118c2ecf20Sopenharmony_ci	{5644800, 44100, 0x00},
4128c2ecf20Sopenharmony_ci	{5644800, 88200, 0x40},
4138c2ecf20Sopenharmony_ci	{6144000, 48000, 0x10},
4148c2ecf20Sopenharmony_ci	{6144000, 96000, 0x50},
4158c2ecf20Sopenharmony_ci	{11289600, 44100, 0x01},
4168c2ecf20Sopenharmony_ci	{11289600, 88200, 0x41},
4178c2ecf20Sopenharmony_ci	{11289600, 176400, 0x81},
4188c2ecf20Sopenharmony_ci	{12000000, 44100, 0x03},
4198c2ecf20Sopenharmony_ci	{12000000, 48000, 0x13},
4208c2ecf20Sopenharmony_ci	{12000000, 88200, 0x43},
4218c2ecf20Sopenharmony_ci	{12000000, 96000, 0x53},
4228c2ecf20Sopenharmony_ci	{12000000, 176400, 0x83},
4238c2ecf20Sopenharmony_ci	{12000000, 192000, 0x93},
4248c2ecf20Sopenharmony_ci	{12288000, 48000, 0x11},
4258c2ecf20Sopenharmony_ci	{12288000, 96000, 0x51},
4268c2ecf20Sopenharmony_ci	{12288000, 192000, 0x91},
4278c2ecf20Sopenharmony_ci	{13000000, 44100, 0x07},
4288c2ecf20Sopenharmony_ci	{13000000, 48000, 0x17},
4298c2ecf20Sopenharmony_ci	{13000000, 88200, 0x47},
4308c2ecf20Sopenharmony_ci	{13000000, 96000, 0x57},
4318c2ecf20Sopenharmony_ci	{13000000, 176400, 0x87},
4328c2ecf20Sopenharmony_ci	{13000000, 192000, 0x97},
4338c2ecf20Sopenharmony_ci	{22579200, 44100, 0x02},
4348c2ecf20Sopenharmony_ci	{22579200, 88200, 0x42},
4358c2ecf20Sopenharmony_ci	{22579200, 176400, 0x82},
4368c2ecf20Sopenharmony_ci	{24000000, 44100, 0x0B},
4378c2ecf20Sopenharmony_ci	{24000000, 48000, 0x1B},
4388c2ecf20Sopenharmony_ci	{24000000, 88200, 0x4B},
4398c2ecf20Sopenharmony_ci	{24000000, 96000, 0x5B},
4408c2ecf20Sopenharmony_ci	{24000000, 176400, 0x8B},
4418c2ecf20Sopenharmony_ci	{24000000, 192000, 0x9B},
4428c2ecf20Sopenharmony_ci	{24576000, 48000, 0x12},
4438c2ecf20Sopenharmony_ci	{24576000, 96000, 0x52},
4448c2ecf20Sopenharmony_ci	{24576000, 192000, 0x92},
4458c2ecf20Sopenharmony_ci	{26000000, 44100, 0x0F},
4468c2ecf20Sopenharmony_ci	{26000000, 48000, 0x1F},
4478c2ecf20Sopenharmony_ci	{26000000, 88200, 0x4F},
4488c2ecf20Sopenharmony_ci	{26000000, 96000, 0x5F},
4498c2ecf20Sopenharmony_ci	{26000000, 176400, 0x8F},
4508c2ecf20Sopenharmony_ci	{26000000, 192000, 0x9F},
4518c2ecf20Sopenharmony_ci};
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistatic int cs35l35_get_clk_config(int sysclk, int srate)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	int i;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l35_clk_ctl); i++) {
4588c2ecf20Sopenharmony_ci		if (cs35l35_clk_ctl[i].sysclk == sysclk &&
4598c2ecf20Sopenharmony_ci			cs35l35_clk_ctl[i].srate == srate)
4608c2ecf20Sopenharmony_ci			return cs35l35_clk_ctl[i].clk_cfg;
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci	return -EINVAL;
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cistatic int cs35l35_hw_params(struct snd_pcm_substream *substream,
4668c2ecf20Sopenharmony_ci				 struct snd_pcm_hw_params *params,
4678c2ecf20Sopenharmony_ci				 struct snd_soc_dai *dai)
4688c2ecf20Sopenharmony_ci{
4698c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
4708c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
4718c2ecf20Sopenharmony_ci	struct classh_cfg *classh = &cs35l35->pdata.classh_algo;
4728c2ecf20Sopenharmony_ci	int srate = params_rate(params);
4738c2ecf20Sopenharmony_ci	int ret = 0;
4748c2ecf20Sopenharmony_ci	u8 sp_sclks;
4758c2ecf20Sopenharmony_ci	int audin_format;
4768c2ecf20Sopenharmony_ci	int errata_chk;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	int clk_ctl = cs35l35_get_clk_config(cs35l35->sysclk, srate);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	if (clk_ctl < 0) {
4818c2ecf20Sopenharmony_ci		dev_err(component->dev, "Invalid CLK:Rate %d:%d\n",
4828c2ecf20Sopenharmony_ci			cs35l35->sysclk, srate);
4838c2ecf20Sopenharmony_ci		return -EINVAL;
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL2,
4878c2ecf20Sopenharmony_ci			  CS35L35_CLK_CTL2_MASK, clk_ctl);
4888c2ecf20Sopenharmony_ci	if (ret != 0) {
4898c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set port config %d\n", ret);
4908c2ecf20Sopenharmony_ci		return ret;
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	/*
4948c2ecf20Sopenharmony_ci	 * Rev A0 Errata
4958c2ecf20Sopenharmony_ci	 * When configured for the weak-drive detection path (CH_WKFET_DIS = 0)
4968c2ecf20Sopenharmony_ci	 * the Class H algorithm does not enable weak-drive operation for
4978c2ecf20Sopenharmony_ci	 * nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10
4988c2ecf20Sopenharmony_ci	 */
4998c2ecf20Sopenharmony_ci	errata_chk = clk_ctl & CS35L35_SP_RATE_MASK;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	if (classh->classh_wk_fet_disable == 0x00 &&
5028c2ecf20Sopenharmony_ci		(errata_chk == 0x01 || errata_chk == 0x03)) {
5038c2ecf20Sopenharmony_ci		ret = regmap_update_bits(cs35l35->regmap,
5048c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
5058c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_DEL_MASK,
5068c2ecf20Sopenharmony_ci					0 << CS35L35_CH_WKFET_DEL_SHIFT);
5078c2ecf20Sopenharmony_ci		if (ret != 0) {
5088c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to set fet config %d\n",
5098c2ecf20Sopenharmony_ci				ret);
5108c2ecf20Sopenharmony_ci			return ret;
5118c2ecf20Sopenharmony_ci		}
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	/*
5158c2ecf20Sopenharmony_ci	 * You can pull more Monitor data from the SDOUT pin than going to SDIN
5168c2ecf20Sopenharmony_ci	 * Just make sure your SCLK is fast enough to fill the frame
5178c2ecf20Sopenharmony_ci	 */
5188c2ecf20Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5198c2ecf20Sopenharmony_ci		switch (params_width(params)) {
5208c2ecf20Sopenharmony_ci		case 8:
5218c2ecf20Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_8;
5228c2ecf20Sopenharmony_ci			break;
5238c2ecf20Sopenharmony_ci		case 16:
5248c2ecf20Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_16;
5258c2ecf20Sopenharmony_ci			break;
5268c2ecf20Sopenharmony_ci		case 24:
5278c2ecf20Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_24;
5288c2ecf20Sopenharmony_ci			break;
5298c2ecf20Sopenharmony_ci		default:
5308c2ecf20Sopenharmony_ci			dev_err(component->dev, "Unsupported Width %d\n",
5318c2ecf20Sopenharmony_ci				params_width(params));
5328c2ecf20Sopenharmony_ci			return -EINVAL;
5338c2ecf20Sopenharmony_ci		}
5348c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
5358c2ecf20Sopenharmony_ci				CS35L35_AUDIN_DEPTH_CTL,
5368c2ecf20Sopenharmony_ci				CS35L35_AUDIN_DEPTH_MASK,
5378c2ecf20Sopenharmony_ci				audin_format <<
5388c2ecf20Sopenharmony_ci				CS35L35_AUDIN_DEPTH_SHIFT);
5398c2ecf20Sopenharmony_ci		if (cs35l35->pdata.stereo) {
5408c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
5418c2ecf20Sopenharmony_ci					CS35L35_AUDIN_DEPTH_CTL,
5428c2ecf20Sopenharmony_ci					CS35L35_ADVIN_DEPTH_MASK,
5438c2ecf20Sopenharmony_ci					audin_format <<
5448c2ecf20Sopenharmony_ci					CS35L35_ADVIN_DEPTH_SHIFT);
5458c2ecf20Sopenharmony_ci		}
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (cs35l35->i2s_mode) {
5498c2ecf20Sopenharmony_ci		/* We have to take the SCLK to derive num sclks
5508c2ecf20Sopenharmony_ci		 * to configure the CLOCK_CTL3 register correctly
5518c2ecf20Sopenharmony_ci		 */
5528c2ecf20Sopenharmony_ci		if ((cs35l35->sclk / srate) % 4) {
5538c2ecf20Sopenharmony_ci			dev_err(component->dev, "Unsupported sclk/fs ratio %d:%d\n",
5548c2ecf20Sopenharmony_ci					cs35l35->sclk, srate);
5558c2ecf20Sopenharmony_ci			return -EINVAL;
5568c2ecf20Sopenharmony_ci		}
5578c2ecf20Sopenharmony_ci		sp_sclks = ((cs35l35->sclk / srate) / 4) - 1;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		/* Only certain ratios are supported in I2S Slave Mode */
5608c2ecf20Sopenharmony_ci		if (cs35l35->slave_mode) {
5618c2ecf20Sopenharmony_ci			switch (sp_sclks) {
5628c2ecf20Sopenharmony_ci			case CS35L35_SP_SCLKS_32FS:
5638c2ecf20Sopenharmony_ci			case CS35L35_SP_SCLKS_48FS:
5648c2ecf20Sopenharmony_ci			case CS35L35_SP_SCLKS_64FS:
5658c2ecf20Sopenharmony_ci				break;
5668c2ecf20Sopenharmony_ci			default:
5678c2ecf20Sopenharmony_ci				dev_err(component->dev, "ratio not supported\n");
5688c2ecf20Sopenharmony_ci				return -EINVAL;
5698c2ecf20Sopenharmony_ci			}
5708c2ecf20Sopenharmony_ci		} else {
5718c2ecf20Sopenharmony_ci			/* Only certain ratios supported in I2S MASTER Mode */
5728c2ecf20Sopenharmony_ci			switch (sp_sclks) {
5738c2ecf20Sopenharmony_ci			case CS35L35_SP_SCLKS_32FS:
5748c2ecf20Sopenharmony_ci			case CS35L35_SP_SCLKS_64FS:
5758c2ecf20Sopenharmony_ci				break;
5768c2ecf20Sopenharmony_ci			default:
5778c2ecf20Sopenharmony_ci				dev_err(component->dev, "ratio not supported\n");
5788c2ecf20Sopenharmony_ci				return -EINVAL;
5798c2ecf20Sopenharmony_ci			}
5808c2ecf20Sopenharmony_ci		}
5818c2ecf20Sopenharmony_ci		ret = regmap_update_bits(cs35l35->regmap,
5828c2ecf20Sopenharmony_ci					CS35L35_CLK_CTL3,
5838c2ecf20Sopenharmony_ci					CS35L35_SP_SCLKS_MASK, sp_sclks <<
5848c2ecf20Sopenharmony_ci					CS35L35_SP_SCLKS_SHIFT);
5858c2ecf20Sopenharmony_ci		if (ret != 0) {
5868c2ecf20Sopenharmony_ci			dev_err(component->dev, "Failed to set fsclk %d\n", ret);
5878c2ecf20Sopenharmony_ci			return ret;
5888c2ecf20Sopenharmony_ci		}
5898c2ecf20Sopenharmony_ci	}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	return ret;
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic const unsigned int cs35l35_src_rates[] = {
5958c2ecf20Sopenharmony_ci	44100, 48000, 88200, 96000, 176400, 192000
5968c2ecf20Sopenharmony_ci};
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list cs35l35_constraints = {
5998c2ecf20Sopenharmony_ci	.count  = ARRAY_SIZE(cs35l35_src_rates),
6008c2ecf20Sopenharmony_ci	.list   = cs35l35_src_rates,
6018c2ecf20Sopenharmony_ci};
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_cistatic int cs35l35_pcm_startup(struct snd_pcm_substream *substream,
6048c2ecf20Sopenharmony_ci			       struct snd_soc_dai *dai)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
6078c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (!substream->runtime)
6108c2ecf20Sopenharmony_ci		return 0;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(substream->runtime, 0,
6138c2ecf20Sopenharmony_ci				SNDRV_PCM_HW_PARAM_RATE, &cs35l35_constraints);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,
6168c2ecf20Sopenharmony_ci					CS35L35_PDM_MODE_MASK,
6178c2ecf20Sopenharmony_ci					0 << CS35L35_PDM_MODE_SHIFT);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	return 0;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic const unsigned int cs35l35_pdm_rates[] = {
6238c2ecf20Sopenharmony_ci	44100, 48000, 88200, 96000
6248c2ecf20Sopenharmony_ci};
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list cs35l35_pdm_constraints = {
6278c2ecf20Sopenharmony_ci	.count  = ARRAY_SIZE(cs35l35_pdm_rates),
6288c2ecf20Sopenharmony_ci	.list   = cs35l35_pdm_rates,
6298c2ecf20Sopenharmony_ci};
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_cistatic int cs35l35_pdm_startup(struct snd_pcm_substream *substream,
6328c2ecf20Sopenharmony_ci			       struct snd_soc_dai *dai)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
6358c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (!substream->runtime)
6388c2ecf20Sopenharmony_ci		return 0;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(substream->runtime, 0,
6418c2ecf20Sopenharmony_ci				SNDRV_PCM_HW_PARAM_RATE,
6428c2ecf20Sopenharmony_ci				&cs35l35_pdm_constraints);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,
6458c2ecf20Sopenharmony_ci					CS35L35_PDM_MODE_MASK,
6468c2ecf20Sopenharmony_ci					1 << CS35L35_PDM_MODE_SHIFT);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	return 0;
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic int cs35l35_dai_set_sysclk(struct snd_soc_dai *dai,
6528c2ecf20Sopenharmony_ci				int clk_id, unsigned int freq, int dir)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
6558c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	/* Need the SCLK Frequency regardless of sysclk source for I2S */
6588c2ecf20Sopenharmony_ci	cs35l35->sclk = freq;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	return 0;
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops cs35l35_ops = {
6648c2ecf20Sopenharmony_ci	.startup = cs35l35_pcm_startup,
6658c2ecf20Sopenharmony_ci	.set_fmt = cs35l35_set_dai_fmt,
6668c2ecf20Sopenharmony_ci	.hw_params = cs35l35_hw_params,
6678c2ecf20Sopenharmony_ci	.set_sysclk = cs35l35_dai_set_sysclk,
6688c2ecf20Sopenharmony_ci};
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops cs35l35_pdm_ops = {
6718c2ecf20Sopenharmony_ci	.startup = cs35l35_pdm_startup,
6728c2ecf20Sopenharmony_ci	.set_fmt = cs35l35_set_dai_fmt,
6738c2ecf20Sopenharmony_ci	.hw_params = cs35l35_hw_params,
6748c2ecf20Sopenharmony_ci};
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver cs35l35_dai[] = {
6778c2ecf20Sopenharmony_ci	{
6788c2ecf20Sopenharmony_ci		.name = "cs35l35-pcm",
6798c2ecf20Sopenharmony_ci		.id = 0,
6808c2ecf20Sopenharmony_ci		.playback = {
6818c2ecf20Sopenharmony_ci			.stream_name = "AMP Playback",
6828c2ecf20Sopenharmony_ci			.channels_min = 1,
6838c2ecf20Sopenharmony_ci			.channels_max = 8,
6848c2ecf20Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
6858c2ecf20Sopenharmony_ci			.formats = CS35L35_FORMATS,
6868c2ecf20Sopenharmony_ci		},
6878c2ecf20Sopenharmony_ci		.capture = {
6888c2ecf20Sopenharmony_ci			.stream_name = "AMP Capture",
6898c2ecf20Sopenharmony_ci			.channels_min = 1,
6908c2ecf20Sopenharmony_ci			.channels_max = 8,
6918c2ecf20Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
6928c2ecf20Sopenharmony_ci			.formats = CS35L35_FORMATS,
6938c2ecf20Sopenharmony_ci		},
6948c2ecf20Sopenharmony_ci		.ops = &cs35l35_ops,
6958c2ecf20Sopenharmony_ci		.symmetric_rates = 1,
6968c2ecf20Sopenharmony_ci	},
6978c2ecf20Sopenharmony_ci	{
6988c2ecf20Sopenharmony_ci		.name = "cs35l35-pdm",
6998c2ecf20Sopenharmony_ci		.id = 1,
7008c2ecf20Sopenharmony_ci		.playback = {
7018c2ecf20Sopenharmony_ci			.stream_name = "PDM Playback",
7028c2ecf20Sopenharmony_ci			.channels_min = 1,
7038c2ecf20Sopenharmony_ci			.channels_max = 2,
7048c2ecf20Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
7058c2ecf20Sopenharmony_ci			.formats = CS35L35_FORMATS,
7068c2ecf20Sopenharmony_ci		},
7078c2ecf20Sopenharmony_ci		.ops = &cs35l35_pdm_ops,
7088c2ecf20Sopenharmony_ci	},
7098c2ecf20Sopenharmony_ci};
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_cistatic int cs35l35_component_set_sysclk(struct snd_soc_component *component,
7128c2ecf20Sopenharmony_ci				int clk_id, int source, unsigned int freq,
7138c2ecf20Sopenharmony_ci				int dir)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
7168c2ecf20Sopenharmony_ci	int clksrc;
7178c2ecf20Sopenharmony_ci	int ret = 0;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	switch (clk_id) {
7208c2ecf20Sopenharmony_ci	case 0:
7218c2ecf20Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_MCLK;
7228c2ecf20Sopenharmony_ci		break;
7238c2ecf20Sopenharmony_ci	case 1:
7248c2ecf20Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_SCLK;
7258c2ecf20Sopenharmony_ci		break;
7268c2ecf20Sopenharmony_ci	case 2:
7278c2ecf20Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_PDM;
7288c2ecf20Sopenharmony_ci		break;
7298c2ecf20Sopenharmony_ci	default:
7308c2ecf20Sopenharmony_ci		dev_err(component->dev, "Invalid CLK Source\n");
7318c2ecf20Sopenharmony_ci		return -EINVAL;
7328c2ecf20Sopenharmony_ci	}
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	switch (freq) {
7358c2ecf20Sopenharmony_ci	case 5644800:
7368c2ecf20Sopenharmony_ci	case 6144000:
7378c2ecf20Sopenharmony_ci	case 11289600:
7388c2ecf20Sopenharmony_ci	case 12000000:
7398c2ecf20Sopenharmony_ci	case 12288000:
7408c2ecf20Sopenharmony_ci	case 13000000:
7418c2ecf20Sopenharmony_ci	case 22579200:
7428c2ecf20Sopenharmony_ci	case 24000000:
7438c2ecf20Sopenharmony_ci	case 24576000:
7448c2ecf20Sopenharmony_ci	case 26000000:
7458c2ecf20Sopenharmony_ci		cs35l35->sysclk = freq;
7468c2ecf20Sopenharmony_ci		break;
7478c2ecf20Sopenharmony_ci	default:
7488c2ecf20Sopenharmony_ci		dev_err(component->dev, "Invalid CLK Frequency Input : %d\n", freq);
7498c2ecf20Sopenharmony_ci		return -EINVAL;
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
7538c2ecf20Sopenharmony_ci				CS35L35_CLK_SOURCE_MASK,
7548c2ecf20Sopenharmony_ci				clksrc << CS35L35_CLK_SOURCE_SHIFT);
7558c2ecf20Sopenharmony_ci	if (ret != 0) {
7568c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set sysclk %d\n", ret);
7578c2ecf20Sopenharmony_ci		return ret;
7588c2ecf20Sopenharmony_ci	}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	return ret;
7618c2ecf20Sopenharmony_ci}
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic int cs35l35_boost_inductor(struct cs35l35_private *cs35l35,
7648c2ecf20Sopenharmony_ci				  int inductor)
7658c2ecf20Sopenharmony_ci{
7668c2ecf20Sopenharmony_ci	struct regmap *regmap = cs35l35->regmap;
7678c2ecf20Sopenharmony_ci	unsigned int bst_ipk = 0;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	/*
7708c2ecf20Sopenharmony_ci	 * Digital Boost Converter Configuration for feedback,
7718c2ecf20Sopenharmony_ci	 * ramping, switching frequency, and estimation block seeding.
7728c2ecf20Sopenharmony_ci	 */
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
7758c2ecf20Sopenharmony_ci			   CS35L35_BST_CONV_SWFREQ_MASK, 0x00);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk);
7788c2ecf20Sopenharmony_ci	bst_ipk &= CS35L35_BST_IPK_MASK;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	switch (inductor) {
7818c2ecf20Sopenharmony_ci	case 1000: /* 1 uH */
7828c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24);
7838c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24);
7848c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
7858c2ecf20Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x00);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci		if (bst_ipk < 0x04)
7888c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
7898c2ecf20Sopenharmony_ci		else
7908c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E);
7918c2ecf20Sopenharmony_ci		break;
7928c2ecf20Sopenharmony_ci	case 1200: /* 1.2 uH */
7938c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
7948c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
7958c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
7968c2ecf20Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x01);
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci		if (bst_ipk < 0x04)
7998c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
8008c2ecf20Sopenharmony_ci		else
8018c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47);
8028c2ecf20Sopenharmony_ci		break;
8038c2ecf20Sopenharmony_ci	case 1500: /* 1.5uH */
8048c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
8058c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
8068c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
8078c2ecf20Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x02);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci		if (bst_ipk < 0x04)
8108c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
8118c2ecf20Sopenharmony_ci		else
8128c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C);
8138c2ecf20Sopenharmony_ci		break;
8148c2ecf20Sopenharmony_ci	case 2200: /* 2.2uH */
8158c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19);
8168c2ecf20Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25);
8178c2ecf20Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
8188c2ecf20Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x03);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci		if (bst_ipk < 0x04)
8218c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
8228c2ecf20Sopenharmony_ci		else
8238c2ecf20Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23);
8248c2ecf20Sopenharmony_ci		break;
8258c2ecf20Sopenharmony_ci	default:
8268c2ecf20Sopenharmony_ci		dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n",
8278c2ecf20Sopenharmony_ci			inductor);
8288c2ecf20Sopenharmony_ci		return -EINVAL;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci	return 0;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic int cs35l35_component_probe(struct snd_soc_component *component)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
8368c2ecf20Sopenharmony_ci	struct classh_cfg *classh = &cs35l35->pdata.classh_algo;
8378c2ecf20Sopenharmony_ci	struct monitor_cfg *monitor_config = &cs35l35->pdata.mon_cfg;
8388c2ecf20Sopenharmony_ci	int ret;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	/* Set Platform Data */
8418c2ecf20Sopenharmony_ci	if (cs35l35->pdata.bst_vctl)
8428c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_BST_CVTR_V_CTL,
8438c2ecf20Sopenharmony_ci				CS35L35_BST_CTL_MASK,
8448c2ecf20Sopenharmony_ci				cs35l35->pdata.bst_vctl);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	if (cs35l35->pdata.bst_ipk)
8478c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_BST_PEAK_I,
8488c2ecf20Sopenharmony_ci				CS35L35_BST_IPK_MASK,
8498c2ecf20Sopenharmony_ci				cs35l35->pdata.bst_ipk <<
8508c2ecf20Sopenharmony_ci				CS35L35_BST_IPK_SHIFT);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);
8538c2ecf20Sopenharmony_ci	if (ret)
8548c2ecf20Sopenharmony_ci		return ret;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	if (cs35l35->pdata.gain_zc)
8578c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
8588c2ecf20Sopenharmony_ci				CS35L35_AMP_GAIN_ZC_MASK,
8598c2ecf20Sopenharmony_ci				cs35l35->pdata.gain_zc <<
8608c2ecf20Sopenharmony_ci				CS35L35_AMP_GAIN_ZC_SHIFT);
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	if (cs35l35->pdata.aud_channel)
8638c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
8648c2ecf20Sopenharmony_ci				CS35L35_AUDIN_RXLOC_CTL,
8658c2ecf20Sopenharmony_ci				CS35L35_AUD_IN_LR_MASK,
8668c2ecf20Sopenharmony_ci				cs35l35->pdata.aud_channel <<
8678c2ecf20Sopenharmony_ci				CS35L35_AUD_IN_LR_SHIFT);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	if (cs35l35->pdata.stereo) {
8708c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
8718c2ecf20Sopenharmony_ci				CS35L35_ADVIN_RXLOC_CTL,
8728c2ecf20Sopenharmony_ci				CS35L35_ADV_IN_LR_MASK,
8738c2ecf20Sopenharmony_ci				cs35l35->pdata.adv_channel <<
8748c2ecf20Sopenharmony_ci				CS35L35_ADV_IN_LR_SHIFT);
8758c2ecf20Sopenharmony_ci		if (cs35l35->pdata.shared_bst)
8768c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_CLASS_H_CTL,
8778c2ecf20Sopenharmony_ci					CS35L35_CH_STEREO_MASK,
8788c2ecf20Sopenharmony_ci					1 << CS35L35_CH_STEREO_SHIFT);
8798c2ecf20Sopenharmony_ci		ret = snd_soc_add_component_controls(component, cs35l35_adv_controls,
8808c2ecf20Sopenharmony_ci					ARRAY_SIZE(cs35l35_adv_controls));
8818c2ecf20Sopenharmony_ci		if (ret)
8828c2ecf20Sopenharmony_ci			return ret;
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	if (cs35l35->pdata.sp_drv_str)
8868c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
8878c2ecf20Sopenharmony_ci				CS35L35_SP_DRV_MASK,
8888c2ecf20Sopenharmony_ci				cs35l35->pdata.sp_drv_str <<
8898c2ecf20Sopenharmony_ci				CS35L35_SP_DRV_SHIFT);
8908c2ecf20Sopenharmony_ci	if (cs35l35->pdata.sp_drv_unused)
8918c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_SP_FMT_CTL3,
8928c2ecf20Sopenharmony_ci				   CS35L35_SP_I2S_DRV_MASK,
8938c2ecf20Sopenharmony_ci				   cs35l35->pdata.sp_drv_unused <<
8948c2ecf20Sopenharmony_ci				   CS35L35_SP_I2S_DRV_SHIFT);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	if (classh->classh_algo_enable) {
8978c2ecf20Sopenharmony_ci		if (classh->classh_bst_override)
8988c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
8998c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_CTL,
9008c2ecf20Sopenharmony_ci					CS35L35_CH_BST_OVR_MASK,
9018c2ecf20Sopenharmony_ci					classh->classh_bst_override <<
9028c2ecf20Sopenharmony_ci					CS35L35_CH_BST_OVR_SHIFT);
9038c2ecf20Sopenharmony_ci		if (classh->classh_bst_max_limit)
9048c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9058c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_CTL,
9068c2ecf20Sopenharmony_ci					CS35L35_CH_BST_LIM_MASK,
9078c2ecf20Sopenharmony_ci					classh->classh_bst_max_limit <<
9088c2ecf20Sopenharmony_ci					CS35L35_CH_BST_LIM_SHIFT);
9098c2ecf20Sopenharmony_ci		if (classh->classh_mem_depth)
9108c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9118c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_CTL,
9128c2ecf20Sopenharmony_ci					CS35L35_CH_MEM_DEPTH_MASK,
9138c2ecf20Sopenharmony_ci					classh->classh_mem_depth <<
9148c2ecf20Sopenharmony_ci					CS35L35_CH_MEM_DEPTH_SHIFT);
9158c2ecf20Sopenharmony_ci		if (classh->classh_headroom)
9168c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9178c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_HEADRM_CTL,
9188c2ecf20Sopenharmony_ci					CS35L35_CH_HDRM_CTL_MASK,
9198c2ecf20Sopenharmony_ci					classh->classh_headroom <<
9208c2ecf20Sopenharmony_ci					CS35L35_CH_HDRM_CTL_SHIFT);
9218c2ecf20Sopenharmony_ci		if (classh->classh_release_rate)
9228c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9238c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_RELEASE_RATE,
9248c2ecf20Sopenharmony_ci					CS35L35_CH_REL_RATE_MASK,
9258c2ecf20Sopenharmony_ci					classh->classh_release_rate <<
9268c2ecf20Sopenharmony_ci					CS35L35_CH_REL_RATE_SHIFT);
9278c2ecf20Sopenharmony_ci		if (classh->classh_wk_fet_disable)
9288c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9298c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
9308c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_DIS_MASK,
9318c2ecf20Sopenharmony_ci					classh->classh_wk_fet_disable <<
9328c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_DIS_SHIFT);
9338c2ecf20Sopenharmony_ci		if (classh->classh_wk_fet_delay)
9348c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9358c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
9368c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_DEL_MASK,
9378c2ecf20Sopenharmony_ci					classh->classh_wk_fet_delay <<
9388c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_DEL_SHIFT);
9398c2ecf20Sopenharmony_ci		if (classh->classh_wk_fet_thld)
9408c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9418c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
9428c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_THLD_MASK,
9438c2ecf20Sopenharmony_ci					classh->classh_wk_fet_thld <<
9448c2ecf20Sopenharmony_ci					CS35L35_CH_WKFET_THLD_SHIFT);
9458c2ecf20Sopenharmony_ci		if (classh->classh_vpch_auto)
9468c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9478c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
9488c2ecf20Sopenharmony_ci					CS35L35_CH_VP_AUTO_MASK,
9498c2ecf20Sopenharmony_ci					classh->classh_vpch_auto <<
9508c2ecf20Sopenharmony_ci					CS35L35_CH_VP_AUTO_SHIFT);
9518c2ecf20Sopenharmony_ci		if (classh->classh_vpch_rate)
9528c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9538c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
9548c2ecf20Sopenharmony_ci					CS35L35_CH_VP_RATE_MASK,
9558c2ecf20Sopenharmony_ci					classh->classh_vpch_rate <<
9568c2ecf20Sopenharmony_ci					CS35L35_CH_VP_RATE_SHIFT);
9578c2ecf20Sopenharmony_ci		if (classh->classh_vpch_man)
9588c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9598c2ecf20Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
9608c2ecf20Sopenharmony_ci					CS35L35_CH_VP_MAN_MASK,
9618c2ecf20Sopenharmony_ci					classh->classh_vpch_man <<
9628c2ecf20Sopenharmony_ci					CS35L35_CH_VP_MAN_SHIFT);
9638c2ecf20Sopenharmony_ci	}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	if (monitor_config->is_present) {
9668c2ecf20Sopenharmony_ci		if (monitor_config->vmon_specs) {
9678c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9688c2ecf20Sopenharmony_ci					CS35L35_SPKMON_DEPTH_CTL,
9698c2ecf20Sopenharmony_ci					CS35L35_VMON_DEPTH_MASK,
9708c2ecf20Sopenharmony_ci					monitor_config->vmon_dpth <<
9718c2ecf20Sopenharmony_ci					CS35L35_VMON_DEPTH_SHIFT);
9728c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9738c2ecf20Sopenharmony_ci					CS35L35_VMON_TXLOC_CTL,
9748c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
9758c2ecf20Sopenharmony_ci					monitor_config->vmon_loc <<
9768c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
9778c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9788c2ecf20Sopenharmony_ci					CS35L35_VMON_TXLOC_CTL,
9798c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
9808c2ecf20Sopenharmony_ci					monitor_config->vmon_frm <<
9818c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
9828c2ecf20Sopenharmony_ci		}
9838c2ecf20Sopenharmony_ci		if (monitor_config->imon_specs) {
9848c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9858c2ecf20Sopenharmony_ci					CS35L35_SPKMON_DEPTH_CTL,
9868c2ecf20Sopenharmony_ci					CS35L35_IMON_DEPTH_MASK,
9878c2ecf20Sopenharmony_ci					monitor_config->imon_dpth <<
9888c2ecf20Sopenharmony_ci					CS35L35_IMON_DEPTH_SHIFT);
9898c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9908c2ecf20Sopenharmony_ci					CS35L35_IMON_TXLOC_CTL,
9918c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
9928c2ecf20Sopenharmony_ci					monitor_config->imon_loc <<
9938c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
9948c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
9958c2ecf20Sopenharmony_ci					CS35L35_IMON_TXLOC_CTL,
9968c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
9978c2ecf20Sopenharmony_ci					monitor_config->imon_frm <<
9988c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
9998c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10008c2ecf20Sopenharmony_ci					CS35L35_IMON_SCALE_CTL,
10018c2ecf20Sopenharmony_ci					CS35L35_IMON_SCALE_MASK,
10028c2ecf20Sopenharmony_ci					monitor_config->imon_scale <<
10038c2ecf20Sopenharmony_ci					CS35L35_IMON_SCALE_SHIFT);
10048c2ecf20Sopenharmony_ci		}
10058c2ecf20Sopenharmony_ci		if (monitor_config->vpmon_specs) {
10068c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10078c2ecf20Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
10088c2ecf20Sopenharmony_ci					CS35L35_VPMON_DEPTH_MASK,
10098c2ecf20Sopenharmony_ci					monitor_config->vpmon_dpth <<
10108c2ecf20Sopenharmony_ci					CS35L35_VPMON_DEPTH_SHIFT);
10118c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10128c2ecf20Sopenharmony_ci					CS35L35_VPMON_TXLOC_CTL,
10138c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
10148c2ecf20Sopenharmony_ci					monitor_config->vpmon_loc <<
10158c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
10168c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10178c2ecf20Sopenharmony_ci					CS35L35_VPMON_TXLOC_CTL,
10188c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
10198c2ecf20Sopenharmony_ci					monitor_config->vpmon_frm <<
10208c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
10218c2ecf20Sopenharmony_ci		}
10228c2ecf20Sopenharmony_ci		if (monitor_config->vbstmon_specs) {
10238c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10248c2ecf20Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
10258c2ecf20Sopenharmony_ci					CS35L35_VBSTMON_DEPTH_MASK,
10268c2ecf20Sopenharmony_ci					monitor_config->vpmon_dpth <<
10278c2ecf20Sopenharmony_ci					CS35L35_VBSTMON_DEPTH_SHIFT);
10288c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10298c2ecf20Sopenharmony_ci					CS35L35_VBSTMON_TXLOC_CTL,
10308c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
10318c2ecf20Sopenharmony_ci					monitor_config->vbstmon_loc <<
10328c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
10338c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10348c2ecf20Sopenharmony_ci					CS35L35_VBSTMON_TXLOC_CTL,
10358c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
10368c2ecf20Sopenharmony_ci					monitor_config->vbstmon_frm <<
10378c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
10388c2ecf20Sopenharmony_ci		}
10398c2ecf20Sopenharmony_ci		if (monitor_config->vpbrstat_specs) {
10408c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10418c2ecf20Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
10428c2ecf20Sopenharmony_ci					CS35L35_VPBRSTAT_DEPTH_MASK,
10438c2ecf20Sopenharmony_ci					monitor_config->vpbrstat_dpth <<
10448c2ecf20Sopenharmony_ci					CS35L35_VPBRSTAT_DEPTH_SHIFT);
10458c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10468c2ecf20Sopenharmony_ci					CS35L35_VPBR_STATUS_TXLOC_CTL,
10478c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
10488c2ecf20Sopenharmony_ci					monitor_config->vpbrstat_loc <<
10498c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
10508c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10518c2ecf20Sopenharmony_ci					CS35L35_VPBR_STATUS_TXLOC_CTL,
10528c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
10538c2ecf20Sopenharmony_ci					monitor_config->vpbrstat_frm <<
10548c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
10558c2ecf20Sopenharmony_ci		}
10568c2ecf20Sopenharmony_ci		if (monitor_config->zerofill_specs) {
10578c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10588c2ecf20Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
10598c2ecf20Sopenharmony_ci					CS35L35_ZEROFILL_DEPTH_MASK,
10608c2ecf20Sopenharmony_ci					monitor_config->zerofill_dpth <<
10618c2ecf20Sopenharmony_ci					CS35L35_ZEROFILL_DEPTH_SHIFT);
10628c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10638c2ecf20Sopenharmony_ci					CS35L35_ZERO_FILL_LOC_CTL,
10648c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
10658c2ecf20Sopenharmony_ci					monitor_config->zerofill_loc <<
10668c2ecf20Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
10678c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
10688c2ecf20Sopenharmony_ci					CS35L35_ZERO_FILL_LOC_CTL,
10698c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_MASK,
10708c2ecf20Sopenharmony_ci					monitor_config->zerofill_frm <<
10718c2ecf20Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
10728c2ecf20Sopenharmony_ci		}
10738c2ecf20Sopenharmony_ci	}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	return 0;
10768c2ecf20Sopenharmony_ci}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_cs35l35 = {
10798c2ecf20Sopenharmony_ci	.probe			= cs35l35_component_probe,
10808c2ecf20Sopenharmony_ci	.set_sysclk		= cs35l35_component_set_sysclk,
10818c2ecf20Sopenharmony_ci	.dapm_widgets		= cs35l35_dapm_widgets,
10828c2ecf20Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(cs35l35_dapm_widgets),
10838c2ecf20Sopenharmony_ci	.dapm_routes		= cs35l35_audio_map,
10848c2ecf20Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(cs35l35_audio_map),
10858c2ecf20Sopenharmony_ci	.controls		= cs35l35_aud_controls,
10868c2ecf20Sopenharmony_ci	.num_controls		= ARRAY_SIZE(cs35l35_aud_controls),
10878c2ecf20Sopenharmony_ci	.idle_bias_on		= 1,
10888c2ecf20Sopenharmony_ci	.use_pmdown_time	= 1,
10898c2ecf20Sopenharmony_ci	.endianness		= 1,
10908c2ecf20Sopenharmony_ci	.non_legacy_dai_naming	= 1,
10918c2ecf20Sopenharmony_ci};
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_cistatic struct regmap_config cs35l35_regmap = {
10948c2ecf20Sopenharmony_ci	.reg_bits = 8,
10958c2ecf20Sopenharmony_ci	.val_bits = 8,
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	.max_register = CS35L35_MAX_REGISTER,
10988c2ecf20Sopenharmony_ci	.reg_defaults = cs35l35_reg,
10998c2ecf20Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(cs35l35_reg),
11008c2ecf20Sopenharmony_ci	.volatile_reg = cs35l35_volatile_register,
11018c2ecf20Sopenharmony_ci	.readable_reg = cs35l35_readable_register,
11028c2ecf20Sopenharmony_ci	.precious_reg = cs35l35_precious_register,
11038c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
11048c2ecf20Sopenharmony_ci	.use_single_read = true,
11058c2ecf20Sopenharmony_ci	.use_single_write = true,
11068c2ecf20Sopenharmony_ci};
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_cistatic irqreturn_t cs35l35_irq(int irq, void *data)
11098c2ecf20Sopenharmony_ci{
11108c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = data;
11118c2ecf20Sopenharmony_ci	unsigned int sticky1, sticky2, sticky3, sticky4;
11128c2ecf20Sopenharmony_ci	unsigned int mask1, mask2, mask3, mask4, current1;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	/* ack the irq by reading all status registers */
11158c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_4, &sticky4);
11168c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_3, &sticky3);
11178c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_2, &sticky2);
11188c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, &sticky1);
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_4, &mask4);
11218c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_3, &mask3);
11228c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_2, &mask2);
11238c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_1, &mask1);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	/* Check to see if unmasked bits are active */
11268c2ecf20Sopenharmony_ci	if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3)
11278c2ecf20Sopenharmony_ci			&& !(sticky4 & ~mask4))
11288c2ecf20Sopenharmony_ci		return IRQ_NONE;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	if (sticky2 & CS35L35_PDN_DONE)
11318c2ecf20Sopenharmony_ci		complete(&cs35l35->pdn_done);
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	/* read the current values */
11348c2ecf20Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, &current1);
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	/* handle the interrupts */
11378c2ecf20Sopenharmony_ci	if (sticky1 & CS35L35_CAL_ERR) {
11388c2ecf20Sopenharmony_ci		dev_crit(cs35l35->dev, "Calibration Error\n");
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci		/* error is no longer asserted; safe to reset */
11418c2ecf20Sopenharmony_ci		if (!(current1 & CS35L35_CAL_ERR)) {
11428c2ecf20Sopenharmony_ci			pr_debug("%s : Cal error release\n", __func__);
11438c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11448c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11458c2ecf20Sopenharmony_ci					CS35L35_CAL_ERR_RLS, 0);
11468c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11478c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11488c2ecf20Sopenharmony_ci					CS35L35_CAL_ERR_RLS,
11498c2ecf20Sopenharmony_ci					CS35L35_CAL_ERR_RLS);
11508c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11518c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11528c2ecf20Sopenharmony_ci					CS35L35_CAL_ERR_RLS, 0);
11538c2ecf20Sopenharmony_ci		}
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	if (sticky1 & CS35L35_AMP_SHORT) {
11578c2ecf20Sopenharmony_ci		dev_crit(cs35l35->dev, "AMP Short Error\n");
11588c2ecf20Sopenharmony_ci		/* error is no longer asserted; safe to reset */
11598c2ecf20Sopenharmony_ci		if (!(current1 & CS35L35_AMP_SHORT)) {
11608c2ecf20Sopenharmony_ci			dev_dbg(cs35l35->dev, "Amp short error release\n");
11618c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11628c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11638c2ecf20Sopenharmony_ci					CS35L35_SHORT_RLS, 0);
11648c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11658c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11668c2ecf20Sopenharmony_ci					CS35L35_SHORT_RLS,
11678c2ecf20Sopenharmony_ci					CS35L35_SHORT_RLS);
11688c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11698c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11708c2ecf20Sopenharmony_ci					CS35L35_SHORT_RLS, 0);
11718c2ecf20Sopenharmony_ci		}
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	if (sticky1 & CS35L35_OTW) {
11758c2ecf20Sopenharmony_ci		dev_warn(cs35l35->dev, "Over temperature warning\n");
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci		/* error is no longer asserted; safe to reset */
11788c2ecf20Sopenharmony_ci		if (!(current1 & CS35L35_OTW)) {
11798c2ecf20Sopenharmony_ci			dev_dbg(cs35l35->dev, "Over temperature warn release\n");
11808c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11818c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11828c2ecf20Sopenharmony_ci					CS35L35_OTW_RLS, 0);
11838c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11848c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11858c2ecf20Sopenharmony_ci					CS35L35_OTW_RLS,
11868c2ecf20Sopenharmony_ci					CS35L35_OTW_RLS);
11878c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11888c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
11898c2ecf20Sopenharmony_ci					CS35L35_OTW_RLS, 0);
11908c2ecf20Sopenharmony_ci		}
11918c2ecf20Sopenharmony_ci	}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	if (sticky1 & CS35L35_OTE) {
11948c2ecf20Sopenharmony_ci		dev_crit(cs35l35->dev, "Over temperature error\n");
11958c2ecf20Sopenharmony_ci		/* error is no longer asserted; safe to reset */
11968c2ecf20Sopenharmony_ci		if (!(current1 & CS35L35_OTE)) {
11978c2ecf20Sopenharmony_ci			dev_dbg(cs35l35->dev, "Over temperature error release\n");
11988c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
11998c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
12008c2ecf20Sopenharmony_ci					CS35L35_OTE_RLS, 0);
12018c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
12028c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
12038c2ecf20Sopenharmony_ci					CS35L35_OTE_RLS,
12048c2ecf20Sopenharmony_ci					CS35L35_OTE_RLS);
12058c2ecf20Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
12068c2ecf20Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
12078c2ecf20Sopenharmony_ci					CS35L35_OTE_RLS, 0);
12088c2ecf20Sopenharmony_ci		}
12098c2ecf20Sopenharmony_ci	}
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	if (sticky3 & CS35L35_BST_HIGH) {
12128c2ecf20Sopenharmony_ci		dev_crit(cs35l35->dev, "VBST error: powering off!\n");
12138c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
12148c2ecf20Sopenharmony_ci			CS35L35_PDN_AMP, CS35L35_PDN_AMP);
12158c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
12168c2ecf20Sopenharmony_ci			CS35L35_PDN_ALL, CS35L35_PDN_ALL);
12178c2ecf20Sopenharmony_ci	}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (sticky3 & CS35L35_LBST_SHORT) {
12208c2ecf20Sopenharmony_ci		dev_crit(cs35l35->dev, "LBST error: powering off!\n");
12218c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
12228c2ecf20Sopenharmony_ci			CS35L35_PDN_AMP, CS35L35_PDN_AMP);
12238c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
12248c2ecf20Sopenharmony_ci			CS35L35_PDN_ALL, CS35L35_PDN_ALL);
12258c2ecf20Sopenharmony_ci	}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	if (sticky2 & CS35L35_VPBR_ERR)
12288c2ecf20Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: Reactive Brownout\n");
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (sticky4 & CS35L35_VMON_OVFL)
12318c2ecf20Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: VMON overflow\n");
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	if (sticky4 & CS35L35_IMON_OVFL)
12348c2ecf20Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: IMON overflow\n");
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic int cs35l35_handle_of_data(struct i2c_client *i2c_client,
12418c2ecf20Sopenharmony_ci				struct cs35l35_platform_data *pdata)
12428c2ecf20Sopenharmony_ci{
12438c2ecf20Sopenharmony_ci	struct device_node *np = i2c_client->dev.of_node;
12448c2ecf20Sopenharmony_ci	struct device_node *classh, *signal_format;
12458c2ecf20Sopenharmony_ci	struct classh_cfg *classh_config = &pdata->classh_algo;
12468c2ecf20Sopenharmony_ci	struct monitor_cfg *monitor_config = &pdata->mon_cfg;
12478c2ecf20Sopenharmony_ci	unsigned int val32 = 0;
12488c2ecf20Sopenharmony_ci	u8 monitor_array[4];
12498c2ecf20Sopenharmony_ci	const int imon_array_size = ARRAY_SIZE(monitor_array);
12508c2ecf20Sopenharmony_ci	const int mon_array_size = imon_array_size - 1;
12518c2ecf20Sopenharmony_ci	int ret = 0;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	if (!np)
12548c2ecf20Sopenharmony_ci		return 0;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	pdata->bst_pdn_fet_on = of_property_read_bool(np,
12578c2ecf20Sopenharmony_ci					"cirrus,boost-pdn-fet-on");
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ctl-millivolt", &val32);
12608c2ecf20Sopenharmony_ci	if (ret >= 0) {
12618c2ecf20Sopenharmony_ci		if (val32 < 2600 || val32 > 9000) {
12628c2ecf20Sopenharmony_ci			dev_err(&i2c_client->dev,
12638c2ecf20Sopenharmony_ci				"Invalid Boost Voltage %d mV\n", val32);
12648c2ecf20Sopenharmony_ci			return -EINVAL;
12658c2ecf20Sopenharmony_ci		}
12668c2ecf20Sopenharmony_ci		pdata->bst_vctl = ((val32 - 2600) / 100) + 1;
12678c2ecf20Sopenharmony_ci	}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val32);
12708c2ecf20Sopenharmony_ci	if (ret >= 0) {
12718c2ecf20Sopenharmony_ci		if (val32 < 1680 || val32 > 4480) {
12728c2ecf20Sopenharmony_ci			dev_err(&i2c_client->dev,
12738c2ecf20Sopenharmony_ci				"Invalid Boost Peak Current %u mA\n", val32);
12748c2ecf20Sopenharmony_ci			return -EINVAL;
12758c2ecf20Sopenharmony_ci		}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci		pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA;
12788c2ecf20Sopenharmony_ci	}
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);
12818c2ecf20Sopenharmony_ci	if (ret >= 0) {
12828c2ecf20Sopenharmony_ci		pdata->boost_ind = val32;
12838c2ecf20Sopenharmony_ci	} else {
12848c2ecf20Sopenharmony_ci		dev_err(&i2c_client->dev, "Inductor not specified.\n");
12858c2ecf20Sopenharmony_ci		return -EINVAL;
12868c2ecf20Sopenharmony_ci	}
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)
12898c2ecf20Sopenharmony_ci		pdata->sp_drv_str = val32;
12908c2ecf20Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0)
12918c2ecf20Sopenharmony_ci		pdata->sp_drv_unused = val32 | CS35L35_VALID_PDATA;
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	pdata->stereo = of_property_read_bool(np, "cirrus,stereo-config");
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	if (pdata->stereo) {
12968c2ecf20Sopenharmony_ci		ret = of_property_read_u32(np, "cirrus,audio-channel", &val32);
12978c2ecf20Sopenharmony_ci		if (ret >= 0)
12988c2ecf20Sopenharmony_ci			pdata->aud_channel = val32;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci		ret = of_property_read_u32(np, "cirrus,advisory-channel",
13018c2ecf20Sopenharmony_ci					   &val32);
13028c2ecf20Sopenharmony_ci		if (ret >= 0)
13038c2ecf20Sopenharmony_ci			pdata->adv_channel = val32;
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci		pdata->shared_bst = of_property_read_bool(np,
13068c2ecf20Sopenharmony_ci						"cirrus,shared-boost");
13078c2ecf20Sopenharmony_ci	}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	pdata->ext_bst = of_property_read_bool(np, "cirrus,external-boost");
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	pdata->gain_zc = of_property_read_bool(np, "cirrus,amp-gain-zc");
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	classh = of_get_child_by_name(np, "cirrus,classh-internal-algo");
13148c2ecf20Sopenharmony_ci	classh_config->classh_algo_enable = classh ? true : false;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	if (classh_config->classh_algo_enable) {
13178c2ecf20Sopenharmony_ci		classh_config->classh_bst_override =
13188c2ecf20Sopenharmony_ci			of_property_read_bool(np, "cirrus,classh-bst-overide");
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh,
13218c2ecf20Sopenharmony_ci					   "cirrus,classh-bst-max-limit",
13228c2ecf20Sopenharmony_ci					   &val32);
13238c2ecf20Sopenharmony_ci		if (ret >= 0) {
13248c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13258c2ecf20Sopenharmony_ci			classh_config->classh_bst_max_limit = val32;
13268c2ecf20Sopenharmony_ci		}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh,
13298c2ecf20Sopenharmony_ci					   "cirrus,classh-bst-max-limit",
13308c2ecf20Sopenharmony_ci					   &val32);
13318c2ecf20Sopenharmony_ci		if (ret >= 0) {
13328c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13338c2ecf20Sopenharmony_ci			classh_config->classh_bst_max_limit = val32;
13348c2ecf20Sopenharmony_ci		}
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-mem-depth",
13378c2ecf20Sopenharmony_ci					   &val32);
13388c2ecf20Sopenharmony_ci		if (ret >= 0) {
13398c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13408c2ecf20Sopenharmony_ci			classh_config->classh_mem_depth = val32;
13418c2ecf20Sopenharmony_ci		}
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-release-rate",
13448c2ecf20Sopenharmony_ci					   &val32);
13458c2ecf20Sopenharmony_ci		if (ret >= 0)
13468c2ecf20Sopenharmony_ci			classh_config->classh_release_rate = val32;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-headroom",
13498c2ecf20Sopenharmony_ci					   &val32);
13508c2ecf20Sopenharmony_ci		if (ret >= 0) {
13518c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13528c2ecf20Sopenharmony_ci			classh_config->classh_headroom = val32;
13538c2ecf20Sopenharmony_ci		}
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh,
13568c2ecf20Sopenharmony_ci					   "cirrus,classh-wk-fet-disable",
13578c2ecf20Sopenharmony_ci					   &val32);
13588c2ecf20Sopenharmony_ci		if (ret >= 0)
13598c2ecf20Sopenharmony_ci			classh_config->classh_wk_fet_disable = val32;
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-delay",
13628c2ecf20Sopenharmony_ci					   &val32);
13638c2ecf20Sopenharmony_ci		if (ret >= 0) {
13648c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13658c2ecf20Sopenharmony_ci			classh_config->classh_wk_fet_delay = val32;
13668c2ecf20Sopenharmony_ci		}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-thld",
13698c2ecf20Sopenharmony_ci					   &val32);
13708c2ecf20Sopenharmony_ci		if (ret >= 0)
13718c2ecf20Sopenharmony_ci			classh_config->classh_wk_fet_thld = val32;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-auto",
13748c2ecf20Sopenharmony_ci					   &val32);
13758c2ecf20Sopenharmony_ci		if (ret >= 0) {
13768c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13778c2ecf20Sopenharmony_ci			classh_config->classh_vpch_auto = val32;
13788c2ecf20Sopenharmony_ci		}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-rate",
13818c2ecf20Sopenharmony_ci					   &val32);
13828c2ecf20Sopenharmony_ci		if (ret >= 0) {
13838c2ecf20Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
13848c2ecf20Sopenharmony_ci			classh_config->classh_vpch_rate = val32;
13858c2ecf20Sopenharmony_ci		}
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-man",
13888c2ecf20Sopenharmony_ci					   &val32);
13898c2ecf20Sopenharmony_ci		if (ret >= 0)
13908c2ecf20Sopenharmony_ci			classh_config->classh_vpch_man = val32;
13918c2ecf20Sopenharmony_ci	}
13928c2ecf20Sopenharmony_ci	of_node_put(classh);
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	/* frame depth location */
13958c2ecf20Sopenharmony_ci	signal_format = of_get_child_by_name(np, "cirrus,monitor-signal-format");
13968c2ecf20Sopenharmony_ci	monitor_config->is_present = signal_format ? true : false;
13978c2ecf20Sopenharmony_ci	if (monitor_config->is_present) {
13988c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,imon",
13998c2ecf20Sopenharmony_ci						monitor_array, imon_array_size);
14008c2ecf20Sopenharmony_ci		if (!ret) {
14018c2ecf20Sopenharmony_ci			monitor_config->imon_specs = true;
14028c2ecf20Sopenharmony_ci			monitor_config->imon_dpth = monitor_array[0];
14038c2ecf20Sopenharmony_ci			monitor_config->imon_loc = monitor_array[1];
14048c2ecf20Sopenharmony_ci			monitor_config->imon_frm = monitor_array[2];
14058c2ecf20Sopenharmony_ci			monitor_config->imon_scale = monitor_array[3];
14068c2ecf20Sopenharmony_ci		}
14078c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vmon",
14088c2ecf20Sopenharmony_ci						monitor_array, mon_array_size);
14098c2ecf20Sopenharmony_ci		if (!ret) {
14108c2ecf20Sopenharmony_ci			monitor_config->vmon_specs = true;
14118c2ecf20Sopenharmony_ci			monitor_config->vmon_dpth = monitor_array[0];
14128c2ecf20Sopenharmony_ci			monitor_config->vmon_loc = monitor_array[1];
14138c2ecf20Sopenharmony_ci			monitor_config->vmon_frm = monitor_array[2];
14148c2ecf20Sopenharmony_ci		}
14158c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vpmon",
14168c2ecf20Sopenharmony_ci						monitor_array, mon_array_size);
14178c2ecf20Sopenharmony_ci		if (!ret) {
14188c2ecf20Sopenharmony_ci			monitor_config->vpmon_specs = true;
14198c2ecf20Sopenharmony_ci			monitor_config->vpmon_dpth = monitor_array[0];
14208c2ecf20Sopenharmony_ci			monitor_config->vpmon_loc = monitor_array[1];
14218c2ecf20Sopenharmony_ci			monitor_config->vpmon_frm = monitor_array[2];
14228c2ecf20Sopenharmony_ci		}
14238c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vbstmon",
14248c2ecf20Sopenharmony_ci						monitor_array, mon_array_size);
14258c2ecf20Sopenharmony_ci		if (!ret) {
14268c2ecf20Sopenharmony_ci			monitor_config->vbstmon_specs = true;
14278c2ecf20Sopenharmony_ci			monitor_config->vbstmon_dpth = monitor_array[0];
14288c2ecf20Sopenharmony_ci			monitor_config->vbstmon_loc = monitor_array[1];
14298c2ecf20Sopenharmony_ci			monitor_config->vbstmon_frm = monitor_array[2];
14308c2ecf20Sopenharmony_ci		}
14318c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vpbrstat",
14328c2ecf20Sopenharmony_ci						monitor_array, mon_array_size);
14338c2ecf20Sopenharmony_ci		if (!ret) {
14348c2ecf20Sopenharmony_ci			monitor_config->vpbrstat_specs = true;
14358c2ecf20Sopenharmony_ci			monitor_config->vpbrstat_dpth = monitor_array[0];
14368c2ecf20Sopenharmony_ci			monitor_config->vpbrstat_loc = monitor_array[1];
14378c2ecf20Sopenharmony_ci			monitor_config->vpbrstat_frm = monitor_array[2];
14388c2ecf20Sopenharmony_ci		}
14398c2ecf20Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,zerofill",
14408c2ecf20Sopenharmony_ci						monitor_array, mon_array_size);
14418c2ecf20Sopenharmony_ci		if (!ret) {
14428c2ecf20Sopenharmony_ci			monitor_config->zerofill_specs = true;
14438c2ecf20Sopenharmony_ci			monitor_config->zerofill_dpth = monitor_array[0];
14448c2ecf20Sopenharmony_ci			monitor_config->zerofill_loc = monitor_array[1];
14458c2ecf20Sopenharmony_ci			monitor_config->zerofill_frm = monitor_array[2];
14468c2ecf20Sopenharmony_ci		}
14478c2ecf20Sopenharmony_ci	}
14488c2ecf20Sopenharmony_ci	of_node_put(signal_format);
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	return 0;
14518c2ecf20Sopenharmony_ci}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci/* Errata Rev A0 */
14548c2ecf20Sopenharmony_cistatic const struct reg_sequence cs35l35_errata_patch[] = {
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	{ 0x7F, 0x99 },
14578c2ecf20Sopenharmony_ci	{ 0x00, 0x99 },
14588c2ecf20Sopenharmony_ci	{ 0x52, 0x22 },
14598c2ecf20Sopenharmony_ci	{ 0x04, 0x14 },
14608c2ecf20Sopenharmony_ci	{ 0x6D, 0x44 },
14618c2ecf20Sopenharmony_ci	{ 0x24, 0x10 },
14628c2ecf20Sopenharmony_ci	{ 0x58, 0xC4 },
14638c2ecf20Sopenharmony_ci	{ 0x00, 0x98 },
14648c2ecf20Sopenharmony_ci	{ 0x18, 0x08 },
14658c2ecf20Sopenharmony_ci	{ 0x00, 0x00 },
14668c2ecf20Sopenharmony_ci	{ 0x7F, 0x00 },
14678c2ecf20Sopenharmony_ci};
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_cistatic int cs35l35_i2c_probe(struct i2c_client *i2c_client,
14708c2ecf20Sopenharmony_ci			      const struct i2c_device_id *id)
14718c2ecf20Sopenharmony_ci{
14728c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35;
14738c2ecf20Sopenharmony_ci	struct device *dev = &i2c_client->dev;
14748c2ecf20Sopenharmony_ci	struct cs35l35_platform_data *pdata = dev_get_platdata(dev);
14758c2ecf20Sopenharmony_ci	int i;
14768c2ecf20Sopenharmony_ci	int ret;
14778c2ecf20Sopenharmony_ci	unsigned int devid = 0;
14788c2ecf20Sopenharmony_ci	unsigned int reg;
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	cs35l35 = devm_kzalloc(dev, sizeof(struct cs35l35_private), GFP_KERNEL);
14818c2ecf20Sopenharmony_ci	if (!cs35l35)
14828c2ecf20Sopenharmony_ci		return -ENOMEM;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	cs35l35->dev = dev;
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	i2c_set_clientdata(i2c_client, cs35l35);
14878c2ecf20Sopenharmony_ci	cs35l35->regmap = devm_regmap_init_i2c(i2c_client, &cs35l35_regmap);
14888c2ecf20Sopenharmony_ci	if (IS_ERR(cs35l35->regmap)) {
14898c2ecf20Sopenharmony_ci		ret = PTR_ERR(cs35l35->regmap);
14908c2ecf20Sopenharmony_ci		dev_err(dev, "regmap_init() failed: %d\n", ret);
14918c2ecf20Sopenharmony_ci		goto err;
14928c2ecf20Sopenharmony_ci	}
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l35_supplies); i++)
14958c2ecf20Sopenharmony_ci		cs35l35->supplies[i].supply = cs35l35_supplies[i];
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	cs35l35->num_supplies = ARRAY_SIZE(cs35l35_supplies);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	ret = devm_regulator_bulk_get(dev, cs35l35->num_supplies,
15008c2ecf20Sopenharmony_ci				      cs35l35->supplies);
15018c2ecf20Sopenharmony_ci	if (ret != 0) {
15028c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request core supplies: %d\n", ret);
15038c2ecf20Sopenharmony_ci		return ret;
15048c2ecf20Sopenharmony_ci	}
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	if (pdata) {
15078c2ecf20Sopenharmony_ci		cs35l35->pdata = *pdata;
15088c2ecf20Sopenharmony_ci	} else {
15098c2ecf20Sopenharmony_ci		pdata = devm_kzalloc(dev, sizeof(struct cs35l35_platform_data),
15108c2ecf20Sopenharmony_ci				     GFP_KERNEL);
15118c2ecf20Sopenharmony_ci		if (!pdata)
15128c2ecf20Sopenharmony_ci			return -ENOMEM;
15138c2ecf20Sopenharmony_ci		if (i2c_client->dev.of_node) {
15148c2ecf20Sopenharmony_ci			ret = cs35l35_handle_of_data(i2c_client, pdata);
15158c2ecf20Sopenharmony_ci			if (ret != 0)
15168c2ecf20Sopenharmony_ci				return ret;
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci		}
15198c2ecf20Sopenharmony_ci		cs35l35->pdata = *pdata;
15208c2ecf20Sopenharmony_ci	}
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	ret = regulator_bulk_enable(cs35l35->num_supplies,
15238c2ecf20Sopenharmony_ci					cs35l35->supplies);
15248c2ecf20Sopenharmony_ci	if (ret != 0) {
15258c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable core supplies: %d\n", ret);
15268c2ecf20Sopenharmony_ci		return ret;
15278c2ecf20Sopenharmony_ci	}
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	/* returning NULL can be valid if in stereo mode */
15308c2ecf20Sopenharmony_ci	cs35l35->reset_gpio = devm_gpiod_get_optional(dev, "reset",
15318c2ecf20Sopenharmony_ci						      GPIOD_OUT_LOW);
15328c2ecf20Sopenharmony_ci	if (IS_ERR(cs35l35->reset_gpio)) {
15338c2ecf20Sopenharmony_ci		ret = PTR_ERR(cs35l35->reset_gpio);
15348c2ecf20Sopenharmony_ci		cs35l35->reset_gpio = NULL;
15358c2ecf20Sopenharmony_ci		if (ret == -EBUSY) {
15368c2ecf20Sopenharmony_ci			dev_info(dev,
15378c2ecf20Sopenharmony_ci				 "Reset line busy, assuming shared reset\n");
15388c2ecf20Sopenharmony_ci		} else {
15398c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to get reset GPIO: %d\n", ret);
15408c2ecf20Sopenharmony_ci			goto err;
15418c2ecf20Sopenharmony_ci		}
15428c2ecf20Sopenharmony_ci	}
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	cs35l35_reset(cs35l35);
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	init_completion(&cs35l35->pdn_done);
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(dev, i2c_client->irq, NULL, cs35l35_irq,
15498c2ecf20Sopenharmony_ci					IRQF_ONESHOT | IRQF_TRIGGER_LOW |
15508c2ecf20Sopenharmony_ci					IRQF_SHARED, "cs35l35", cs35l35);
15518c2ecf20Sopenharmony_ci	if (ret != 0) {
15528c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request IRQ: %d\n", ret);
15538c2ecf20Sopenharmony_ci		goto err;
15548c2ecf20Sopenharmony_ci	}
15558c2ecf20Sopenharmony_ci	/* initialize codec */
15568c2ecf20Sopenharmony_ci	ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_AB, &reg);
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	devid = (reg & 0xFF) << 12;
15598c2ecf20Sopenharmony_ci	ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_CD, &reg);
15608c2ecf20Sopenharmony_ci	devid |= (reg & 0xFF) << 4;
15618c2ecf20Sopenharmony_ci	ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_E, &reg);
15628c2ecf20Sopenharmony_ci	devid |= (reg & 0xF0) >> 4;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	if (devid != CS35L35_CHIP_ID) {
15658c2ecf20Sopenharmony_ci		dev_err(dev, "CS35L35 Device ID (%X). Expected ID %X\n",
15668c2ecf20Sopenharmony_ci			devid, CS35L35_CHIP_ID);
15678c2ecf20Sopenharmony_ci		ret = -ENODEV;
15688c2ecf20Sopenharmony_ci		goto err;
15698c2ecf20Sopenharmony_ci	}
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	ret = regmap_read(cs35l35->regmap, CS35L35_REV_ID, &reg);
15728c2ecf20Sopenharmony_ci	if (ret < 0) {
15738c2ecf20Sopenharmony_ci		dev_err(dev, "Get Revision ID failed: %d\n", ret);
15748c2ecf20Sopenharmony_ci		goto err;
15758c2ecf20Sopenharmony_ci	}
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	ret = regmap_register_patch(cs35l35->regmap, cs35l35_errata_patch,
15788c2ecf20Sopenharmony_ci				    ARRAY_SIZE(cs35l35_errata_patch));
15798c2ecf20Sopenharmony_ci	if (ret < 0) {
15808c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to apply errata patch: %d\n", ret);
15818c2ecf20Sopenharmony_ci		goto err;
15828c2ecf20Sopenharmony_ci	}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	dev_info(dev, "Cirrus Logic CS35L35 (%x), Revision: %02X\n",
15858c2ecf20Sopenharmony_ci		 devid, reg & 0xFF);
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	/* Set the INT Masks for critical errors */
15888c2ecf20Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_1,
15898c2ecf20Sopenharmony_ci				CS35L35_INT1_CRIT_MASK);
15908c2ecf20Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_2,
15918c2ecf20Sopenharmony_ci				CS35L35_INT2_CRIT_MASK);
15928c2ecf20Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_3,
15938c2ecf20Sopenharmony_ci				CS35L35_INT3_CRIT_MASK);
15948c2ecf20Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_4,
15958c2ecf20Sopenharmony_ci				CS35L35_INT4_CRIT_MASK);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
15988c2ecf20Sopenharmony_ci			CS35L35_PWR2_PDN_MASK,
15998c2ecf20Sopenharmony_ci			CS35L35_PWR2_PDN_MASK);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	if (cs35l35->pdata.bst_pdn_fet_on)
16028c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
16038c2ecf20Sopenharmony_ci					CS35L35_PDN_BST_MASK,
16048c2ecf20Sopenharmony_ci					1 << CS35L35_PDN_BST_FETON_SHIFT);
16058c2ecf20Sopenharmony_ci	else
16068c2ecf20Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
16078c2ecf20Sopenharmony_ci					CS35L35_PDN_BST_MASK,
16088c2ecf20Sopenharmony_ci					1 << CS35L35_PDN_BST_FETOFF_SHIFT);
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL3,
16118c2ecf20Sopenharmony_ci			CS35L35_PWR3_PDN_MASK,
16128c2ecf20Sopenharmony_ci			CS35L35_PWR3_PDN_MASK);
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
16158c2ecf20Sopenharmony_ci		CS35L35_AMP_MUTE_MASK, 1 << CS35L35_AMP_MUTE_SHIFT);
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	ret = devm_snd_soc_register_component(dev, &soc_component_dev_cs35l35,
16188c2ecf20Sopenharmony_ci					cs35l35_dai, ARRAY_SIZE(cs35l35_dai));
16198c2ecf20Sopenharmony_ci	if (ret < 0) {
16208c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to register component: %d\n", ret);
16218c2ecf20Sopenharmony_ci		goto err;
16228c2ecf20Sopenharmony_ci	}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	return 0;
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_cierr:
16278c2ecf20Sopenharmony_ci	regulator_bulk_disable(cs35l35->num_supplies,
16288c2ecf20Sopenharmony_ci			       cs35l35->supplies);
16298c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	return ret;
16328c2ecf20Sopenharmony_ci}
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_cistatic int cs35l35_i2c_remove(struct i2c_client *i2c_client)
16358c2ecf20Sopenharmony_ci{
16368c2ecf20Sopenharmony_ci	struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client);
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies);
16398c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	return 0;
16428c2ecf20Sopenharmony_ci}
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_cistatic const struct of_device_id cs35l35_of_match[] = {
16458c2ecf20Sopenharmony_ci	{.compatible = "cirrus,cs35l35"},
16468c2ecf20Sopenharmony_ci	{},
16478c2ecf20Sopenharmony_ci};
16488c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, cs35l35_of_match);
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_cistatic const struct i2c_device_id cs35l35_id[] = {
16518c2ecf20Sopenharmony_ci	{"cs35l35", 0},
16528c2ecf20Sopenharmony_ci	{}
16538c2ecf20Sopenharmony_ci};
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, cs35l35_id);
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_cistatic struct i2c_driver cs35l35_i2c_driver = {
16588c2ecf20Sopenharmony_ci	.driver = {
16598c2ecf20Sopenharmony_ci		.name = "cs35l35",
16608c2ecf20Sopenharmony_ci		.of_match_table = cs35l35_of_match,
16618c2ecf20Sopenharmony_ci	},
16628c2ecf20Sopenharmony_ci	.id_table = cs35l35_id,
16638c2ecf20Sopenharmony_ci	.probe = cs35l35_i2c_probe,
16648c2ecf20Sopenharmony_ci	.remove = cs35l35_i2c_remove,
16658c2ecf20Sopenharmony_ci};
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_cimodule_i2c_driver(cs35l35_i2c_driver);
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC CS35L35 driver");
16708c2ecf20Sopenharmony_ciMODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
16718c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1672