162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * cs35l35.c -- CS35L35 ALSA SoC audio driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2017 Cirrus Logic, Inc.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Brian Austin <brian.austin@cirrus.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/moduleparam.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/i2c.h>
1662306a36Sopenharmony_ci#include <linux/slab.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1962306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
2062306a36Sopenharmony_ci#include <linux/of_device.h>
2162306a36Sopenharmony_ci#include <linux/of_gpio.h>
2262306a36Sopenharmony_ci#include <linux/regmap.h>
2362306a36Sopenharmony_ci#include <sound/core.h>
2462306a36Sopenharmony_ci#include <sound/pcm.h>
2562306a36Sopenharmony_ci#include <sound/pcm_params.h>
2662306a36Sopenharmony_ci#include <sound/soc.h>
2762306a36Sopenharmony_ci#include <sound/soc-dapm.h>
2862306a36Sopenharmony_ci#include <linux/gpio.h>
2962306a36Sopenharmony_ci#include <sound/initval.h>
3062306a36Sopenharmony_ci#include <sound/tlv.h>
3162306a36Sopenharmony_ci#include <sound/cs35l35.h>
3262306a36Sopenharmony_ci#include <linux/of_irq.h>
3362306a36Sopenharmony_ci#include <linux/completion.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "cs35l35.h"
3662306a36Sopenharmony_ci#include "cirrus_legacy.h"
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * Some fields take zero as a valid value so use a high bit flag that won't
4062306a36Sopenharmony_ci * get written to the device to mark those.
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_ci#define CS35L35_VALID_PDATA 0x80000000
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic const struct reg_default cs35l35_reg[] = {
4562306a36Sopenharmony_ci	{CS35L35_PWRCTL1,		0x01},
4662306a36Sopenharmony_ci	{CS35L35_PWRCTL2,		0x11},
4762306a36Sopenharmony_ci	{CS35L35_PWRCTL3,		0x00},
4862306a36Sopenharmony_ci	{CS35L35_CLK_CTL1,		0x04},
4962306a36Sopenharmony_ci	{CS35L35_CLK_CTL2,		0x12},
5062306a36Sopenharmony_ci	{CS35L35_CLK_CTL3,		0xCF},
5162306a36Sopenharmony_ci	{CS35L35_SP_FMT_CTL1,		0x20},
5262306a36Sopenharmony_ci	{CS35L35_SP_FMT_CTL2,		0x00},
5362306a36Sopenharmony_ci	{CS35L35_SP_FMT_CTL3,		0x02},
5462306a36Sopenharmony_ci	{CS35L35_MAG_COMP_CTL,		0x00},
5562306a36Sopenharmony_ci	{CS35L35_AMP_INP_DRV_CTL,	0x01},
5662306a36Sopenharmony_ci	{CS35L35_AMP_DIG_VOL_CTL,	0x12},
5762306a36Sopenharmony_ci	{CS35L35_AMP_DIG_VOL,		0x00},
5862306a36Sopenharmony_ci	{CS35L35_ADV_DIG_VOL,		0x00},
5962306a36Sopenharmony_ci	{CS35L35_PROTECT_CTL,		0x06},
6062306a36Sopenharmony_ci	{CS35L35_AMP_GAIN_AUD_CTL,	0x13},
6162306a36Sopenharmony_ci	{CS35L35_AMP_GAIN_PDM_CTL,	0x00},
6262306a36Sopenharmony_ci	{CS35L35_AMP_GAIN_ADV_CTL,	0x00},
6362306a36Sopenharmony_ci	{CS35L35_GPI_CTL,		0x00},
6462306a36Sopenharmony_ci	{CS35L35_BST_CVTR_V_CTL,	0x00},
6562306a36Sopenharmony_ci	{CS35L35_BST_PEAK_I,		0x07},
6662306a36Sopenharmony_ci	{CS35L35_BST_RAMP_CTL,		0x85},
6762306a36Sopenharmony_ci	{CS35L35_BST_CONV_COEF_1,	0x24},
6862306a36Sopenharmony_ci	{CS35L35_BST_CONV_COEF_2,	0x24},
6962306a36Sopenharmony_ci	{CS35L35_BST_CONV_SLOPE_COMP,	0x4E},
7062306a36Sopenharmony_ci	{CS35L35_BST_CONV_SW_FREQ,	0x04},
7162306a36Sopenharmony_ci	{CS35L35_CLASS_H_CTL,		0x0B},
7262306a36Sopenharmony_ci	{CS35L35_CLASS_H_HEADRM_CTL,	0x0B},
7362306a36Sopenharmony_ci	{CS35L35_CLASS_H_RELEASE_RATE,	0x08},
7462306a36Sopenharmony_ci	{CS35L35_CLASS_H_FET_DRIVE_CTL, 0x41},
7562306a36Sopenharmony_ci	{CS35L35_CLASS_H_VP_CTL,	0xC5},
7662306a36Sopenharmony_ci	{CS35L35_VPBR_CTL,		0x0A},
7762306a36Sopenharmony_ci	{CS35L35_VPBR_VOL_CTL,		0x90},
7862306a36Sopenharmony_ci	{CS35L35_VPBR_TIMING_CTL,	0x6A},
7962306a36Sopenharmony_ci	{CS35L35_VPBR_MODE_VOL_CTL,	0x00},
8062306a36Sopenharmony_ci	{CS35L35_SPKR_MON_CTL,		0xC0},
8162306a36Sopenharmony_ci	{CS35L35_IMON_SCALE_CTL,	0x30},
8262306a36Sopenharmony_ci	{CS35L35_AUDIN_RXLOC_CTL,	0x00},
8362306a36Sopenharmony_ci	{CS35L35_ADVIN_RXLOC_CTL,	0x80},
8462306a36Sopenharmony_ci	{CS35L35_VMON_TXLOC_CTL,	0x00},
8562306a36Sopenharmony_ci	{CS35L35_IMON_TXLOC_CTL,	0x80},
8662306a36Sopenharmony_ci	{CS35L35_VPMON_TXLOC_CTL,	0x04},
8762306a36Sopenharmony_ci	{CS35L35_VBSTMON_TXLOC_CTL,	0x84},
8862306a36Sopenharmony_ci	{CS35L35_VPBR_STATUS_TXLOC_CTL,	0x04},
8962306a36Sopenharmony_ci	{CS35L35_ZERO_FILL_LOC_CTL,	0x00},
9062306a36Sopenharmony_ci	{CS35L35_AUDIN_DEPTH_CTL,	0x0F},
9162306a36Sopenharmony_ci	{CS35L35_SPKMON_DEPTH_CTL,	0x0F},
9262306a36Sopenharmony_ci	{CS35L35_SUPMON_DEPTH_CTL,	0x0F},
9362306a36Sopenharmony_ci	{CS35L35_ZEROFILL_DEPTH_CTL,	0x00},
9462306a36Sopenharmony_ci	{CS35L35_MULT_DEV_SYNCH1,	0x02},
9562306a36Sopenharmony_ci	{CS35L35_MULT_DEV_SYNCH2,	0x80},
9662306a36Sopenharmony_ci	{CS35L35_PROT_RELEASE_CTL,	0x00},
9762306a36Sopenharmony_ci	{CS35L35_DIAG_MODE_REG_LOCK,	0x00},
9862306a36Sopenharmony_ci	{CS35L35_DIAG_MODE_CTL_1,	0x40},
9962306a36Sopenharmony_ci	{CS35L35_DIAG_MODE_CTL_2,	0x00},
10062306a36Sopenharmony_ci	{CS35L35_INT_MASK_1,		0xFF},
10162306a36Sopenharmony_ci	{CS35L35_INT_MASK_2,		0xFF},
10262306a36Sopenharmony_ci	{CS35L35_INT_MASK_3,		0xFF},
10362306a36Sopenharmony_ci	{CS35L35_INT_MASK_4,		0xFF},
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic bool cs35l35_volatile_register(struct device *dev, unsigned int reg)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	switch (reg) {
11062306a36Sopenharmony_ci	case CS35L35_INT_STATUS_1:
11162306a36Sopenharmony_ci	case CS35L35_INT_STATUS_2:
11262306a36Sopenharmony_ci	case CS35L35_INT_STATUS_3:
11362306a36Sopenharmony_ci	case CS35L35_INT_STATUS_4:
11462306a36Sopenharmony_ci	case CS35L35_PLL_STATUS:
11562306a36Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
11662306a36Sopenharmony_ci		return true;
11762306a36Sopenharmony_ci	default:
11862306a36Sopenharmony_ci		return false;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic bool cs35l35_readable_register(struct device *dev, unsigned int reg)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	switch (reg) {
12562306a36Sopenharmony_ci	case CS35L35_DEVID_AB ... CS35L35_PWRCTL3:
12662306a36Sopenharmony_ci	case CS35L35_CLK_CTL1 ... CS35L35_SP_FMT_CTL3:
12762306a36Sopenharmony_ci	case CS35L35_MAG_COMP_CTL ... CS35L35_AMP_GAIN_AUD_CTL:
12862306a36Sopenharmony_ci	case CS35L35_AMP_GAIN_PDM_CTL ... CS35L35_BST_PEAK_I:
12962306a36Sopenharmony_ci	case CS35L35_BST_RAMP_CTL ... CS35L35_BST_CONV_SW_FREQ:
13062306a36Sopenharmony_ci	case CS35L35_CLASS_H_CTL ... CS35L35_CLASS_H_VP_CTL:
13162306a36Sopenharmony_ci	case CS35L35_CLASS_H_STATUS:
13262306a36Sopenharmony_ci	case CS35L35_VPBR_CTL ... CS35L35_VPBR_MODE_VOL_CTL:
13362306a36Sopenharmony_ci	case CS35L35_VPBR_ATTEN_STATUS:
13462306a36Sopenharmony_ci	case CS35L35_SPKR_MON_CTL:
13562306a36Sopenharmony_ci	case CS35L35_IMON_SCALE_CTL ... CS35L35_ZEROFILL_DEPTH_CTL:
13662306a36Sopenharmony_ci	case CS35L35_MULT_DEV_SYNCH1 ... CS35L35_PROT_RELEASE_CTL:
13762306a36Sopenharmony_ci	case CS35L35_DIAG_MODE_REG_LOCK ... CS35L35_DIAG_MODE_CTL_2:
13862306a36Sopenharmony_ci	case CS35L35_INT_MASK_1 ... CS35L35_PLL_STATUS:
13962306a36Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
14062306a36Sopenharmony_ci		return true;
14162306a36Sopenharmony_ci	default:
14262306a36Sopenharmony_ci		return false;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic bool cs35l35_precious_register(struct device *dev, unsigned int reg)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	switch (reg) {
14962306a36Sopenharmony_ci	case CS35L35_INT_STATUS_1:
15062306a36Sopenharmony_ci	case CS35L35_INT_STATUS_2:
15162306a36Sopenharmony_ci	case CS35L35_INT_STATUS_3:
15262306a36Sopenharmony_ci	case CS35L35_INT_STATUS_4:
15362306a36Sopenharmony_ci	case CS35L35_PLL_STATUS:
15462306a36Sopenharmony_ci	case CS35L35_OTP_TRIM_STATUS:
15562306a36Sopenharmony_ci		return true;
15662306a36Sopenharmony_ci	default:
15762306a36Sopenharmony_ci		return false;
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic void cs35l35_reset(struct cs35l35_private *cs35l35)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
16462306a36Sopenharmony_ci	usleep_range(2000, 2100);
16562306a36Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
16662306a36Sopenharmony_ci	usleep_range(1000, 1100);
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	int ret;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (cs35l35->pdata.ext_bst) {
17462306a36Sopenharmony_ci		usleep_range(5000, 5500);
17562306a36Sopenharmony_ci		return 0;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	reinit_completion(&cs35l35->pdn_done);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&cs35l35->pdn_done,
18162306a36Sopenharmony_ci					  msecs_to_jiffies(100));
18262306a36Sopenharmony_ci	if (ret == 0) {
18362306a36Sopenharmony_ci		dev_err(cs35l35->dev, "PDN_DONE did not complete\n");
18462306a36Sopenharmony_ci		return -ETIMEDOUT;
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return 0;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int cs35l35_sdin_event(struct snd_soc_dapm_widget *w,
19162306a36Sopenharmony_ci		struct snd_kcontrol *kcontrol, int event)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
19462306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
19562306a36Sopenharmony_ci	int ret = 0;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	switch (event) {
19862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
19962306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
20062306a36Sopenharmony_ci					CS35L35_MCLK_DIS_MASK,
20162306a36Sopenharmony_ci					0 << CS35L35_MCLK_DIS_SHIFT);
20262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
20362306a36Sopenharmony_ci					CS35L35_DISCHG_FILT_MASK,
20462306a36Sopenharmony_ci					0 << CS35L35_DISCHG_FILT_SHIFT);
20562306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
20662306a36Sopenharmony_ci					CS35L35_PDN_ALL_MASK, 0);
20762306a36Sopenharmony_ci		break;
20862306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
20962306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
21062306a36Sopenharmony_ci					CS35L35_DISCHG_FILT_MASK,
21162306a36Sopenharmony_ci					1 << CS35L35_DISCHG_FILT_SHIFT);
21262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
21362306a36Sopenharmony_ci					  CS35L35_PDN_ALL_MASK, 1);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		/* Already muted, so disable volume ramp for faster shutdown */
21662306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
21762306a36Sopenharmony_ci				   CS35L35_AMP_DIGSFT_MASK, 0);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		ret = cs35l35_wait_for_pdn(cs35l35);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
22262306a36Sopenharmony_ci					CS35L35_MCLK_DIS_MASK,
22362306a36Sopenharmony_ci					1 << CS35L35_MCLK_DIS_SHIFT);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_AMP_DIG_VOL_CTL,
22662306a36Sopenharmony_ci				   CS35L35_AMP_DIGSFT_MASK,
22762306a36Sopenharmony_ci				   1 << CS35L35_AMP_DIGSFT_SHIFT);
22862306a36Sopenharmony_ci		break;
22962306a36Sopenharmony_ci	default:
23062306a36Sopenharmony_ci		dev_err(component->dev, "Invalid event = 0x%x\n", event);
23162306a36Sopenharmony_ci		ret = -EINVAL;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci	return ret;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int cs35l35_main_amp_event(struct snd_soc_dapm_widget *w,
23762306a36Sopenharmony_ci		struct snd_kcontrol *kcontrol, int event)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
24062306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
24162306a36Sopenharmony_ci	unsigned int reg[4];
24262306a36Sopenharmony_ci	int i;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	switch (event) {
24562306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
24662306a36Sopenharmony_ci		if (cs35l35->pdata.bst_pdn_fet_on)
24762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
24862306a36Sopenharmony_ci				CS35L35_PDN_BST_MASK,
24962306a36Sopenharmony_ci				0 << CS35L35_PDN_BST_FETON_SHIFT);
25062306a36Sopenharmony_ci		else
25162306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
25262306a36Sopenharmony_ci				CS35L35_PDN_BST_MASK,
25362306a36Sopenharmony_ci				0 << CS35L35_PDN_BST_FETOFF_SHIFT);
25462306a36Sopenharmony_ci		break;
25562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
25662306a36Sopenharmony_ci		usleep_range(5000, 5100);
25762306a36Sopenharmony_ci		/* If in PDM mode we must use VP for Voltage control */
25862306a36Sopenharmony_ci		if (cs35l35->pdm_mode)
25962306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
26062306a36Sopenharmony_ci					CS35L35_BST_CVTR_V_CTL,
26162306a36Sopenharmony_ci					CS35L35_BST_CTL_MASK,
26262306a36Sopenharmony_ci					0 << CS35L35_BST_CTL_SHIFT);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
26562306a36Sopenharmony_ci			CS35L35_AMP_MUTE_MASK, 0);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci		for (i = 0; i < 2; i++)
26862306a36Sopenharmony_ci			regmap_bulk_read(cs35l35->regmap, CS35L35_INT_STATUS_1,
26962306a36Sopenharmony_ci					&reg, ARRAY_SIZE(reg));
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci		break;
27262306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
27362306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
27462306a36Sopenharmony_ci				CS35L35_AMP_MUTE_MASK,
27562306a36Sopenharmony_ci				1 << CS35L35_AMP_MUTE_SHIFT);
27662306a36Sopenharmony_ci		if (cs35l35->pdata.bst_pdn_fet_on)
27762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
27862306a36Sopenharmony_ci				CS35L35_PDN_BST_MASK,
27962306a36Sopenharmony_ci				1 << CS35L35_PDN_BST_FETON_SHIFT);
28062306a36Sopenharmony_ci		else
28162306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
28262306a36Sopenharmony_ci				CS35L35_PDN_BST_MASK,
28362306a36Sopenharmony_ci				1 << CS35L35_PDN_BST_FETOFF_SHIFT);
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
28662306a36Sopenharmony_ci		usleep_range(5000, 5100);
28762306a36Sopenharmony_ci		/*
28862306a36Sopenharmony_ci		 * If PDM mode we should switch back to pdata value
28962306a36Sopenharmony_ci		 * for Voltage control when we go down
29062306a36Sopenharmony_ci		 */
29162306a36Sopenharmony_ci		if (cs35l35->pdm_mode)
29262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
29362306a36Sopenharmony_ci					CS35L35_BST_CVTR_V_CTL,
29462306a36Sopenharmony_ci					CS35L35_BST_CTL_MASK,
29562306a36Sopenharmony_ci					cs35l35->pdata.bst_vctl
29662306a36Sopenharmony_ci					<< CS35L35_BST_CTL_SHIFT);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci		break;
29962306a36Sopenharmony_ci	default:
30062306a36Sopenharmony_ci		dev_err(component->dev, "Invalid event = 0x%x\n", event);
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci	return 0;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
30662306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 50, 0);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs35l35_aud_controls[] = {
30962306a36Sopenharmony_ci	SOC_SINGLE_SX_TLV("Digital Audio Volume", CS35L35_AMP_DIG_VOL,
31062306a36Sopenharmony_ci		      0, 0x34, 0xE4, dig_vol_tlv),
31162306a36Sopenharmony_ci	SOC_SINGLE_TLV("Analog Audio Volume", CS35L35_AMP_GAIN_AUD_CTL, 0, 19, 0,
31262306a36Sopenharmony_ci			amp_gain_tlv),
31362306a36Sopenharmony_ci	SOC_SINGLE_TLV("PDM Volume", CS35L35_AMP_GAIN_PDM_CTL, 0, 19, 0,
31462306a36Sopenharmony_ci			amp_gain_tlv),
31562306a36Sopenharmony_ci};
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs35l35_adv_controls[] = {
31862306a36Sopenharmony_ci	SOC_SINGLE_SX_TLV("Digital Advisory Volume", CS35L35_ADV_DIG_VOL,
31962306a36Sopenharmony_ci		      0, 0x34, 0xE4, dig_vol_tlv),
32062306a36Sopenharmony_ci	SOC_SINGLE_TLV("Analog Advisory Volume", CS35L35_AMP_GAIN_ADV_CTL, 0, 19, 0,
32162306a36Sopenharmony_ci			amp_gain_tlv),
32262306a36Sopenharmony_ci};
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget cs35l35_dapm_widgets[] = {
32562306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L35_PWRCTL3, 1, 1,
32662306a36Sopenharmony_ci				cs35l35_sdin_event, SND_SOC_DAPM_PRE_PMU |
32762306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD),
32862306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L35_PWRCTL3, 2, 1),
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPK"),
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VP"),
33362306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VBST"),
33462306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("ISENSE"),
33562306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VSENSE"),
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L35_PWRCTL2, 7, 1),
33862306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L35_PWRCTL2, 6, 1),
33962306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L35_PWRCTL3, 3, 1),
34062306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L35_PWRCTL3, 4, 1),
34162306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L35_PWRCTL2, 5, 1),
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L35_PWRCTL2, 0, 1, NULL, 0,
34462306a36Sopenharmony_ci		cs35l35_main_amp_event, SND_SOC_DAPM_PRE_PMU |
34562306a36Sopenharmony_ci				SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU |
34662306a36Sopenharmony_ci				SND_SOC_DAPM_PRE_PMD),
34762306a36Sopenharmony_ci};
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic const struct snd_soc_dapm_route cs35l35_audio_map[] = {
35062306a36Sopenharmony_ci	{"VPMON ADC", NULL, "VP"},
35162306a36Sopenharmony_ci	{"VBSTMON ADC", NULL, "VBST"},
35262306a36Sopenharmony_ci	{"IMON ADC", NULL, "ISENSE"},
35362306a36Sopenharmony_ci	{"VMON ADC", NULL, "VSENSE"},
35462306a36Sopenharmony_ci	{"SDOUT", NULL, "IMON ADC"},
35562306a36Sopenharmony_ci	{"SDOUT", NULL, "VMON ADC"},
35662306a36Sopenharmony_ci	{"SDOUT", NULL, "VBSTMON ADC"},
35762306a36Sopenharmony_ci	{"SDOUT", NULL, "VPMON ADC"},
35862306a36Sopenharmony_ci	{"AMP Capture", NULL, "SDOUT"},
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	{"SDIN", NULL, "AMP Playback"},
36162306a36Sopenharmony_ci	{"CLASS H", NULL, "SDIN"},
36262306a36Sopenharmony_ci	{"Main AMP", NULL, "CLASS H"},
36362306a36Sopenharmony_ci	{"SPK", NULL, "Main AMP"},
36462306a36Sopenharmony_ci};
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cistatic int cs35l35_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
36962306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
37262306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBP_CFP:
37362306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
37462306a36Sopenharmony_ci				    CS35L35_MS_MASK, 1 << CS35L35_MS_SHIFT);
37562306a36Sopenharmony_ci		cs35l35->clock_consumer = false;
37662306a36Sopenharmony_ci		break;
37762306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBC_CFC:
37862306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
37962306a36Sopenharmony_ci				    CS35L35_MS_MASK, 0 << CS35L35_MS_SHIFT);
38062306a36Sopenharmony_ci		cs35l35->clock_consumer = true;
38162306a36Sopenharmony_ci		break;
38262306a36Sopenharmony_ci	default:
38362306a36Sopenharmony_ci		return -EINVAL;
38462306a36Sopenharmony_ci	}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
38762306a36Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
38862306a36Sopenharmony_ci		cs35l35->i2s_mode = true;
38962306a36Sopenharmony_ci		cs35l35->pdm_mode = false;
39062306a36Sopenharmony_ci		break;
39162306a36Sopenharmony_ci	case SND_SOC_DAIFMT_PDM:
39262306a36Sopenharmony_ci		cs35l35->pdm_mode = true;
39362306a36Sopenharmony_ci		cs35l35->i2s_mode = false;
39462306a36Sopenharmony_ci		break;
39562306a36Sopenharmony_ci	default:
39662306a36Sopenharmony_ci		return -EINVAL;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	return 0;
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistruct cs35l35_sysclk_config {
40362306a36Sopenharmony_ci	int sysclk;
40462306a36Sopenharmony_ci	int srate;
40562306a36Sopenharmony_ci	u8 clk_cfg;
40662306a36Sopenharmony_ci};
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic struct cs35l35_sysclk_config cs35l35_clk_ctl[] = {
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/* SYSCLK, Sample Rate, Serial Port Cfg */
41162306a36Sopenharmony_ci	{5644800, 44100, 0x00},
41262306a36Sopenharmony_ci	{5644800, 88200, 0x40},
41362306a36Sopenharmony_ci	{6144000, 48000, 0x10},
41462306a36Sopenharmony_ci	{6144000, 96000, 0x50},
41562306a36Sopenharmony_ci	{11289600, 44100, 0x01},
41662306a36Sopenharmony_ci	{11289600, 88200, 0x41},
41762306a36Sopenharmony_ci	{11289600, 176400, 0x81},
41862306a36Sopenharmony_ci	{12000000, 44100, 0x03},
41962306a36Sopenharmony_ci	{12000000, 48000, 0x13},
42062306a36Sopenharmony_ci	{12000000, 88200, 0x43},
42162306a36Sopenharmony_ci	{12000000, 96000, 0x53},
42262306a36Sopenharmony_ci	{12000000, 176400, 0x83},
42362306a36Sopenharmony_ci	{12000000, 192000, 0x93},
42462306a36Sopenharmony_ci	{12288000, 48000, 0x11},
42562306a36Sopenharmony_ci	{12288000, 96000, 0x51},
42662306a36Sopenharmony_ci	{12288000, 192000, 0x91},
42762306a36Sopenharmony_ci	{13000000, 44100, 0x07},
42862306a36Sopenharmony_ci	{13000000, 48000, 0x17},
42962306a36Sopenharmony_ci	{13000000, 88200, 0x47},
43062306a36Sopenharmony_ci	{13000000, 96000, 0x57},
43162306a36Sopenharmony_ci	{13000000, 176400, 0x87},
43262306a36Sopenharmony_ci	{13000000, 192000, 0x97},
43362306a36Sopenharmony_ci	{22579200, 44100, 0x02},
43462306a36Sopenharmony_ci	{22579200, 88200, 0x42},
43562306a36Sopenharmony_ci	{22579200, 176400, 0x82},
43662306a36Sopenharmony_ci	{24000000, 44100, 0x0B},
43762306a36Sopenharmony_ci	{24000000, 48000, 0x1B},
43862306a36Sopenharmony_ci	{24000000, 88200, 0x4B},
43962306a36Sopenharmony_ci	{24000000, 96000, 0x5B},
44062306a36Sopenharmony_ci	{24000000, 176400, 0x8B},
44162306a36Sopenharmony_ci	{24000000, 192000, 0x9B},
44262306a36Sopenharmony_ci	{24576000, 48000, 0x12},
44362306a36Sopenharmony_ci	{24576000, 96000, 0x52},
44462306a36Sopenharmony_ci	{24576000, 192000, 0x92},
44562306a36Sopenharmony_ci	{26000000, 44100, 0x0F},
44662306a36Sopenharmony_ci	{26000000, 48000, 0x1F},
44762306a36Sopenharmony_ci	{26000000, 88200, 0x4F},
44862306a36Sopenharmony_ci	{26000000, 96000, 0x5F},
44962306a36Sopenharmony_ci	{26000000, 176400, 0x8F},
45062306a36Sopenharmony_ci	{26000000, 192000, 0x9F},
45162306a36Sopenharmony_ci};
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_cistatic int cs35l35_get_clk_config(int sysclk, int srate)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	int i;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l35_clk_ctl); i++) {
45862306a36Sopenharmony_ci		if (cs35l35_clk_ctl[i].sysclk == sysclk &&
45962306a36Sopenharmony_ci			cs35l35_clk_ctl[i].srate == srate)
46062306a36Sopenharmony_ci			return cs35l35_clk_ctl[i].clk_cfg;
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci	return -EINVAL;
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic int cs35l35_hw_params(struct snd_pcm_substream *substream,
46662306a36Sopenharmony_ci				 struct snd_pcm_hw_params *params,
46762306a36Sopenharmony_ci				 struct snd_soc_dai *dai)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
47062306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
47162306a36Sopenharmony_ci	struct classh_cfg *classh = &cs35l35->pdata.classh_algo;
47262306a36Sopenharmony_ci	int srate = params_rate(params);
47362306a36Sopenharmony_ci	int ret = 0;
47462306a36Sopenharmony_ci	u8 sp_sclks;
47562306a36Sopenharmony_ci	int audin_format;
47662306a36Sopenharmony_ci	int errata_chk;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	int clk_ctl = cs35l35_get_clk_config(cs35l35->sysclk, srate);
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (clk_ctl < 0) {
48162306a36Sopenharmony_ci		dev_err(component->dev, "Invalid CLK:Rate %d:%d\n",
48262306a36Sopenharmony_ci			cs35l35->sysclk, srate);
48362306a36Sopenharmony_ci		return -EINVAL;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL2,
48762306a36Sopenharmony_ci			  CS35L35_CLK_CTL2_MASK, clk_ctl);
48862306a36Sopenharmony_ci	if (ret != 0) {
48962306a36Sopenharmony_ci		dev_err(component->dev, "Failed to set port config %d\n", ret);
49062306a36Sopenharmony_ci		return ret;
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	/*
49462306a36Sopenharmony_ci	 * Rev A0 Errata
49562306a36Sopenharmony_ci	 * When configured for the weak-drive detection path (CH_WKFET_DIS = 0)
49662306a36Sopenharmony_ci	 * the Class H algorithm does not enable weak-drive operation for
49762306a36Sopenharmony_ci	 * nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10
49862306a36Sopenharmony_ci	 */
49962306a36Sopenharmony_ci	errata_chk = (clk_ctl & CS35L35_SP_RATE_MASK) >> CS35L35_SP_RATE_SHIFT;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	if (classh->classh_wk_fet_disable == 0x00 &&
50262306a36Sopenharmony_ci		(errata_chk == 0x01 || errata_chk == 0x02)) {
50362306a36Sopenharmony_ci		ret = regmap_update_bits(cs35l35->regmap,
50462306a36Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
50562306a36Sopenharmony_ci					CS35L35_CH_WKFET_DEL_MASK,
50662306a36Sopenharmony_ci					0 << CS35L35_CH_WKFET_DEL_SHIFT);
50762306a36Sopenharmony_ci		if (ret != 0) {
50862306a36Sopenharmony_ci			dev_err(component->dev, "Failed to set fet config %d\n",
50962306a36Sopenharmony_ci				ret);
51062306a36Sopenharmony_ci			return ret;
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	/*
51562306a36Sopenharmony_ci	 * You can pull more Monitor data from the SDOUT pin than going to SDIN
51662306a36Sopenharmony_ci	 * Just make sure your SCLK is fast enough to fill the frame
51762306a36Sopenharmony_ci	 */
51862306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
51962306a36Sopenharmony_ci		switch (params_width(params)) {
52062306a36Sopenharmony_ci		case 8:
52162306a36Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_8;
52262306a36Sopenharmony_ci			break;
52362306a36Sopenharmony_ci		case 16:
52462306a36Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_16;
52562306a36Sopenharmony_ci			break;
52662306a36Sopenharmony_ci		case 24:
52762306a36Sopenharmony_ci			audin_format = CS35L35_SDIN_DEPTH_24;
52862306a36Sopenharmony_ci			break;
52962306a36Sopenharmony_ci		default:
53062306a36Sopenharmony_ci			dev_err(component->dev, "Unsupported Width %d\n",
53162306a36Sopenharmony_ci				params_width(params));
53262306a36Sopenharmony_ci			return -EINVAL;
53362306a36Sopenharmony_ci		}
53462306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
53562306a36Sopenharmony_ci				CS35L35_AUDIN_DEPTH_CTL,
53662306a36Sopenharmony_ci				CS35L35_AUDIN_DEPTH_MASK,
53762306a36Sopenharmony_ci				audin_format <<
53862306a36Sopenharmony_ci				CS35L35_AUDIN_DEPTH_SHIFT);
53962306a36Sopenharmony_ci		if (cs35l35->pdata.stereo) {
54062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
54162306a36Sopenharmony_ci					CS35L35_AUDIN_DEPTH_CTL,
54262306a36Sopenharmony_ci					CS35L35_ADVIN_DEPTH_MASK,
54362306a36Sopenharmony_ci					audin_format <<
54462306a36Sopenharmony_ci					CS35L35_ADVIN_DEPTH_SHIFT);
54562306a36Sopenharmony_ci		}
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	if (cs35l35->i2s_mode) {
54962306a36Sopenharmony_ci		/* We have to take the SCLK to derive num sclks
55062306a36Sopenharmony_ci		 * to configure the CLOCK_CTL3 register correctly
55162306a36Sopenharmony_ci		 */
55262306a36Sopenharmony_ci		if ((cs35l35->sclk / srate) % 4) {
55362306a36Sopenharmony_ci			dev_err(component->dev, "Unsupported sclk/fs ratio %d:%d\n",
55462306a36Sopenharmony_ci					cs35l35->sclk, srate);
55562306a36Sopenharmony_ci			return -EINVAL;
55662306a36Sopenharmony_ci		}
55762306a36Sopenharmony_ci		sp_sclks = ((cs35l35->sclk / srate) / 4) - 1;
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		/* Only certain ratios supported when device is a clock consumer */
56062306a36Sopenharmony_ci		if (cs35l35->clock_consumer) {
56162306a36Sopenharmony_ci			switch (sp_sclks) {
56262306a36Sopenharmony_ci			case CS35L35_SP_SCLKS_32FS:
56362306a36Sopenharmony_ci			case CS35L35_SP_SCLKS_48FS:
56462306a36Sopenharmony_ci			case CS35L35_SP_SCLKS_64FS:
56562306a36Sopenharmony_ci				break;
56662306a36Sopenharmony_ci			default:
56762306a36Sopenharmony_ci				dev_err(component->dev, "ratio not supported\n");
56862306a36Sopenharmony_ci				return -EINVAL;
56962306a36Sopenharmony_ci			}
57062306a36Sopenharmony_ci		} else {
57162306a36Sopenharmony_ci			/* Only certain ratios supported when device is a clock provider */
57262306a36Sopenharmony_ci			switch (sp_sclks) {
57362306a36Sopenharmony_ci			case CS35L35_SP_SCLKS_32FS:
57462306a36Sopenharmony_ci			case CS35L35_SP_SCLKS_64FS:
57562306a36Sopenharmony_ci				break;
57662306a36Sopenharmony_ci			default:
57762306a36Sopenharmony_ci				dev_err(component->dev, "ratio not supported\n");
57862306a36Sopenharmony_ci				return -EINVAL;
57962306a36Sopenharmony_ci			}
58062306a36Sopenharmony_ci		}
58162306a36Sopenharmony_ci		ret = regmap_update_bits(cs35l35->regmap,
58262306a36Sopenharmony_ci					CS35L35_CLK_CTL3,
58362306a36Sopenharmony_ci					CS35L35_SP_SCLKS_MASK, sp_sclks <<
58462306a36Sopenharmony_ci					CS35L35_SP_SCLKS_SHIFT);
58562306a36Sopenharmony_ci		if (ret != 0) {
58662306a36Sopenharmony_ci			dev_err(component->dev, "Failed to set fsclk %d\n", ret);
58762306a36Sopenharmony_ci			return ret;
58862306a36Sopenharmony_ci		}
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	return ret;
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic const unsigned int cs35l35_src_rates[] = {
59562306a36Sopenharmony_ci	44100, 48000, 88200, 96000, 176400, 192000
59662306a36Sopenharmony_ci};
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list cs35l35_constraints = {
59962306a36Sopenharmony_ci	.count  = ARRAY_SIZE(cs35l35_src_rates),
60062306a36Sopenharmony_ci	.list   = cs35l35_src_rates,
60162306a36Sopenharmony_ci};
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic int cs35l35_pcm_startup(struct snd_pcm_substream *substream,
60462306a36Sopenharmony_ci			       struct snd_soc_dai *dai)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
60762306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	if (!substream->runtime)
61062306a36Sopenharmony_ci		return 0;
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	snd_pcm_hw_constraint_list(substream->runtime, 0,
61362306a36Sopenharmony_ci				SNDRV_PCM_HW_PARAM_RATE, &cs35l35_constraints);
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,
61662306a36Sopenharmony_ci					CS35L35_PDM_MODE_MASK,
61762306a36Sopenharmony_ci					0 << CS35L35_PDM_MODE_SHIFT);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return 0;
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic const unsigned int cs35l35_pdm_rates[] = {
62362306a36Sopenharmony_ci	44100, 48000, 88200, 96000
62462306a36Sopenharmony_ci};
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list cs35l35_pdm_constraints = {
62762306a36Sopenharmony_ci	.count  = ARRAY_SIZE(cs35l35_pdm_rates),
62862306a36Sopenharmony_ci	.list   = cs35l35_pdm_rates,
62962306a36Sopenharmony_ci};
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic int cs35l35_pdm_startup(struct snd_pcm_substream *substream,
63262306a36Sopenharmony_ci			       struct snd_soc_dai *dai)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
63562306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	if (!substream->runtime)
63862306a36Sopenharmony_ci		return 0;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	snd_pcm_hw_constraint_list(substream->runtime, 0,
64162306a36Sopenharmony_ci				SNDRV_PCM_HW_PARAM_RATE,
64262306a36Sopenharmony_ci				&cs35l35_pdm_constraints);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_AMP_INP_DRV_CTL,
64562306a36Sopenharmony_ci					CS35L35_PDM_MODE_MASK,
64662306a36Sopenharmony_ci					1 << CS35L35_PDM_MODE_SHIFT);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return 0;
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic int cs35l35_dai_set_sysclk(struct snd_soc_dai *dai,
65262306a36Sopenharmony_ci				int clk_id, unsigned int freq, int dir)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
65562306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/* Need the SCLK Frequency regardless of sysclk source for I2S */
65862306a36Sopenharmony_ci	cs35l35->sclk = freq;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	return 0;
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic const struct snd_soc_dai_ops cs35l35_ops = {
66462306a36Sopenharmony_ci	.startup = cs35l35_pcm_startup,
66562306a36Sopenharmony_ci	.set_fmt = cs35l35_set_dai_fmt,
66662306a36Sopenharmony_ci	.hw_params = cs35l35_hw_params,
66762306a36Sopenharmony_ci	.set_sysclk = cs35l35_dai_set_sysclk,
66862306a36Sopenharmony_ci};
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops cs35l35_pdm_ops = {
67162306a36Sopenharmony_ci	.startup = cs35l35_pdm_startup,
67262306a36Sopenharmony_ci	.set_fmt = cs35l35_set_dai_fmt,
67362306a36Sopenharmony_ci	.hw_params = cs35l35_hw_params,
67462306a36Sopenharmony_ci};
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic struct snd_soc_dai_driver cs35l35_dai[] = {
67762306a36Sopenharmony_ci	{
67862306a36Sopenharmony_ci		.name = "cs35l35-pcm",
67962306a36Sopenharmony_ci		.id = 0,
68062306a36Sopenharmony_ci		.playback = {
68162306a36Sopenharmony_ci			.stream_name = "AMP Playback",
68262306a36Sopenharmony_ci			.channels_min = 1,
68362306a36Sopenharmony_ci			.channels_max = 8,
68462306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
68562306a36Sopenharmony_ci			.formats = CS35L35_FORMATS,
68662306a36Sopenharmony_ci		},
68762306a36Sopenharmony_ci		.capture = {
68862306a36Sopenharmony_ci			.stream_name = "AMP Capture",
68962306a36Sopenharmony_ci			.channels_min = 1,
69062306a36Sopenharmony_ci			.channels_max = 8,
69162306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
69262306a36Sopenharmony_ci			.formats = CS35L35_FORMATS,
69362306a36Sopenharmony_ci		},
69462306a36Sopenharmony_ci		.ops = &cs35l35_ops,
69562306a36Sopenharmony_ci		.symmetric_rate = 1,
69662306a36Sopenharmony_ci	},
69762306a36Sopenharmony_ci	{
69862306a36Sopenharmony_ci		.name = "cs35l35-pdm",
69962306a36Sopenharmony_ci		.id = 1,
70062306a36Sopenharmony_ci		.playback = {
70162306a36Sopenharmony_ci			.stream_name = "PDM Playback",
70262306a36Sopenharmony_ci			.channels_min = 1,
70362306a36Sopenharmony_ci			.channels_max = 2,
70462306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
70562306a36Sopenharmony_ci			.formats = CS35L35_FORMATS,
70662306a36Sopenharmony_ci		},
70762306a36Sopenharmony_ci		.ops = &cs35l35_pdm_ops,
70862306a36Sopenharmony_ci	},
70962306a36Sopenharmony_ci};
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_cistatic int cs35l35_component_set_sysclk(struct snd_soc_component *component,
71262306a36Sopenharmony_ci				int clk_id, int source, unsigned int freq,
71362306a36Sopenharmony_ci				int dir)
71462306a36Sopenharmony_ci{
71562306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
71662306a36Sopenharmony_ci	int clksrc;
71762306a36Sopenharmony_ci	int ret = 0;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	switch (clk_id) {
72062306a36Sopenharmony_ci	case 0:
72162306a36Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_MCLK;
72262306a36Sopenharmony_ci		break;
72362306a36Sopenharmony_ci	case 1:
72462306a36Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_SCLK;
72562306a36Sopenharmony_ci		break;
72662306a36Sopenharmony_ci	case 2:
72762306a36Sopenharmony_ci		clksrc = CS35L35_CLK_SOURCE_PDM;
72862306a36Sopenharmony_ci		break;
72962306a36Sopenharmony_ci	default:
73062306a36Sopenharmony_ci		dev_err(component->dev, "Invalid CLK Source\n");
73162306a36Sopenharmony_ci		return -EINVAL;
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	switch (freq) {
73562306a36Sopenharmony_ci	case 5644800:
73662306a36Sopenharmony_ci	case 6144000:
73762306a36Sopenharmony_ci	case 11289600:
73862306a36Sopenharmony_ci	case 12000000:
73962306a36Sopenharmony_ci	case 12288000:
74062306a36Sopenharmony_ci	case 13000000:
74162306a36Sopenharmony_ci	case 22579200:
74262306a36Sopenharmony_ci	case 24000000:
74362306a36Sopenharmony_ci	case 24576000:
74462306a36Sopenharmony_ci	case 26000000:
74562306a36Sopenharmony_ci		cs35l35->sysclk = freq;
74662306a36Sopenharmony_ci		break;
74762306a36Sopenharmony_ci	default:
74862306a36Sopenharmony_ci		dev_err(component->dev, "Invalid CLK Frequency Input : %d\n", freq);
74962306a36Sopenharmony_ci		return -EINVAL;
75062306a36Sopenharmony_ci	}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	ret = regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
75362306a36Sopenharmony_ci				CS35L35_CLK_SOURCE_MASK,
75462306a36Sopenharmony_ci				clksrc << CS35L35_CLK_SOURCE_SHIFT);
75562306a36Sopenharmony_ci	if (ret != 0) {
75662306a36Sopenharmony_ci		dev_err(component->dev, "Failed to set sysclk %d\n", ret);
75762306a36Sopenharmony_ci		return ret;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	return ret;
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_cistatic int cs35l35_boost_inductor(struct cs35l35_private *cs35l35,
76462306a36Sopenharmony_ci				  int inductor)
76562306a36Sopenharmony_ci{
76662306a36Sopenharmony_ci	struct regmap *regmap = cs35l35->regmap;
76762306a36Sopenharmony_ci	unsigned int bst_ipk = 0;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	/*
77062306a36Sopenharmony_ci	 * Digital Boost Converter Configuration for feedback,
77162306a36Sopenharmony_ci	 * ramping, switching frequency, and estimation block seeding.
77262306a36Sopenharmony_ci	 */
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
77562306a36Sopenharmony_ci			   CS35L35_BST_CONV_SWFREQ_MASK, 0x00);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk);
77862306a36Sopenharmony_ci	bst_ipk &= CS35L35_BST_IPK_MASK;
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	switch (inductor) {
78162306a36Sopenharmony_ci	case 1000: /* 1 uH */
78262306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24);
78362306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24);
78462306a36Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
78562306a36Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x00);
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci		if (bst_ipk < 0x04)
78862306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
78962306a36Sopenharmony_ci		else
79062306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E);
79162306a36Sopenharmony_ci		break;
79262306a36Sopenharmony_ci	case 1200: /* 1.2 uH */
79362306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
79462306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
79562306a36Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
79662306a36Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x01);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci		if (bst_ipk < 0x04)
79962306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
80062306a36Sopenharmony_ci		else
80162306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47);
80262306a36Sopenharmony_ci		break;
80362306a36Sopenharmony_ci	case 1500: /* 1.5uH */
80462306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
80562306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
80662306a36Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
80762306a36Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x02);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci		if (bst_ipk < 0x04)
81062306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
81162306a36Sopenharmony_ci		else
81262306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C);
81362306a36Sopenharmony_ci		break;
81462306a36Sopenharmony_ci	case 2200: /* 2.2uH */
81562306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19);
81662306a36Sopenharmony_ci		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25);
81762306a36Sopenharmony_ci		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
81862306a36Sopenharmony_ci				   CS35L35_BST_CONV_LBST_MASK, 0x03);
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		if (bst_ipk < 0x04)
82162306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
82262306a36Sopenharmony_ci		else
82362306a36Sopenharmony_ci			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23);
82462306a36Sopenharmony_ci		break;
82562306a36Sopenharmony_ci	default:
82662306a36Sopenharmony_ci		dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n",
82762306a36Sopenharmony_ci			inductor);
82862306a36Sopenharmony_ci		return -EINVAL;
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci	return 0;
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic int cs35l35_component_probe(struct snd_soc_component *component)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
83662306a36Sopenharmony_ci	struct classh_cfg *classh = &cs35l35->pdata.classh_algo;
83762306a36Sopenharmony_ci	struct monitor_cfg *monitor_config = &cs35l35->pdata.mon_cfg;
83862306a36Sopenharmony_ci	int ret;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/* Set Platform Data */
84162306a36Sopenharmony_ci	if (cs35l35->pdata.bst_vctl)
84262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_BST_CVTR_V_CTL,
84362306a36Sopenharmony_ci				CS35L35_BST_CTL_MASK,
84462306a36Sopenharmony_ci				cs35l35->pdata.bst_vctl);
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	if (cs35l35->pdata.bst_ipk)
84762306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_BST_PEAK_I,
84862306a36Sopenharmony_ci				CS35L35_BST_IPK_MASK,
84962306a36Sopenharmony_ci				cs35l35->pdata.bst_ipk <<
85062306a36Sopenharmony_ci				CS35L35_BST_IPK_SHIFT);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);
85362306a36Sopenharmony_ci	if (ret)
85462306a36Sopenharmony_ci		return ret;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	if (cs35l35->pdata.gain_zc)
85762306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
85862306a36Sopenharmony_ci				CS35L35_AMP_GAIN_ZC_MASK,
85962306a36Sopenharmony_ci				cs35l35->pdata.gain_zc <<
86062306a36Sopenharmony_ci				CS35L35_AMP_GAIN_ZC_SHIFT);
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	if (cs35l35->pdata.aud_channel)
86362306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
86462306a36Sopenharmony_ci				CS35L35_AUDIN_RXLOC_CTL,
86562306a36Sopenharmony_ci				CS35L35_AUD_IN_LR_MASK,
86662306a36Sopenharmony_ci				cs35l35->pdata.aud_channel <<
86762306a36Sopenharmony_ci				CS35L35_AUD_IN_LR_SHIFT);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (cs35l35->pdata.stereo) {
87062306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap,
87162306a36Sopenharmony_ci				CS35L35_ADVIN_RXLOC_CTL,
87262306a36Sopenharmony_ci				CS35L35_ADV_IN_LR_MASK,
87362306a36Sopenharmony_ci				cs35l35->pdata.adv_channel <<
87462306a36Sopenharmony_ci				CS35L35_ADV_IN_LR_SHIFT);
87562306a36Sopenharmony_ci		if (cs35l35->pdata.shared_bst)
87662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap, CS35L35_CLASS_H_CTL,
87762306a36Sopenharmony_ci					CS35L35_CH_STEREO_MASK,
87862306a36Sopenharmony_ci					1 << CS35L35_CH_STEREO_SHIFT);
87962306a36Sopenharmony_ci		ret = snd_soc_add_component_controls(component, cs35l35_adv_controls,
88062306a36Sopenharmony_ci					ARRAY_SIZE(cs35l35_adv_controls));
88162306a36Sopenharmony_ci		if (ret)
88262306a36Sopenharmony_ci			return ret;
88362306a36Sopenharmony_ci	}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	if (cs35l35->pdata.sp_drv_str)
88662306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
88762306a36Sopenharmony_ci				CS35L35_SP_DRV_MASK,
88862306a36Sopenharmony_ci				cs35l35->pdata.sp_drv_str <<
88962306a36Sopenharmony_ci				CS35L35_SP_DRV_SHIFT);
89062306a36Sopenharmony_ci	if (cs35l35->pdata.sp_drv_unused)
89162306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_SP_FMT_CTL3,
89262306a36Sopenharmony_ci				   CS35L35_SP_I2S_DRV_MASK,
89362306a36Sopenharmony_ci				   cs35l35->pdata.sp_drv_unused <<
89462306a36Sopenharmony_ci				   CS35L35_SP_I2S_DRV_SHIFT);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	if (classh->classh_algo_enable) {
89762306a36Sopenharmony_ci		if (classh->classh_bst_override)
89862306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
89962306a36Sopenharmony_ci					CS35L35_CLASS_H_CTL,
90062306a36Sopenharmony_ci					CS35L35_CH_BST_OVR_MASK,
90162306a36Sopenharmony_ci					classh->classh_bst_override <<
90262306a36Sopenharmony_ci					CS35L35_CH_BST_OVR_SHIFT);
90362306a36Sopenharmony_ci		if (classh->classh_bst_max_limit)
90462306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
90562306a36Sopenharmony_ci					CS35L35_CLASS_H_CTL,
90662306a36Sopenharmony_ci					CS35L35_CH_BST_LIM_MASK,
90762306a36Sopenharmony_ci					classh->classh_bst_max_limit <<
90862306a36Sopenharmony_ci					CS35L35_CH_BST_LIM_SHIFT);
90962306a36Sopenharmony_ci		if (classh->classh_mem_depth)
91062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
91162306a36Sopenharmony_ci					CS35L35_CLASS_H_CTL,
91262306a36Sopenharmony_ci					CS35L35_CH_MEM_DEPTH_MASK,
91362306a36Sopenharmony_ci					classh->classh_mem_depth <<
91462306a36Sopenharmony_ci					CS35L35_CH_MEM_DEPTH_SHIFT);
91562306a36Sopenharmony_ci		if (classh->classh_headroom)
91662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
91762306a36Sopenharmony_ci					CS35L35_CLASS_H_HEADRM_CTL,
91862306a36Sopenharmony_ci					CS35L35_CH_HDRM_CTL_MASK,
91962306a36Sopenharmony_ci					classh->classh_headroom <<
92062306a36Sopenharmony_ci					CS35L35_CH_HDRM_CTL_SHIFT);
92162306a36Sopenharmony_ci		if (classh->classh_release_rate)
92262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
92362306a36Sopenharmony_ci					CS35L35_CLASS_H_RELEASE_RATE,
92462306a36Sopenharmony_ci					CS35L35_CH_REL_RATE_MASK,
92562306a36Sopenharmony_ci					classh->classh_release_rate <<
92662306a36Sopenharmony_ci					CS35L35_CH_REL_RATE_SHIFT);
92762306a36Sopenharmony_ci		if (classh->classh_wk_fet_disable)
92862306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
92962306a36Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
93062306a36Sopenharmony_ci					CS35L35_CH_WKFET_DIS_MASK,
93162306a36Sopenharmony_ci					classh->classh_wk_fet_disable <<
93262306a36Sopenharmony_ci					CS35L35_CH_WKFET_DIS_SHIFT);
93362306a36Sopenharmony_ci		if (classh->classh_wk_fet_delay)
93462306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
93562306a36Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
93662306a36Sopenharmony_ci					CS35L35_CH_WKFET_DEL_MASK,
93762306a36Sopenharmony_ci					classh->classh_wk_fet_delay <<
93862306a36Sopenharmony_ci					CS35L35_CH_WKFET_DEL_SHIFT);
93962306a36Sopenharmony_ci		if (classh->classh_wk_fet_thld)
94062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
94162306a36Sopenharmony_ci					CS35L35_CLASS_H_FET_DRIVE_CTL,
94262306a36Sopenharmony_ci					CS35L35_CH_WKFET_THLD_MASK,
94362306a36Sopenharmony_ci					classh->classh_wk_fet_thld <<
94462306a36Sopenharmony_ci					CS35L35_CH_WKFET_THLD_SHIFT);
94562306a36Sopenharmony_ci		if (classh->classh_vpch_auto)
94662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
94762306a36Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
94862306a36Sopenharmony_ci					CS35L35_CH_VP_AUTO_MASK,
94962306a36Sopenharmony_ci					classh->classh_vpch_auto <<
95062306a36Sopenharmony_ci					CS35L35_CH_VP_AUTO_SHIFT);
95162306a36Sopenharmony_ci		if (classh->classh_vpch_rate)
95262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
95362306a36Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
95462306a36Sopenharmony_ci					CS35L35_CH_VP_RATE_MASK,
95562306a36Sopenharmony_ci					classh->classh_vpch_rate <<
95662306a36Sopenharmony_ci					CS35L35_CH_VP_RATE_SHIFT);
95762306a36Sopenharmony_ci		if (classh->classh_vpch_man)
95862306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
95962306a36Sopenharmony_ci					CS35L35_CLASS_H_VP_CTL,
96062306a36Sopenharmony_ci					CS35L35_CH_VP_MAN_MASK,
96162306a36Sopenharmony_ci					classh->classh_vpch_man <<
96262306a36Sopenharmony_ci					CS35L35_CH_VP_MAN_SHIFT);
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	if (monitor_config->is_present) {
96662306a36Sopenharmony_ci		if (monitor_config->vmon_specs) {
96762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
96862306a36Sopenharmony_ci					CS35L35_SPKMON_DEPTH_CTL,
96962306a36Sopenharmony_ci					CS35L35_VMON_DEPTH_MASK,
97062306a36Sopenharmony_ci					monitor_config->vmon_dpth <<
97162306a36Sopenharmony_ci					CS35L35_VMON_DEPTH_SHIFT);
97262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
97362306a36Sopenharmony_ci					CS35L35_VMON_TXLOC_CTL,
97462306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
97562306a36Sopenharmony_ci					monitor_config->vmon_loc <<
97662306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
97762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
97862306a36Sopenharmony_ci					CS35L35_VMON_TXLOC_CTL,
97962306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
98062306a36Sopenharmony_ci					monitor_config->vmon_frm <<
98162306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
98262306a36Sopenharmony_ci		}
98362306a36Sopenharmony_ci		if (monitor_config->imon_specs) {
98462306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
98562306a36Sopenharmony_ci					CS35L35_SPKMON_DEPTH_CTL,
98662306a36Sopenharmony_ci					CS35L35_IMON_DEPTH_MASK,
98762306a36Sopenharmony_ci					monitor_config->imon_dpth <<
98862306a36Sopenharmony_ci					CS35L35_IMON_DEPTH_SHIFT);
98962306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
99062306a36Sopenharmony_ci					CS35L35_IMON_TXLOC_CTL,
99162306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
99262306a36Sopenharmony_ci					monitor_config->imon_loc <<
99362306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
99462306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
99562306a36Sopenharmony_ci					CS35L35_IMON_TXLOC_CTL,
99662306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
99762306a36Sopenharmony_ci					monitor_config->imon_frm <<
99862306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
99962306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
100062306a36Sopenharmony_ci					CS35L35_IMON_SCALE_CTL,
100162306a36Sopenharmony_ci					CS35L35_IMON_SCALE_MASK,
100262306a36Sopenharmony_ci					monitor_config->imon_scale <<
100362306a36Sopenharmony_ci					CS35L35_IMON_SCALE_SHIFT);
100462306a36Sopenharmony_ci		}
100562306a36Sopenharmony_ci		if (monitor_config->vpmon_specs) {
100662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
100762306a36Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
100862306a36Sopenharmony_ci					CS35L35_VPMON_DEPTH_MASK,
100962306a36Sopenharmony_ci					monitor_config->vpmon_dpth <<
101062306a36Sopenharmony_ci					CS35L35_VPMON_DEPTH_SHIFT);
101162306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
101262306a36Sopenharmony_ci					CS35L35_VPMON_TXLOC_CTL,
101362306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
101462306a36Sopenharmony_ci					monitor_config->vpmon_loc <<
101562306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
101662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
101762306a36Sopenharmony_ci					CS35L35_VPMON_TXLOC_CTL,
101862306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
101962306a36Sopenharmony_ci					monitor_config->vpmon_frm <<
102062306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
102162306a36Sopenharmony_ci		}
102262306a36Sopenharmony_ci		if (monitor_config->vbstmon_specs) {
102362306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
102462306a36Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
102562306a36Sopenharmony_ci					CS35L35_VBSTMON_DEPTH_MASK,
102662306a36Sopenharmony_ci					monitor_config->vpmon_dpth <<
102762306a36Sopenharmony_ci					CS35L35_VBSTMON_DEPTH_SHIFT);
102862306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
102962306a36Sopenharmony_ci					CS35L35_VBSTMON_TXLOC_CTL,
103062306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
103162306a36Sopenharmony_ci					monitor_config->vbstmon_loc <<
103262306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
103362306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
103462306a36Sopenharmony_ci					CS35L35_VBSTMON_TXLOC_CTL,
103562306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
103662306a36Sopenharmony_ci					monitor_config->vbstmon_frm <<
103762306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
103862306a36Sopenharmony_ci		}
103962306a36Sopenharmony_ci		if (monitor_config->vpbrstat_specs) {
104062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
104162306a36Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
104262306a36Sopenharmony_ci					CS35L35_VPBRSTAT_DEPTH_MASK,
104362306a36Sopenharmony_ci					monitor_config->vpbrstat_dpth <<
104462306a36Sopenharmony_ci					CS35L35_VPBRSTAT_DEPTH_SHIFT);
104562306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
104662306a36Sopenharmony_ci					CS35L35_VPBR_STATUS_TXLOC_CTL,
104762306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
104862306a36Sopenharmony_ci					monitor_config->vpbrstat_loc <<
104962306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
105062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
105162306a36Sopenharmony_ci					CS35L35_VPBR_STATUS_TXLOC_CTL,
105262306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
105362306a36Sopenharmony_ci					monitor_config->vpbrstat_frm <<
105462306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci		if (monitor_config->zerofill_specs) {
105762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
105862306a36Sopenharmony_ci					CS35L35_SUPMON_DEPTH_CTL,
105962306a36Sopenharmony_ci					CS35L35_ZEROFILL_DEPTH_MASK,
106062306a36Sopenharmony_ci					monitor_config->zerofill_dpth <<
106162306a36Sopenharmony_ci					CS35L35_ZEROFILL_DEPTH_SHIFT);
106262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
106362306a36Sopenharmony_ci					CS35L35_ZERO_FILL_LOC_CTL,
106462306a36Sopenharmony_ci					CS35L35_MON_TXLOC_MASK,
106562306a36Sopenharmony_ci					monitor_config->zerofill_loc <<
106662306a36Sopenharmony_ci					CS35L35_MON_TXLOC_SHIFT);
106762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
106862306a36Sopenharmony_ci					CS35L35_ZERO_FILL_LOC_CTL,
106962306a36Sopenharmony_ci					CS35L35_MON_FRM_MASK,
107062306a36Sopenharmony_ci					monitor_config->zerofill_frm <<
107162306a36Sopenharmony_ci					CS35L35_MON_FRM_SHIFT);
107262306a36Sopenharmony_ci		}
107362306a36Sopenharmony_ci	}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	return 0;
107662306a36Sopenharmony_ci}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_cs35l35 = {
107962306a36Sopenharmony_ci	.probe			= cs35l35_component_probe,
108062306a36Sopenharmony_ci	.set_sysclk		= cs35l35_component_set_sysclk,
108162306a36Sopenharmony_ci	.dapm_widgets		= cs35l35_dapm_widgets,
108262306a36Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(cs35l35_dapm_widgets),
108362306a36Sopenharmony_ci	.dapm_routes		= cs35l35_audio_map,
108462306a36Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(cs35l35_audio_map),
108562306a36Sopenharmony_ci	.controls		= cs35l35_aud_controls,
108662306a36Sopenharmony_ci	.num_controls		= ARRAY_SIZE(cs35l35_aud_controls),
108762306a36Sopenharmony_ci	.idle_bias_on		= 1,
108862306a36Sopenharmony_ci	.use_pmdown_time	= 1,
108962306a36Sopenharmony_ci	.endianness		= 1,
109062306a36Sopenharmony_ci};
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_cistatic struct regmap_config cs35l35_regmap = {
109362306a36Sopenharmony_ci	.reg_bits = 8,
109462306a36Sopenharmony_ci	.val_bits = 8,
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	.max_register = CS35L35_MAX_REGISTER,
109762306a36Sopenharmony_ci	.reg_defaults = cs35l35_reg,
109862306a36Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(cs35l35_reg),
109962306a36Sopenharmony_ci	.volatile_reg = cs35l35_volatile_register,
110062306a36Sopenharmony_ci	.readable_reg = cs35l35_readable_register,
110162306a36Sopenharmony_ci	.precious_reg = cs35l35_precious_register,
110262306a36Sopenharmony_ci	.cache_type = REGCACHE_MAPLE,
110362306a36Sopenharmony_ci	.use_single_read = true,
110462306a36Sopenharmony_ci	.use_single_write = true,
110562306a36Sopenharmony_ci};
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_cistatic irqreturn_t cs35l35_irq(int irq, void *data)
110862306a36Sopenharmony_ci{
110962306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = data;
111062306a36Sopenharmony_ci	unsigned int sticky1, sticky2, sticky3, sticky4;
111162306a36Sopenharmony_ci	unsigned int mask1, mask2, mask3, mask4, current1;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	/* ack the irq by reading all status registers */
111462306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_4, &sticky4);
111562306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_3, &sticky3);
111662306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_2, &sticky2);
111762306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, &sticky1);
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_4, &mask4);
112062306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_3, &mask3);
112162306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_2, &mask2);
112262306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_MASK_1, &mask1);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	/* Check to see if unmasked bits are active */
112562306a36Sopenharmony_ci	if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3)
112662306a36Sopenharmony_ci			&& !(sticky4 & ~mask4))
112762306a36Sopenharmony_ci		return IRQ_NONE;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	if (sticky2 & CS35L35_PDN_DONE)
113062306a36Sopenharmony_ci		complete(&cs35l35->pdn_done);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* read the current values */
113362306a36Sopenharmony_ci	regmap_read(cs35l35->regmap, CS35L35_INT_STATUS_1, &current1);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	/* handle the interrupts */
113662306a36Sopenharmony_ci	if (sticky1 & CS35L35_CAL_ERR) {
113762306a36Sopenharmony_ci		dev_crit(cs35l35->dev, "Calibration Error\n");
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci		/* error is no longer asserted; safe to reset */
114062306a36Sopenharmony_ci		if (!(current1 & CS35L35_CAL_ERR)) {
114162306a36Sopenharmony_ci			pr_debug("%s : Cal error release\n", __func__);
114262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
114362306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
114462306a36Sopenharmony_ci					CS35L35_CAL_ERR_RLS, 0);
114562306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
114662306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
114762306a36Sopenharmony_ci					CS35L35_CAL_ERR_RLS,
114862306a36Sopenharmony_ci					CS35L35_CAL_ERR_RLS);
114962306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
115062306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
115162306a36Sopenharmony_ci					CS35L35_CAL_ERR_RLS, 0);
115262306a36Sopenharmony_ci		}
115362306a36Sopenharmony_ci	}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	if (sticky1 & CS35L35_AMP_SHORT) {
115662306a36Sopenharmony_ci		dev_crit(cs35l35->dev, "AMP Short Error\n");
115762306a36Sopenharmony_ci		/* error is no longer asserted; safe to reset */
115862306a36Sopenharmony_ci		if (!(current1 & CS35L35_AMP_SHORT)) {
115962306a36Sopenharmony_ci			dev_dbg(cs35l35->dev, "Amp short error release\n");
116062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
116162306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
116262306a36Sopenharmony_ci					CS35L35_SHORT_RLS, 0);
116362306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
116462306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
116562306a36Sopenharmony_ci					CS35L35_SHORT_RLS,
116662306a36Sopenharmony_ci					CS35L35_SHORT_RLS);
116762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
116862306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
116962306a36Sopenharmony_ci					CS35L35_SHORT_RLS, 0);
117062306a36Sopenharmony_ci		}
117162306a36Sopenharmony_ci	}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (sticky1 & CS35L35_OTW) {
117462306a36Sopenharmony_ci		dev_warn(cs35l35->dev, "Over temperature warning\n");
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci		/* error is no longer asserted; safe to reset */
117762306a36Sopenharmony_ci		if (!(current1 & CS35L35_OTW)) {
117862306a36Sopenharmony_ci			dev_dbg(cs35l35->dev, "Over temperature warn release\n");
117962306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
118062306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
118162306a36Sopenharmony_ci					CS35L35_OTW_RLS, 0);
118262306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
118362306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
118462306a36Sopenharmony_ci					CS35L35_OTW_RLS,
118562306a36Sopenharmony_ci					CS35L35_OTW_RLS);
118662306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
118762306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
118862306a36Sopenharmony_ci					CS35L35_OTW_RLS, 0);
118962306a36Sopenharmony_ci		}
119062306a36Sopenharmony_ci	}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	if (sticky1 & CS35L35_OTE) {
119362306a36Sopenharmony_ci		dev_crit(cs35l35->dev, "Over temperature error\n");
119462306a36Sopenharmony_ci		/* error is no longer asserted; safe to reset */
119562306a36Sopenharmony_ci		if (!(current1 & CS35L35_OTE)) {
119662306a36Sopenharmony_ci			dev_dbg(cs35l35->dev, "Over temperature error release\n");
119762306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
119862306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
119962306a36Sopenharmony_ci					CS35L35_OTE_RLS, 0);
120062306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
120162306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
120262306a36Sopenharmony_ci					CS35L35_OTE_RLS,
120362306a36Sopenharmony_ci					CS35L35_OTE_RLS);
120462306a36Sopenharmony_ci			regmap_update_bits(cs35l35->regmap,
120562306a36Sopenharmony_ci					CS35L35_PROT_RELEASE_CTL,
120662306a36Sopenharmony_ci					CS35L35_OTE_RLS, 0);
120762306a36Sopenharmony_ci		}
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	if (sticky3 & CS35L35_BST_HIGH) {
121162306a36Sopenharmony_ci		dev_crit(cs35l35->dev, "VBST error: powering off!\n");
121262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
121362306a36Sopenharmony_ci			CS35L35_PDN_AMP, CS35L35_PDN_AMP);
121462306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
121562306a36Sopenharmony_ci			CS35L35_PDN_ALL, CS35L35_PDN_ALL);
121662306a36Sopenharmony_ci	}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	if (sticky3 & CS35L35_LBST_SHORT) {
121962306a36Sopenharmony_ci		dev_crit(cs35l35->dev, "LBST error: powering off!\n");
122062306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
122162306a36Sopenharmony_ci			CS35L35_PDN_AMP, CS35L35_PDN_AMP);
122262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL1,
122362306a36Sopenharmony_ci			CS35L35_PDN_ALL, CS35L35_PDN_ALL);
122462306a36Sopenharmony_ci	}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	if (sticky2 & CS35L35_VPBR_ERR)
122762306a36Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: Reactive Brownout\n");
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	if (sticky4 & CS35L35_VMON_OVFL)
123062306a36Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: VMON overflow\n");
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	if (sticky4 & CS35L35_IMON_OVFL)
123362306a36Sopenharmony_ci		dev_dbg(cs35l35->dev, "Error: IMON overflow\n");
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	return IRQ_HANDLED;
123662306a36Sopenharmony_ci}
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic int cs35l35_handle_of_data(struct i2c_client *i2c_client,
124062306a36Sopenharmony_ci				struct cs35l35_platform_data *pdata)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	struct device_node *np = i2c_client->dev.of_node;
124362306a36Sopenharmony_ci	struct device_node *classh, *signal_format;
124462306a36Sopenharmony_ci	struct classh_cfg *classh_config = &pdata->classh_algo;
124562306a36Sopenharmony_ci	struct monitor_cfg *monitor_config = &pdata->mon_cfg;
124662306a36Sopenharmony_ci	unsigned int val32 = 0;
124762306a36Sopenharmony_ci	u8 monitor_array[4];
124862306a36Sopenharmony_ci	const int imon_array_size = ARRAY_SIZE(monitor_array);
124962306a36Sopenharmony_ci	const int mon_array_size = imon_array_size - 1;
125062306a36Sopenharmony_ci	int ret = 0;
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (!np)
125362306a36Sopenharmony_ci		return 0;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	pdata->bst_pdn_fet_on = of_property_read_bool(np,
125662306a36Sopenharmony_ci					"cirrus,boost-pdn-fet-on");
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ctl-millivolt", &val32);
125962306a36Sopenharmony_ci	if (ret >= 0) {
126062306a36Sopenharmony_ci		if (val32 < 2600 || val32 > 9000) {
126162306a36Sopenharmony_ci			dev_err(&i2c_client->dev,
126262306a36Sopenharmony_ci				"Invalid Boost Voltage %d mV\n", val32);
126362306a36Sopenharmony_ci			return -EINVAL;
126462306a36Sopenharmony_ci		}
126562306a36Sopenharmony_ci		pdata->bst_vctl = ((val32 - 2600) / 100) + 1;
126662306a36Sopenharmony_ci	}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val32);
126962306a36Sopenharmony_ci	if (ret >= 0) {
127062306a36Sopenharmony_ci		if (val32 < 1680 || val32 > 4480) {
127162306a36Sopenharmony_ci			dev_err(&i2c_client->dev,
127262306a36Sopenharmony_ci				"Invalid Boost Peak Current %u mA\n", val32);
127362306a36Sopenharmony_ci			return -EINVAL;
127462306a36Sopenharmony_ci		}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci		pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA;
127762306a36Sopenharmony_ci	}
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);
128062306a36Sopenharmony_ci	if (ret >= 0) {
128162306a36Sopenharmony_ci		pdata->boost_ind = val32;
128262306a36Sopenharmony_ci	} else {
128362306a36Sopenharmony_ci		dev_err(&i2c_client->dev, "Inductor not specified.\n");
128462306a36Sopenharmony_ci		return -EINVAL;
128562306a36Sopenharmony_ci	}
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)
128862306a36Sopenharmony_ci		pdata->sp_drv_str = val32;
128962306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0)
129062306a36Sopenharmony_ci		pdata->sp_drv_unused = val32 | CS35L35_VALID_PDATA;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	pdata->stereo = of_property_read_bool(np, "cirrus,stereo-config");
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	if (pdata->stereo) {
129562306a36Sopenharmony_ci		ret = of_property_read_u32(np, "cirrus,audio-channel", &val32);
129662306a36Sopenharmony_ci		if (ret >= 0)
129762306a36Sopenharmony_ci			pdata->aud_channel = val32;
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci		ret = of_property_read_u32(np, "cirrus,advisory-channel",
130062306a36Sopenharmony_ci					   &val32);
130162306a36Sopenharmony_ci		if (ret >= 0)
130262306a36Sopenharmony_ci			pdata->adv_channel = val32;
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci		pdata->shared_bst = of_property_read_bool(np,
130562306a36Sopenharmony_ci						"cirrus,shared-boost");
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	pdata->ext_bst = of_property_read_bool(np, "cirrus,external-boost");
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	pdata->gain_zc = of_property_read_bool(np, "cirrus,amp-gain-zc");
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	classh = of_get_child_by_name(np, "cirrus,classh-internal-algo");
131362306a36Sopenharmony_ci	classh_config->classh_algo_enable = (classh != NULL);
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	if (classh_config->classh_algo_enable) {
131662306a36Sopenharmony_ci		classh_config->classh_bst_override =
131762306a36Sopenharmony_ci			of_property_read_bool(np, "cirrus,classh-bst-overide");
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci		ret = of_property_read_u32(classh,
132062306a36Sopenharmony_ci					   "cirrus,classh-bst-max-limit",
132162306a36Sopenharmony_ci					   &val32);
132262306a36Sopenharmony_ci		if (ret >= 0) {
132362306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
132462306a36Sopenharmony_ci			classh_config->classh_bst_max_limit = val32;
132562306a36Sopenharmony_ci		}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci		ret = of_property_read_u32(classh,
132862306a36Sopenharmony_ci					   "cirrus,classh-bst-max-limit",
132962306a36Sopenharmony_ci					   &val32);
133062306a36Sopenharmony_ci		if (ret >= 0) {
133162306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
133262306a36Sopenharmony_ci			classh_config->classh_bst_max_limit = val32;
133362306a36Sopenharmony_ci		}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-mem-depth",
133662306a36Sopenharmony_ci					   &val32);
133762306a36Sopenharmony_ci		if (ret >= 0) {
133862306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
133962306a36Sopenharmony_ci			classh_config->classh_mem_depth = val32;
134062306a36Sopenharmony_ci		}
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-release-rate",
134362306a36Sopenharmony_ci					   &val32);
134462306a36Sopenharmony_ci		if (ret >= 0)
134562306a36Sopenharmony_ci			classh_config->classh_release_rate = val32;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-headroom",
134862306a36Sopenharmony_ci					   &val32);
134962306a36Sopenharmony_ci		if (ret >= 0) {
135062306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
135162306a36Sopenharmony_ci			classh_config->classh_headroom = val32;
135262306a36Sopenharmony_ci		}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci		ret = of_property_read_u32(classh,
135562306a36Sopenharmony_ci					   "cirrus,classh-wk-fet-disable",
135662306a36Sopenharmony_ci					   &val32);
135762306a36Sopenharmony_ci		if (ret >= 0)
135862306a36Sopenharmony_ci			classh_config->classh_wk_fet_disable = val32;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-delay",
136162306a36Sopenharmony_ci					   &val32);
136262306a36Sopenharmony_ci		if (ret >= 0) {
136362306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
136462306a36Sopenharmony_ci			classh_config->classh_wk_fet_delay = val32;
136562306a36Sopenharmony_ci		}
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-wk-fet-thld",
136862306a36Sopenharmony_ci					   &val32);
136962306a36Sopenharmony_ci		if (ret >= 0)
137062306a36Sopenharmony_ci			classh_config->classh_wk_fet_thld = val32;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-auto",
137362306a36Sopenharmony_ci					   &val32);
137462306a36Sopenharmony_ci		if (ret >= 0) {
137562306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
137662306a36Sopenharmony_ci			classh_config->classh_vpch_auto = val32;
137762306a36Sopenharmony_ci		}
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-rate",
138062306a36Sopenharmony_ci					   &val32);
138162306a36Sopenharmony_ci		if (ret >= 0) {
138262306a36Sopenharmony_ci			val32 |= CS35L35_VALID_PDATA;
138362306a36Sopenharmony_ci			classh_config->classh_vpch_rate = val32;
138462306a36Sopenharmony_ci		}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci		ret = of_property_read_u32(classh, "cirrus,classh-vpch-man",
138762306a36Sopenharmony_ci					   &val32);
138862306a36Sopenharmony_ci		if (ret >= 0)
138962306a36Sopenharmony_ci			classh_config->classh_vpch_man = val32;
139062306a36Sopenharmony_ci	}
139162306a36Sopenharmony_ci	of_node_put(classh);
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	/* frame depth location */
139462306a36Sopenharmony_ci	signal_format = of_get_child_by_name(np, "cirrus,monitor-signal-format");
139562306a36Sopenharmony_ci	monitor_config->is_present = signal_format ? true : false;
139662306a36Sopenharmony_ci	if (monitor_config->is_present) {
139762306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,imon",
139862306a36Sopenharmony_ci						monitor_array, imon_array_size);
139962306a36Sopenharmony_ci		if (!ret) {
140062306a36Sopenharmony_ci			monitor_config->imon_specs = true;
140162306a36Sopenharmony_ci			monitor_config->imon_dpth = monitor_array[0];
140262306a36Sopenharmony_ci			monitor_config->imon_loc = monitor_array[1];
140362306a36Sopenharmony_ci			monitor_config->imon_frm = monitor_array[2];
140462306a36Sopenharmony_ci			monitor_config->imon_scale = monitor_array[3];
140562306a36Sopenharmony_ci		}
140662306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vmon",
140762306a36Sopenharmony_ci						monitor_array, mon_array_size);
140862306a36Sopenharmony_ci		if (!ret) {
140962306a36Sopenharmony_ci			monitor_config->vmon_specs = true;
141062306a36Sopenharmony_ci			monitor_config->vmon_dpth = monitor_array[0];
141162306a36Sopenharmony_ci			monitor_config->vmon_loc = monitor_array[1];
141262306a36Sopenharmony_ci			monitor_config->vmon_frm = monitor_array[2];
141362306a36Sopenharmony_ci		}
141462306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vpmon",
141562306a36Sopenharmony_ci						monitor_array, mon_array_size);
141662306a36Sopenharmony_ci		if (!ret) {
141762306a36Sopenharmony_ci			monitor_config->vpmon_specs = true;
141862306a36Sopenharmony_ci			monitor_config->vpmon_dpth = monitor_array[0];
141962306a36Sopenharmony_ci			monitor_config->vpmon_loc = monitor_array[1];
142062306a36Sopenharmony_ci			monitor_config->vpmon_frm = monitor_array[2];
142162306a36Sopenharmony_ci		}
142262306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vbstmon",
142362306a36Sopenharmony_ci						monitor_array, mon_array_size);
142462306a36Sopenharmony_ci		if (!ret) {
142562306a36Sopenharmony_ci			monitor_config->vbstmon_specs = true;
142662306a36Sopenharmony_ci			monitor_config->vbstmon_dpth = monitor_array[0];
142762306a36Sopenharmony_ci			monitor_config->vbstmon_loc = monitor_array[1];
142862306a36Sopenharmony_ci			monitor_config->vbstmon_frm = monitor_array[2];
142962306a36Sopenharmony_ci		}
143062306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,vpbrstat",
143162306a36Sopenharmony_ci						monitor_array, mon_array_size);
143262306a36Sopenharmony_ci		if (!ret) {
143362306a36Sopenharmony_ci			monitor_config->vpbrstat_specs = true;
143462306a36Sopenharmony_ci			monitor_config->vpbrstat_dpth = monitor_array[0];
143562306a36Sopenharmony_ci			monitor_config->vpbrstat_loc = monitor_array[1];
143662306a36Sopenharmony_ci			monitor_config->vpbrstat_frm = monitor_array[2];
143762306a36Sopenharmony_ci		}
143862306a36Sopenharmony_ci		ret = of_property_read_u8_array(signal_format, "cirrus,zerofill",
143962306a36Sopenharmony_ci						monitor_array, mon_array_size);
144062306a36Sopenharmony_ci		if (!ret) {
144162306a36Sopenharmony_ci			monitor_config->zerofill_specs = true;
144262306a36Sopenharmony_ci			monitor_config->zerofill_dpth = monitor_array[0];
144362306a36Sopenharmony_ci			monitor_config->zerofill_loc = monitor_array[1];
144462306a36Sopenharmony_ci			monitor_config->zerofill_frm = monitor_array[2];
144562306a36Sopenharmony_ci		}
144662306a36Sopenharmony_ci	}
144762306a36Sopenharmony_ci	of_node_put(signal_format);
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return 0;
145062306a36Sopenharmony_ci}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci/* Errata Rev A0 */
145362306a36Sopenharmony_cistatic const struct reg_sequence cs35l35_errata_patch[] = {
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	{ 0x7F, 0x99 },
145662306a36Sopenharmony_ci	{ 0x00, 0x99 },
145762306a36Sopenharmony_ci	{ 0x52, 0x22 },
145862306a36Sopenharmony_ci	{ 0x04, 0x14 },
145962306a36Sopenharmony_ci	{ 0x6D, 0x44 },
146062306a36Sopenharmony_ci	{ 0x24, 0x10 },
146162306a36Sopenharmony_ci	{ 0x58, 0xC4 },
146262306a36Sopenharmony_ci	{ 0x00, 0x98 },
146362306a36Sopenharmony_ci	{ 0x18, 0x08 },
146462306a36Sopenharmony_ci	{ 0x00, 0x00 },
146562306a36Sopenharmony_ci	{ 0x7F, 0x00 },
146662306a36Sopenharmony_ci};
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_cistatic int cs35l35_i2c_probe(struct i2c_client *i2c_client)
146962306a36Sopenharmony_ci{
147062306a36Sopenharmony_ci	struct cs35l35_private *cs35l35;
147162306a36Sopenharmony_ci	struct device *dev = &i2c_client->dev;
147262306a36Sopenharmony_ci	struct cs35l35_platform_data *pdata = dev_get_platdata(dev);
147362306a36Sopenharmony_ci	int i, devid;
147462306a36Sopenharmony_ci	int ret;
147562306a36Sopenharmony_ci	unsigned int reg;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	cs35l35 = devm_kzalloc(dev, sizeof(struct cs35l35_private), GFP_KERNEL);
147862306a36Sopenharmony_ci	if (!cs35l35)
147962306a36Sopenharmony_ci		return -ENOMEM;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	cs35l35->dev = dev;
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	i2c_set_clientdata(i2c_client, cs35l35);
148462306a36Sopenharmony_ci	cs35l35->regmap = devm_regmap_init_i2c(i2c_client, &cs35l35_regmap);
148562306a36Sopenharmony_ci	if (IS_ERR(cs35l35->regmap)) {
148662306a36Sopenharmony_ci		ret = PTR_ERR(cs35l35->regmap);
148762306a36Sopenharmony_ci		dev_err(dev, "regmap_init() failed: %d\n", ret);
148862306a36Sopenharmony_ci		return ret;
148962306a36Sopenharmony_ci	}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l35_supplies); i++)
149262306a36Sopenharmony_ci		cs35l35->supplies[i].supply = cs35l35_supplies[i];
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	cs35l35->num_supplies = ARRAY_SIZE(cs35l35_supplies);
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	ret = devm_regulator_bulk_get(dev, cs35l35->num_supplies,
149762306a36Sopenharmony_ci				      cs35l35->supplies);
149862306a36Sopenharmony_ci	if (ret != 0) {
149962306a36Sopenharmony_ci		dev_err(dev, "Failed to request core supplies: %d\n", ret);
150062306a36Sopenharmony_ci		return ret;
150162306a36Sopenharmony_ci	}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	if (pdata) {
150462306a36Sopenharmony_ci		cs35l35->pdata = *pdata;
150562306a36Sopenharmony_ci	} else {
150662306a36Sopenharmony_ci		pdata = devm_kzalloc(dev, sizeof(struct cs35l35_platform_data),
150762306a36Sopenharmony_ci				     GFP_KERNEL);
150862306a36Sopenharmony_ci		if (!pdata)
150962306a36Sopenharmony_ci			return -ENOMEM;
151062306a36Sopenharmony_ci		if (i2c_client->dev.of_node) {
151162306a36Sopenharmony_ci			ret = cs35l35_handle_of_data(i2c_client, pdata);
151262306a36Sopenharmony_ci			if (ret != 0)
151362306a36Sopenharmony_ci				return ret;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci		}
151662306a36Sopenharmony_ci		cs35l35->pdata = *pdata;
151762306a36Sopenharmony_ci	}
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	ret = regulator_bulk_enable(cs35l35->num_supplies,
152062306a36Sopenharmony_ci					cs35l35->supplies);
152162306a36Sopenharmony_ci	if (ret != 0) {
152262306a36Sopenharmony_ci		dev_err(dev, "Failed to enable core supplies: %d\n", ret);
152362306a36Sopenharmony_ci		return ret;
152462306a36Sopenharmony_ci	}
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	/* returning NULL can be valid if in stereo mode */
152762306a36Sopenharmony_ci	cs35l35->reset_gpio = devm_gpiod_get_optional(dev, "reset",
152862306a36Sopenharmony_ci						      GPIOD_OUT_LOW);
152962306a36Sopenharmony_ci	if (IS_ERR(cs35l35->reset_gpio)) {
153062306a36Sopenharmony_ci		ret = PTR_ERR(cs35l35->reset_gpio);
153162306a36Sopenharmony_ci		cs35l35->reset_gpio = NULL;
153262306a36Sopenharmony_ci		if (ret == -EBUSY) {
153362306a36Sopenharmony_ci			dev_info(dev,
153462306a36Sopenharmony_ci				 "Reset line busy, assuming shared reset\n");
153562306a36Sopenharmony_ci		} else {
153662306a36Sopenharmony_ci			dev_err(dev, "Failed to get reset GPIO: %d\n", ret);
153762306a36Sopenharmony_ci			goto err;
153862306a36Sopenharmony_ci		}
153962306a36Sopenharmony_ci	}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	cs35l35_reset(cs35l35);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	init_completion(&cs35l35->pdn_done);
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	ret = devm_request_threaded_irq(dev, i2c_client->irq, NULL, cs35l35_irq,
154662306a36Sopenharmony_ci					IRQF_ONESHOT | IRQF_TRIGGER_LOW |
154762306a36Sopenharmony_ci					IRQF_SHARED, "cs35l35", cs35l35);
154862306a36Sopenharmony_ci	if (ret != 0) {
154962306a36Sopenharmony_ci		dev_err(dev, "Failed to request IRQ: %d\n", ret);
155062306a36Sopenharmony_ci		goto err;
155162306a36Sopenharmony_ci	}
155262306a36Sopenharmony_ci	/* initialize codec */
155362306a36Sopenharmony_ci	devid = cirrus_read_device_id(cs35l35->regmap, CS35L35_DEVID_AB);
155462306a36Sopenharmony_ci	if (devid < 0) {
155562306a36Sopenharmony_ci		ret = devid;
155662306a36Sopenharmony_ci		dev_err(dev, "Failed to read device ID: %d\n", ret);
155762306a36Sopenharmony_ci		goto err;
155862306a36Sopenharmony_ci	}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	if (devid != CS35L35_CHIP_ID) {
156162306a36Sopenharmony_ci		dev_err(dev, "CS35L35 Device ID (%X). Expected ID %X\n",
156262306a36Sopenharmony_ci			devid, CS35L35_CHIP_ID);
156362306a36Sopenharmony_ci		ret = -ENODEV;
156462306a36Sopenharmony_ci		goto err;
156562306a36Sopenharmony_ci	}
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	ret = regmap_read(cs35l35->regmap, CS35L35_REV_ID, &reg);
156862306a36Sopenharmony_ci	if (ret < 0) {
156962306a36Sopenharmony_ci		dev_err(dev, "Get Revision ID failed: %d\n", ret);
157062306a36Sopenharmony_ci		goto err;
157162306a36Sopenharmony_ci	}
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	ret = regmap_register_patch(cs35l35->regmap, cs35l35_errata_patch,
157462306a36Sopenharmony_ci				    ARRAY_SIZE(cs35l35_errata_patch));
157562306a36Sopenharmony_ci	if (ret < 0) {
157662306a36Sopenharmony_ci		dev_err(dev, "Failed to apply errata patch: %d\n", ret);
157762306a36Sopenharmony_ci		goto err;
157862306a36Sopenharmony_ci	}
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	dev_info(dev, "Cirrus Logic CS35L35 (%x), Revision: %02X\n",
158162306a36Sopenharmony_ci		 devid, reg & 0xFF);
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	/* Set the INT Masks for critical errors */
158462306a36Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_1,
158562306a36Sopenharmony_ci				CS35L35_INT1_CRIT_MASK);
158662306a36Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_2,
158762306a36Sopenharmony_ci				CS35L35_INT2_CRIT_MASK);
158862306a36Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_3,
158962306a36Sopenharmony_ci				CS35L35_INT3_CRIT_MASK);
159062306a36Sopenharmony_ci	regmap_write(cs35l35->regmap, CS35L35_INT_MASK_4,
159162306a36Sopenharmony_ci				CS35L35_INT4_CRIT_MASK);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
159462306a36Sopenharmony_ci			CS35L35_PWR2_PDN_MASK,
159562306a36Sopenharmony_ci			CS35L35_PWR2_PDN_MASK);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	if (cs35l35->pdata.bst_pdn_fet_on)
159862306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
159962306a36Sopenharmony_ci					CS35L35_PDN_BST_MASK,
160062306a36Sopenharmony_ci					1 << CS35L35_PDN_BST_FETON_SHIFT);
160162306a36Sopenharmony_ci	else
160262306a36Sopenharmony_ci		regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL2,
160362306a36Sopenharmony_ci					CS35L35_PDN_BST_MASK,
160462306a36Sopenharmony_ci					1 << CS35L35_PDN_BST_FETOFF_SHIFT);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PWRCTL3,
160762306a36Sopenharmony_ci			CS35L35_PWR3_PDN_MASK,
160862306a36Sopenharmony_ci			CS35L35_PWR3_PDN_MASK);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
161162306a36Sopenharmony_ci		CS35L35_AMP_MUTE_MASK, 1 << CS35L35_AMP_MUTE_SHIFT);
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	ret = devm_snd_soc_register_component(dev, &soc_component_dev_cs35l35,
161462306a36Sopenharmony_ci					cs35l35_dai, ARRAY_SIZE(cs35l35_dai));
161562306a36Sopenharmony_ci	if (ret < 0) {
161662306a36Sopenharmony_ci		dev_err(dev, "Failed to register component: %d\n", ret);
161762306a36Sopenharmony_ci		goto err;
161862306a36Sopenharmony_ci	}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	return 0;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_cierr:
162362306a36Sopenharmony_ci	regulator_bulk_disable(cs35l35->num_supplies,
162462306a36Sopenharmony_ci			       cs35l35->supplies);
162562306a36Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	return ret;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic void cs35l35_i2c_remove(struct i2c_client *i2c_client)
163162306a36Sopenharmony_ci{
163262306a36Sopenharmony_ci	struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client);
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies);
163562306a36Sopenharmony_ci	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
163662306a36Sopenharmony_ci}
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_cistatic const struct of_device_id cs35l35_of_match[] = {
163962306a36Sopenharmony_ci	{.compatible = "cirrus,cs35l35"},
164062306a36Sopenharmony_ci	{},
164162306a36Sopenharmony_ci};
164262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cs35l35_of_match);
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_cistatic const struct i2c_device_id cs35l35_id[] = {
164562306a36Sopenharmony_ci	{"cs35l35", 0},
164662306a36Sopenharmony_ci	{}
164762306a36Sopenharmony_ci};
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, cs35l35_id);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_cistatic struct i2c_driver cs35l35_i2c_driver = {
165262306a36Sopenharmony_ci	.driver = {
165362306a36Sopenharmony_ci		.name = "cs35l35",
165462306a36Sopenharmony_ci		.of_match_table = cs35l35_of_match,
165562306a36Sopenharmony_ci	},
165662306a36Sopenharmony_ci	.id_table = cs35l35_id,
165762306a36Sopenharmony_ci	.probe = cs35l35_i2c_probe,
165862306a36Sopenharmony_ci	.remove = cs35l35_i2c_remove,
165962306a36Sopenharmony_ci};
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_cimodule_i2c_driver(cs35l35_i2c_driver);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC CS35L35 driver");
166462306a36Sopenharmony_ciMODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
166562306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1666