162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// cs35l36.c -- CS35L36 ALSA SoC audio driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2018 Cirrus Logic, Inc.
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci// Author: James Schulman <james.schulman@cirrus.com>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/moduleparam.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci#include <linux/i2c.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/workqueue.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/cs35l36.h>
3262306a36Sopenharmony_ci#include <linux/of_irq.h>
3362306a36Sopenharmony_ci#include <linux/completion.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "cs35l36.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * Some fields take zero as a valid value so use a high bit flag that won't
3962306a36Sopenharmony_ci * get written to the device to mark those.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci#define CS35L36_VALID_PDATA 0x80000000
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic const char * const cs35l36_supplies[] = {
4462306a36Sopenharmony_ci	"VA",
4562306a36Sopenharmony_ci	"VP",
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistruct  cs35l36_private {
4962306a36Sopenharmony_ci	struct device *dev;
5062306a36Sopenharmony_ci	struct cs35l36_platform_data pdata;
5162306a36Sopenharmony_ci	struct regmap *regmap;
5262306a36Sopenharmony_ci	struct regulator_bulk_data supplies[2];
5362306a36Sopenharmony_ci	int num_supplies;
5462306a36Sopenharmony_ci	int clksrc;
5562306a36Sopenharmony_ci	int chip_version;
5662306a36Sopenharmony_ci	int rev_id;
5762306a36Sopenharmony_ci	int ldm_mode_sel;
5862306a36Sopenharmony_ci	struct gpio_desc *reset_gpio;
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistruct cs35l36_pll_config {
6262306a36Sopenharmony_ci	int freq;
6362306a36Sopenharmony_ci	int clk_cfg;
6462306a36Sopenharmony_ci	int fll_igain;
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic const struct cs35l36_pll_config cs35l36_pll_sysclk[] = {
6862306a36Sopenharmony_ci	{32768,		0x00, 0x05},
6962306a36Sopenharmony_ci	{8000,		0x01, 0x03},
7062306a36Sopenharmony_ci	{11025,		0x02, 0x03},
7162306a36Sopenharmony_ci	{12000,		0x03, 0x03},
7262306a36Sopenharmony_ci	{16000,		0x04, 0x04},
7362306a36Sopenharmony_ci	{22050,		0x05, 0x04},
7462306a36Sopenharmony_ci	{24000,		0x06, 0x04},
7562306a36Sopenharmony_ci	{32000,		0x07, 0x05},
7662306a36Sopenharmony_ci	{44100,		0x08, 0x05},
7762306a36Sopenharmony_ci	{48000,		0x09, 0x05},
7862306a36Sopenharmony_ci	{88200,		0x0A, 0x06},
7962306a36Sopenharmony_ci	{96000,		0x0B, 0x06},
8062306a36Sopenharmony_ci	{128000,	0x0C, 0x07},
8162306a36Sopenharmony_ci	{176400,	0x0D, 0x07},
8262306a36Sopenharmony_ci	{192000,	0x0E, 0x07},
8362306a36Sopenharmony_ci	{256000,	0x0F, 0x08},
8462306a36Sopenharmony_ci	{352800,	0x10, 0x08},
8562306a36Sopenharmony_ci	{384000,	0x11, 0x08},
8662306a36Sopenharmony_ci	{512000,	0x12, 0x09},
8762306a36Sopenharmony_ci	{705600,	0x13, 0x09},
8862306a36Sopenharmony_ci	{750000,	0x14, 0x09},
8962306a36Sopenharmony_ci	{768000,	0x15, 0x09},
9062306a36Sopenharmony_ci	{1000000,	0x16, 0x0A},
9162306a36Sopenharmony_ci	{1024000,	0x17, 0x0A},
9262306a36Sopenharmony_ci	{1200000,	0x18, 0x0A},
9362306a36Sopenharmony_ci	{1411200,	0x19, 0x0A},
9462306a36Sopenharmony_ci	{1500000,	0x1A, 0x0A},
9562306a36Sopenharmony_ci	{1536000,	0x1B, 0x0A},
9662306a36Sopenharmony_ci	{2000000,	0x1C, 0x0A},
9762306a36Sopenharmony_ci	{2048000,	0x1D, 0x0A},
9862306a36Sopenharmony_ci	{2400000,	0x1E, 0x0A},
9962306a36Sopenharmony_ci	{2822400,	0x1F, 0x0A},
10062306a36Sopenharmony_ci	{3000000,	0x20, 0x0A},
10162306a36Sopenharmony_ci	{3072000,	0x21, 0x0A},
10262306a36Sopenharmony_ci	{3200000,	0x22, 0x0A},
10362306a36Sopenharmony_ci	{4000000,	0x23, 0x0A},
10462306a36Sopenharmony_ci	{4096000,	0x24, 0x0A},
10562306a36Sopenharmony_ci	{4800000,	0x25, 0x0A},
10662306a36Sopenharmony_ci	{5644800,	0x26, 0x0A},
10762306a36Sopenharmony_ci	{6000000,	0x27, 0x0A},
10862306a36Sopenharmony_ci	{6144000,	0x28, 0x0A},
10962306a36Sopenharmony_ci	{6250000,	0x29, 0x08},
11062306a36Sopenharmony_ci	{6400000,	0x2A, 0x0A},
11162306a36Sopenharmony_ci	{6500000,	0x2B, 0x08},
11262306a36Sopenharmony_ci	{6750000,	0x2C, 0x09},
11362306a36Sopenharmony_ci	{7526400,	0x2D, 0x0A},
11462306a36Sopenharmony_ci	{8000000,	0x2E, 0x0A},
11562306a36Sopenharmony_ci	{8192000,	0x2F, 0x0A},
11662306a36Sopenharmony_ci	{9600000,	0x30, 0x0A},
11762306a36Sopenharmony_ci	{11289600,	0x31, 0x0A},
11862306a36Sopenharmony_ci	{12000000,	0x32, 0x0A},
11962306a36Sopenharmony_ci	{12288000,	0x33, 0x0A},
12062306a36Sopenharmony_ci	{12500000,	0x34, 0x08},
12162306a36Sopenharmony_ci	{12800000,	0x35, 0x0A},
12262306a36Sopenharmony_ci	{13000000,	0x36, 0x0A},
12362306a36Sopenharmony_ci	{13500000,	0x37, 0x0A},
12462306a36Sopenharmony_ci	{19200000,	0x38, 0x0A},
12562306a36Sopenharmony_ci	{22579200,	0x39, 0x0A},
12662306a36Sopenharmony_ci	{24000000,	0x3A, 0x0A},
12762306a36Sopenharmony_ci	{24576000,	0x3B, 0x0A},
12862306a36Sopenharmony_ci	{25000000,	0x3C, 0x0A},
12962306a36Sopenharmony_ci	{25600000,	0x3D, 0x0A},
13062306a36Sopenharmony_ci	{26000000,	0x3E, 0x0A},
13162306a36Sopenharmony_ci	{27000000,	0x3F, 0x0A},
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic struct reg_default cs35l36_reg[] = {
13562306a36Sopenharmony_ci	{CS35L36_TESTKEY_CTRL,			0x00000000},
13662306a36Sopenharmony_ci	{CS35L36_USERKEY_CTL,			0x00000000},
13762306a36Sopenharmony_ci	{CS35L36_OTP_CTRL1,			0x00002460},
13862306a36Sopenharmony_ci	{CS35L36_OTP_CTRL2,			0x00000000},
13962306a36Sopenharmony_ci	{CS35L36_OTP_CTRL3,			0x00000000},
14062306a36Sopenharmony_ci	{CS35L36_OTP_CTRL4,			0x00000000},
14162306a36Sopenharmony_ci	{CS35L36_OTP_CTRL5,			0x00000000},
14262306a36Sopenharmony_ci	{CS35L36_PAC_CTL1,			0x00000004},
14362306a36Sopenharmony_ci	{CS35L36_PAC_CTL2,			0x00000000},
14462306a36Sopenharmony_ci	{CS35L36_PAC_CTL3,			0x00000000},
14562306a36Sopenharmony_ci	{CS35L36_PWR_CTRL1,			0x00000000},
14662306a36Sopenharmony_ci	{CS35L36_PWR_CTRL2,			0x00003321},
14762306a36Sopenharmony_ci	{CS35L36_PWR_CTRL3,			0x01000010},
14862306a36Sopenharmony_ci	{CS35L36_CTRL_OVRRIDE,			0x00000002},
14962306a36Sopenharmony_ci	{CS35L36_AMP_OUT_MUTE,			0x00000000},
15062306a36Sopenharmony_ci	{CS35L36_OTP_TRIM_STATUS,		0x00000000},
15162306a36Sopenharmony_ci	{CS35L36_DISCH_FILT,			0x00000000},
15262306a36Sopenharmony_ci	{CS35L36_PROTECT_REL_ERR,		0x00000000},
15362306a36Sopenharmony_ci	{CS35L36_PAD_INTERFACE,			0x00000038},
15462306a36Sopenharmony_ci	{CS35L36_PLL_CLK_CTRL,			0x00000010},
15562306a36Sopenharmony_ci	{CS35L36_GLOBAL_CLK_CTRL,		0x00000003},
15662306a36Sopenharmony_ci	{CS35L36_ADC_CLK_CTRL,			0x00000000},
15762306a36Sopenharmony_ci	{CS35L36_SWIRE_CLK_CTRL,		0x00000000},
15862306a36Sopenharmony_ci	{CS35L36_SP_SCLK_CLK_CTRL,		0x00000000},
15962306a36Sopenharmony_ci	{CS35L36_MDSYNC_EN,			0x00000000},
16062306a36Sopenharmony_ci	{CS35L36_MDSYNC_TX_ID,			0x00000000},
16162306a36Sopenharmony_ci	{CS35L36_MDSYNC_PWR_CTRL,		0x00000000},
16262306a36Sopenharmony_ci	{CS35L36_MDSYNC_DATA_TX,		0x00000000},
16362306a36Sopenharmony_ci	{CS35L36_MDSYNC_TX_STATUS,		0x00000002},
16462306a36Sopenharmony_ci	{CS35L36_MDSYNC_RX_STATUS,		0x00000000},
16562306a36Sopenharmony_ci	{CS35L36_MDSYNC_ERR_STATUS,		0x00000000},
16662306a36Sopenharmony_ci	{CS35L36_BSTCVRT_VCTRL1,		0x00000000},
16762306a36Sopenharmony_ci	{CS35L36_BSTCVRT_VCTRL2,		0x00000001},
16862306a36Sopenharmony_ci	{CS35L36_BSTCVRT_PEAK_CUR,		0x0000004A},
16962306a36Sopenharmony_ci	{CS35L36_BSTCVRT_SFT_RAMP,		0x00000003},
17062306a36Sopenharmony_ci	{CS35L36_BSTCVRT_COEFF,			0x00002424},
17162306a36Sopenharmony_ci	{CS35L36_BSTCVRT_SLOPE_LBST,		0x00005800},
17262306a36Sopenharmony_ci	{CS35L36_BSTCVRT_SW_FREQ,		0x00010000},
17362306a36Sopenharmony_ci	{CS35L36_BSTCVRT_DCM_CTRL,		0x00002001},
17462306a36Sopenharmony_ci	{CS35L36_BSTCVRT_DCM_MODE_FORCE,	0x00000000},
17562306a36Sopenharmony_ci	{CS35L36_BSTCVRT_OVERVOLT_CTRL,		0x00000130},
17662306a36Sopenharmony_ci	{CS35L36_VPI_LIMIT_MODE,		0x00000000},
17762306a36Sopenharmony_ci	{CS35L36_VPI_LIMIT_MINMAX,		0x00003000},
17862306a36Sopenharmony_ci	{CS35L36_VPI_VP_THLD,			0x00101010},
17962306a36Sopenharmony_ci	{CS35L36_VPI_TRACK_CTRL,		0x00000000},
18062306a36Sopenharmony_ci	{CS35L36_VPI_TRIG_MODE_CTRL,		0x00000000},
18162306a36Sopenharmony_ci	{CS35L36_VPI_TRIG_STEPS,		0x00000000},
18262306a36Sopenharmony_ci	{CS35L36_VI_SPKMON_FILT,		0x00000003},
18362306a36Sopenharmony_ci	{CS35L36_VI_SPKMON_GAIN,		0x00000909},
18462306a36Sopenharmony_ci	{CS35L36_VI_SPKMON_IP_SEL,		0x00000000},
18562306a36Sopenharmony_ci	{CS35L36_DTEMP_WARN_THLD,		0x00000002},
18662306a36Sopenharmony_ci	{CS35L36_DTEMP_STATUS,			0x00000000},
18762306a36Sopenharmony_ci	{CS35L36_VPVBST_FS_SEL,			0x00000001},
18862306a36Sopenharmony_ci	{CS35L36_VPVBST_VP_CTRL,		0x000001C0},
18962306a36Sopenharmony_ci	{CS35L36_VPVBST_VBST_CTRL,		0x000001C0},
19062306a36Sopenharmony_ci	{CS35L36_ASP_TX_PIN_CTRL,		0x00000028},
19162306a36Sopenharmony_ci	{CS35L36_ASP_RATE_CTRL,			0x00090000},
19262306a36Sopenharmony_ci	{CS35L36_ASP_FORMAT,			0x00000002},
19362306a36Sopenharmony_ci	{CS35L36_ASP_FRAME_CTRL,		0x00180018},
19462306a36Sopenharmony_ci	{CS35L36_ASP_TX1_TX2_SLOT,		0x00010000},
19562306a36Sopenharmony_ci	{CS35L36_ASP_TX3_TX4_SLOT,		0x00030002},
19662306a36Sopenharmony_ci	{CS35L36_ASP_TX5_TX6_SLOT,		0x00050004},
19762306a36Sopenharmony_ci	{CS35L36_ASP_TX7_TX8_SLOT,		0x00070006},
19862306a36Sopenharmony_ci	{CS35L36_ASP_RX1_SLOT,			0x00000000},
19962306a36Sopenharmony_ci	{CS35L36_ASP_RX_TX_EN,			0x00000000},
20062306a36Sopenharmony_ci	{CS35L36_ASP_RX1_SEL,			0x00000008},
20162306a36Sopenharmony_ci	{CS35L36_ASP_TX1_SEL,			0x00000018},
20262306a36Sopenharmony_ci	{CS35L36_ASP_TX2_SEL,			0x00000019},
20362306a36Sopenharmony_ci	{CS35L36_ASP_TX3_SEL,			0x00000028},
20462306a36Sopenharmony_ci	{CS35L36_ASP_TX4_SEL,			0x00000029},
20562306a36Sopenharmony_ci	{CS35L36_ASP_TX5_SEL,			0x00000020},
20662306a36Sopenharmony_ci	{CS35L36_ASP_TX6_SEL,			0x00000000},
20762306a36Sopenharmony_ci	{CS35L36_SWIRE_P1_TX1_SEL,		0x00000018},
20862306a36Sopenharmony_ci	{CS35L36_SWIRE_P1_TX2_SEL,		0x00000019},
20962306a36Sopenharmony_ci	{CS35L36_SWIRE_P2_TX1_SEL,		0x00000028},
21062306a36Sopenharmony_ci	{CS35L36_SWIRE_P2_TX2_SEL,		0x00000029},
21162306a36Sopenharmony_ci	{CS35L36_SWIRE_P2_TX3_SEL,		0x00000020},
21262306a36Sopenharmony_ci	{CS35L36_SWIRE_DP1_FIFO_CFG,		0x0000001B},
21362306a36Sopenharmony_ci	{CS35L36_SWIRE_DP2_FIFO_CFG,		0x0000001B},
21462306a36Sopenharmony_ci	{CS35L36_SWIRE_DP3_FIFO_CFG,		0x0000001B},
21562306a36Sopenharmony_ci	{CS35L36_SWIRE_PCM_RX_DATA,		0x00000000},
21662306a36Sopenharmony_ci	{CS35L36_SWIRE_FS_SEL,			0x00000001},
21762306a36Sopenharmony_ci	{CS35L36_AMP_DIG_VOL_CTRL,		0x00008000},
21862306a36Sopenharmony_ci	{CS35L36_VPBR_CFG,			0x02AA1905},
21962306a36Sopenharmony_ci	{CS35L36_VBBR_CFG,			0x02AA1905},
22062306a36Sopenharmony_ci	{CS35L36_VPBR_STATUS,			0x00000000},
22162306a36Sopenharmony_ci	{CS35L36_VBBR_STATUS,			0x00000000},
22262306a36Sopenharmony_ci	{CS35L36_OVERTEMP_CFG,			0x00000001},
22362306a36Sopenharmony_ci	{CS35L36_AMP_ERR_VOL,			0x00000000},
22462306a36Sopenharmony_ci	{CS35L36_CLASSH_CFG,			0x000B0405},
22562306a36Sopenharmony_ci	{CS35L36_CLASSH_FET_DRV_CFG,		0x00000111},
22662306a36Sopenharmony_ci	{CS35L36_NG_CFG,			0x00000033},
22762306a36Sopenharmony_ci	{CS35L36_AMP_GAIN_CTRL,			0x00000273},
22862306a36Sopenharmony_ci	{CS35L36_PWM_MOD_IO_CTRL,		0x00000000},
22962306a36Sopenharmony_ci	{CS35L36_PWM_MOD_STATUS,		0x00000000},
23062306a36Sopenharmony_ci	{CS35L36_DAC_MSM_CFG,			0x00000000},
23162306a36Sopenharmony_ci	{CS35L36_AMP_SLOPE_CTRL,		0x00000B00},
23262306a36Sopenharmony_ci	{CS35L36_AMP_PDM_VOLUME,		0x00000000},
23362306a36Sopenharmony_ci	{CS35L36_AMP_PDM_RATE_CTRL,		0x00000000},
23462306a36Sopenharmony_ci	{CS35L36_PDM_CH_SEL,			0x00000000},
23562306a36Sopenharmony_ci	{CS35L36_AMP_NG_CTRL,			0x0000212F},
23662306a36Sopenharmony_ci	{CS35L36_PDM_HIGHFILT_CTRL,		0x00000000},
23762306a36Sopenharmony_ci	{CS35L36_PAC_INT0_CTRL,			0x00000001},
23862306a36Sopenharmony_ci	{CS35L36_PAC_INT1_CTRL,			0x00000001},
23962306a36Sopenharmony_ci	{CS35L36_PAC_INT2_CTRL,			0x00000001},
24062306a36Sopenharmony_ci	{CS35L36_PAC_INT3_CTRL,			0x00000001},
24162306a36Sopenharmony_ci	{CS35L36_PAC_INT4_CTRL,			0x00000001},
24262306a36Sopenharmony_ci	{CS35L36_PAC_INT5_CTRL,			0x00000001},
24362306a36Sopenharmony_ci	{CS35L36_PAC_INT6_CTRL,			0x00000001},
24462306a36Sopenharmony_ci	{CS35L36_PAC_INT7_CTRL,			0x00000001},
24562306a36Sopenharmony_ci};
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic bool cs35l36_readable_reg(struct device *dev, unsigned int reg)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	switch (reg) {
25062306a36Sopenharmony_ci	case CS35L36_SW_RESET:
25162306a36Sopenharmony_ci	case CS35L36_SW_REV:
25262306a36Sopenharmony_ci	case CS35L36_HW_REV:
25362306a36Sopenharmony_ci	case CS35L36_TESTKEY_CTRL:
25462306a36Sopenharmony_ci	case CS35L36_USERKEY_CTL:
25562306a36Sopenharmony_ci	case CS35L36_OTP_MEM30:
25662306a36Sopenharmony_ci	case CS35L36_OTP_CTRL1:
25762306a36Sopenharmony_ci	case CS35L36_OTP_CTRL2:
25862306a36Sopenharmony_ci	case CS35L36_OTP_CTRL3:
25962306a36Sopenharmony_ci	case CS35L36_OTP_CTRL4:
26062306a36Sopenharmony_ci	case CS35L36_OTP_CTRL5:
26162306a36Sopenharmony_ci	case CS35L36_PAC_CTL1:
26262306a36Sopenharmony_ci	case CS35L36_PAC_CTL2:
26362306a36Sopenharmony_ci	case CS35L36_PAC_CTL3:
26462306a36Sopenharmony_ci	case CS35L36_DEVICE_ID:
26562306a36Sopenharmony_ci	case CS35L36_FAB_ID:
26662306a36Sopenharmony_ci	case CS35L36_REV_ID:
26762306a36Sopenharmony_ci	case CS35L36_PWR_CTRL1:
26862306a36Sopenharmony_ci	case CS35L36_PWR_CTRL2:
26962306a36Sopenharmony_ci	case CS35L36_PWR_CTRL3:
27062306a36Sopenharmony_ci	case CS35L36_CTRL_OVRRIDE:
27162306a36Sopenharmony_ci	case CS35L36_AMP_OUT_MUTE:
27262306a36Sopenharmony_ci	case CS35L36_OTP_TRIM_STATUS:
27362306a36Sopenharmony_ci	case CS35L36_DISCH_FILT:
27462306a36Sopenharmony_ci	case CS35L36_PROTECT_REL_ERR:
27562306a36Sopenharmony_ci	case CS35L36_PAD_INTERFACE:
27662306a36Sopenharmony_ci	case CS35L36_PLL_CLK_CTRL:
27762306a36Sopenharmony_ci	case CS35L36_GLOBAL_CLK_CTRL:
27862306a36Sopenharmony_ci	case CS35L36_ADC_CLK_CTRL:
27962306a36Sopenharmony_ci	case CS35L36_SWIRE_CLK_CTRL:
28062306a36Sopenharmony_ci	case CS35L36_SP_SCLK_CLK_CTRL:
28162306a36Sopenharmony_ci	case CS35L36_TST_FS_MON0:
28262306a36Sopenharmony_ci	case CS35L36_MDSYNC_EN:
28362306a36Sopenharmony_ci	case CS35L36_MDSYNC_TX_ID:
28462306a36Sopenharmony_ci	case CS35L36_MDSYNC_PWR_CTRL:
28562306a36Sopenharmony_ci	case CS35L36_MDSYNC_DATA_TX:
28662306a36Sopenharmony_ci	case CS35L36_MDSYNC_TX_STATUS:
28762306a36Sopenharmony_ci	case CS35L36_MDSYNC_RX_STATUS:
28862306a36Sopenharmony_ci	case CS35L36_MDSYNC_ERR_STATUS:
28962306a36Sopenharmony_ci	case CS35L36_BSTCVRT_VCTRL1:
29062306a36Sopenharmony_ci	case CS35L36_BSTCVRT_VCTRL2:
29162306a36Sopenharmony_ci	case CS35L36_BSTCVRT_PEAK_CUR:
29262306a36Sopenharmony_ci	case CS35L36_BSTCVRT_SFT_RAMP:
29362306a36Sopenharmony_ci	case CS35L36_BSTCVRT_COEFF:
29462306a36Sopenharmony_ci	case CS35L36_BSTCVRT_SLOPE_LBST:
29562306a36Sopenharmony_ci	case CS35L36_BSTCVRT_SW_FREQ:
29662306a36Sopenharmony_ci	case CS35L36_BSTCVRT_DCM_CTRL:
29762306a36Sopenharmony_ci	case CS35L36_BSTCVRT_DCM_MODE_FORCE:
29862306a36Sopenharmony_ci	case CS35L36_BSTCVRT_OVERVOLT_CTRL:
29962306a36Sopenharmony_ci	case CS35L36_BST_TST_MANUAL:
30062306a36Sopenharmony_ci	case CS35L36_BST_ANA2_TEST:
30162306a36Sopenharmony_ci	case CS35L36_VPI_LIMIT_MODE:
30262306a36Sopenharmony_ci	case CS35L36_VPI_LIMIT_MINMAX:
30362306a36Sopenharmony_ci	case CS35L36_VPI_VP_THLD:
30462306a36Sopenharmony_ci	case CS35L36_VPI_TRACK_CTRL:
30562306a36Sopenharmony_ci	case CS35L36_VPI_TRIG_MODE_CTRL:
30662306a36Sopenharmony_ci	case CS35L36_VPI_TRIG_STEPS:
30762306a36Sopenharmony_ci	case CS35L36_VI_SPKMON_FILT:
30862306a36Sopenharmony_ci	case CS35L36_VI_SPKMON_GAIN:
30962306a36Sopenharmony_ci	case CS35L36_VI_SPKMON_IP_SEL:
31062306a36Sopenharmony_ci	case CS35L36_DTEMP_WARN_THLD:
31162306a36Sopenharmony_ci	case CS35L36_DTEMP_STATUS:
31262306a36Sopenharmony_ci	case CS35L36_VPVBST_FS_SEL:
31362306a36Sopenharmony_ci	case CS35L36_VPVBST_VP_CTRL:
31462306a36Sopenharmony_ci	case CS35L36_VPVBST_VBST_CTRL:
31562306a36Sopenharmony_ci	case CS35L36_ASP_TX_PIN_CTRL:
31662306a36Sopenharmony_ci	case CS35L36_ASP_RATE_CTRL:
31762306a36Sopenharmony_ci	case CS35L36_ASP_FORMAT:
31862306a36Sopenharmony_ci	case CS35L36_ASP_FRAME_CTRL:
31962306a36Sopenharmony_ci	case CS35L36_ASP_TX1_TX2_SLOT:
32062306a36Sopenharmony_ci	case CS35L36_ASP_TX3_TX4_SLOT:
32162306a36Sopenharmony_ci	case CS35L36_ASP_TX5_TX6_SLOT:
32262306a36Sopenharmony_ci	case CS35L36_ASP_TX7_TX8_SLOT:
32362306a36Sopenharmony_ci	case CS35L36_ASP_RX1_SLOT:
32462306a36Sopenharmony_ci	case CS35L36_ASP_RX_TX_EN:
32562306a36Sopenharmony_ci	case CS35L36_ASP_RX1_SEL:
32662306a36Sopenharmony_ci	case CS35L36_ASP_TX1_SEL:
32762306a36Sopenharmony_ci	case CS35L36_ASP_TX2_SEL:
32862306a36Sopenharmony_ci	case CS35L36_ASP_TX3_SEL:
32962306a36Sopenharmony_ci	case CS35L36_ASP_TX4_SEL:
33062306a36Sopenharmony_ci	case CS35L36_ASP_TX5_SEL:
33162306a36Sopenharmony_ci	case CS35L36_ASP_TX6_SEL:
33262306a36Sopenharmony_ci	case CS35L36_SWIRE_P1_TX1_SEL:
33362306a36Sopenharmony_ci	case CS35L36_SWIRE_P1_TX2_SEL:
33462306a36Sopenharmony_ci	case CS35L36_SWIRE_P2_TX1_SEL:
33562306a36Sopenharmony_ci	case CS35L36_SWIRE_P2_TX2_SEL:
33662306a36Sopenharmony_ci	case CS35L36_SWIRE_P2_TX3_SEL:
33762306a36Sopenharmony_ci	case CS35L36_SWIRE_DP1_FIFO_CFG:
33862306a36Sopenharmony_ci	case CS35L36_SWIRE_DP2_FIFO_CFG:
33962306a36Sopenharmony_ci	case CS35L36_SWIRE_DP3_FIFO_CFG:
34062306a36Sopenharmony_ci	case CS35L36_SWIRE_PCM_RX_DATA:
34162306a36Sopenharmony_ci	case CS35L36_SWIRE_FS_SEL:
34262306a36Sopenharmony_ci	case CS35L36_AMP_DIG_VOL_CTRL:
34362306a36Sopenharmony_ci	case CS35L36_VPBR_CFG:
34462306a36Sopenharmony_ci	case CS35L36_VBBR_CFG:
34562306a36Sopenharmony_ci	case CS35L36_VPBR_STATUS:
34662306a36Sopenharmony_ci	case CS35L36_VBBR_STATUS:
34762306a36Sopenharmony_ci	case CS35L36_OVERTEMP_CFG:
34862306a36Sopenharmony_ci	case CS35L36_AMP_ERR_VOL:
34962306a36Sopenharmony_ci	case CS35L36_CLASSH_CFG:
35062306a36Sopenharmony_ci	case CS35L36_CLASSH_FET_DRV_CFG:
35162306a36Sopenharmony_ci	case CS35L36_NG_CFG:
35262306a36Sopenharmony_ci	case CS35L36_AMP_GAIN_CTRL:
35362306a36Sopenharmony_ci	case CS35L36_PWM_MOD_IO_CTRL:
35462306a36Sopenharmony_ci	case CS35L36_PWM_MOD_STATUS:
35562306a36Sopenharmony_ci	case CS35L36_DAC_MSM_CFG:
35662306a36Sopenharmony_ci	case CS35L36_AMP_SLOPE_CTRL:
35762306a36Sopenharmony_ci	case CS35L36_AMP_PDM_VOLUME:
35862306a36Sopenharmony_ci	case CS35L36_AMP_PDM_RATE_CTRL:
35962306a36Sopenharmony_ci	case CS35L36_PDM_CH_SEL:
36062306a36Sopenharmony_ci	case CS35L36_AMP_NG_CTRL:
36162306a36Sopenharmony_ci	case CS35L36_PDM_HIGHFILT_CTRL:
36262306a36Sopenharmony_ci	case CS35L36_INT1_STATUS:
36362306a36Sopenharmony_ci	case CS35L36_INT2_STATUS:
36462306a36Sopenharmony_ci	case CS35L36_INT3_STATUS:
36562306a36Sopenharmony_ci	case CS35L36_INT4_STATUS:
36662306a36Sopenharmony_ci	case CS35L36_INT1_RAW_STATUS:
36762306a36Sopenharmony_ci	case CS35L36_INT2_RAW_STATUS:
36862306a36Sopenharmony_ci	case CS35L36_INT3_RAW_STATUS:
36962306a36Sopenharmony_ci	case CS35L36_INT4_RAW_STATUS:
37062306a36Sopenharmony_ci	case CS35L36_INT1_MASK:
37162306a36Sopenharmony_ci	case CS35L36_INT2_MASK:
37262306a36Sopenharmony_ci	case CS35L36_INT3_MASK:
37362306a36Sopenharmony_ci	case CS35L36_INT4_MASK:
37462306a36Sopenharmony_ci	case CS35L36_INT1_EDGE_LVL_CTRL:
37562306a36Sopenharmony_ci	case CS35L36_INT3_EDGE_LVL_CTRL:
37662306a36Sopenharmony_ci	case CS35L36_PAC_INT_STATUS:
37762306a36Sopenharmony_ci	case CS35L36_PAC_INT_RAW_STATUS:
37862306a36Sopenharmony_ci	case CS35L36_PAC_INT_FLUSH_CTRL:
37962306a36Sopenharmony_ci	case CS35L36_PAC_INT0_CTRL:
38062306a36Sopenharmony_ci	case CS35L36_PAC_INT1_CTRL:
38162306a36Sopenharmony_ci	case CS35L36_PAC_INT2_CTRL:
38262306a36Sopenharmony_ci	case CS35L36_PAC_INT3_CTRL:
38362306a36Sopenharmony_ci	case CS35L36_PAC_INT4_CTRL:
38462306a36Sopenharmony_ci	case CS35L36_PAC_INT5_CTRL:
38562306a36Sopenharmony_ci	case CS35L36_PAC_INT6_CTRL:
38662306a36Sopenharmony_ci	case CS35L36_PAC_INT7_CTRL:
38762306a36Sopenharmony_ci		return true;
38862306a36Sopenharmony_ci	default:
38962306a36Sopenharmony_ci		if (reg >= CS35L36_PAC_PMEM_WORD0 &&
39062306a36Sopenharmony_ci			reg <= CS35L36_PAC_PMEM_WORD1023)
39162306a36Sopenharmony_ci			return true;
39262306a36Sopenharmony_ci		else
39362306a36Sopenharmony_ci			return false;
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic bool cs35l36_precious_reg(struct device *dev, unsigned int reg)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	switch (reg) {
40062306a36Sopenharmony_ci	case CS35L36_TESTKEY_CTRL:
40162306a36Sopenharmony_ci	case CS35L36_USERKEY_CTL:
40262306a36Sopenharmony_ci	case CS35L36_TST_FS_MON0:
40362306a36Sopenharmony_ci		return true;
40462306a36Sopenharmony_ci	default:
40562306a36Sopenharmony_ci		return false;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic bool cs35l36_volatile_reg(struct device *dev, unsigned int reg)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	switch (reg) {
41262306a36Sopenharmony_ci	case CS35L36_SW_RESET:
41362306a36Sopenharmony_ci	case CS35L36_SW_REV:
41462306a36Sopenharmony_ci	case CS35L36_HW_REV:
41562306a36Sopenharmony_ci	case CS35L36_TESTKEY_CTRL:
41662306a36Sopenharmony_ci	case CS35L36_USERKEY_CTL:
41762306a36Sopenharmony_ci	case CS35L36_DEVICE_ID:
41862306a36Sopenharmony_ci	case CS35L36_FAB_ID:
41962306a36Sopenharmony_ci	case CS35L36_REV_ID:
42062306a36Sopenharmony_ci	case CS35L36_INT1_STATUS:
42162306a36Sopenharmony_ci	case CS35L36_INT2_STATUS:
42262306a36Sopenharmony_ci	case CS35L36_INT3_STATUS:
42362306a36Sopenharmony_ci	case CS35L36_INT4_STATUS:
42462306a36Sopenharmony_ci	case CS35L36_INT1_RAW_STATUS:
42562306a36Sopenharmony_ci	case CS35L36_INT2_RAW_STATUS:
42662306a36Sopenharmony_ci	case CS35L36_INT3_RAW_STATUS:
42762306a36Sopenharmony_ci	case CS35L36_INT4_RAW_STATUS:
42862306a36Sopenharmony_ci	case CS35L36_INT1_MASK:
42962306a36Sopenharmony_ci	case CS35L36_INT2_MASK:
43062306a36Sopenharmony_ci	case CS35L36_INT3_MASK:
43162306a36Sopenharmony_ci	case CS35L36_INT4_MASK:
43262306a36Sopenharmony_ci	case CS35L36_INT1_EDGE_LVL_CTRL:
43362306a36Sopenharmony_ci	case CS35L36_INT3_EDGE_LVL_CTRL:
43462306a36Sopenharmony_ci	case CS35L36_PAC_INT_STATUS:
43562306a36Sopenharmony_ci	case CS35L36_PAC_INT_RAW_STATUS:
43662306a36Sopenharmony_ci	case CS35L36_PAC_INT_FLUSH_CTRL:
43762306a36Sopenharmony_ci		return true;
43862306a36Sopenharmony_ci	default:
43962306a36Sopenharmony_ci		if (reg >= CS35L36_PAC_PMEM_WORD0 &&
44062306a36Sopenharmony_ci			reg <= CS35L36_PAC_PMEM_WORD1023)
44162306a36Sopenharmony_ci			return true;
44262306a36Sopenharmony_ci		else
44362306a36Sopenharmony_ci			return false;
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(dig_vol_tlv, 0, 912,
44862306a36Sopenharmony_ci				  TLV_DB_MINMAX_ITEM(-10200, 1200));
44962306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic const char * const cs35l36_pcm_sftramp_text[] =  {
45262306a36Sopenharmony_ci	"Off", ".5ms", "1ms", "2ms", "4ms", "8ms", "15ms", "30ms"};
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(pcm_sft_ramp, CS35L36_AMP_DIG_VOL_CTRL, 0,
45562306a36Sopenharmony_ci			    cs35l36_pcm_sftramp_text);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_cistatic int cs35l36_ldm_sel_get(struct snd_kcontrol *kcontrol,
45862306a36Sopenharmony_ci			       struct snd_ctl_elem_value *ucontrol)
45962306a36Sopenharmony_ci{
46062306a36Sopenharmony_ci	struct snd_soc_component *component =
46162306a36Sopenharmony_ci			snd_soc_kcontrol_component(kcontrol);
46262306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
46362306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = cs35l36->ldm_mode_sel;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	return 0;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cistatic int cs35l36_ldm_sel_put(struct snd_kcontrol *kcontrol,
47162306a36Sopenharmony_ci			       struct snd_ctl_elem_value *ucontrol)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct snd_soc_component *component =
47462306a36Sopenharmony_ci			snd_soc_kcontrol_component(kcontrol);
47562306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
47662306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
47762306a36Sopenharmony_ci	int val = (ucontrol->value.integer.value[0]) ? CS35L36_NG_AMP_EN_MASK :
47862306a36Sopenharmony_ci						       0;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	cs35l36->ldm_mode_sel = val;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_NG_CFG,
48362306a36Sopenharmony_ci			   CS35L36_NG_AMP_EN_MASK, val);
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	return 0;
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs35l36_aud_controls[] = {
48962306a36Sopenharmony_ci	SOC_SINGLE_SX_TLV("Digital PCM Volume", CS35L36_AMP_DIG_VOL_CTRL,
49062306a36Sopenharmony_ci		3, 0x4D0, 0x390, dig_vol_tlv),
49162306a36Sopenharmony_ci	SOC_SINGLE_TLV("Analog PCM Volume", CS35L36_AMP_GAIN_CTRL, 5, 0x13, 0,
49262306a36Sopenharmony_ci		amp_gain_tlv),
49362306a36Sopenharmony_ci	SOC_ENUM("PCM Soft Ramp", pcm_sft_ramp),
49462306a36Sopenharmony_ci	SOC_SINGLE("Amp Gain Zero-Cross Switch", CS35L36_AMP_GAIN_CTRL,
49562306a36Sopenharmony_ci		CS35L36_AMP_ZC_SHIFT, 1, 0),
49662306a36Sopenharmony_ci	SOC_SINGLE("PDM LDM Enter Ramp Switch", CS35L36_DAC_MSM_CFG,
49762306a36Sopenharmony_ci		CS35L36_PDM_LDM_ENTER_SHIFT, 1, 0),
49862306a36Sopenharmony_ci	SOC_SINGLE("PDM LDM Exit Ramp Switch", CS35L36_DAC_MSM_CFG,
49962306a36Sopenharmony_ci		CS35L36_PDM_LDM_EXIT_SHIFT, 1, 0),
50062306a36Sopenharmony_ci	SOC_SINGLE_BOOL_EXT("LDM Select Switch", 0, cs35l36_ldm_sel_get,
50162306a36Sopenharmony_ci		cs35l36_ldm_sel_put),
50262306a36Sopenharmony_ci};
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_cistatic int cs35l36_main_amp_event(struct snd_soc_dapm_widget *w,
50562306a36Sopenharmony_ci				  struct snd_kcontrol *kcontrol, int event)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	struct snd_soc_component *component =
50862306a36Sopenharmony_ci			snd_soc_dapm_to_component(w->dapm);
50962306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
51062306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
51162306a36Sopenharmony_ci	u32 reg;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	switch (event) {
51462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
51562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PWR_CTRL1,
51662306a36Sopenharmony_ci				   CS35L36_GLOBAL_EN_MASK,
51762306a36Sopenharmony_ci				   1 << CS35L36_GLOBAL_EN_SHIFT);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci		usleep_range(2000, 2100);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci		regmap_read(cs35l36->regmap, CS35L36_INT4_RAW_STATUS, &reg);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci		if (WARN_ON_ONCE(reg & CS35L36_PLL_UNLOCK_MASK))
52462306a36Sopenharmony_ci			dev_crit(cs35l36->dev, "PLL Unlocked\n");
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RX1_SEL,
52762306a36Sopenharmony_ci				   CS35L36_PCM_RX_SEL_MASK,
52862306a36Sopenharmony_ci				   CS35L36_PCM_RX_SEL_PCM);
52962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_AMP_OUT_MUTE,
53062306a36Sopenharmony_ci				   CS35L36_AMP_MUTE_MASK,
53162306a36Sopenharmony_ci				   0 << CS35L36_AMP_MUTE_SHIFT);
53262306a36Sopenharmony_ci		break;
53362306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
53462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RX1_SEL,
53562306a36Sopenharmony_ci				   CS35L36_PCM_RX_SEL_MASK,
53662306a36Sopenharmony_ci				   CS35L36_PCM_RX_SEL_ZERO);
53762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_AMP_OUT_MUTE,
53862306a36Sopenharmony_ci				   CS35L36_AMP_MUTE_MASK,
53962306a36Sopenharmony_ci				   1 << CS35L36_AMP_MUTE_SHIFT);
54062306a36Sopenharmony_ci		break;
54162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
54262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PWR_CTRL1,
54362306a36Sopenharmony_ci				   CS35L36_GLOBAL_EN_MASK,
54462306a36Sopenharmony_ci				   0 << CS35L36_GLOBAL_EN_SHIFT);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		usleep_range(2000, 2100);
54762306a36Sopenharmony_ci		break;
54862306a36Sopenharmony_ci	default:
54962306a36Sopenharmony_ci		dev_dbg(component->dev, "Invalid event = 0x%x\n", event);
55062306a36Sopenharmony_ci		return -EINVAL;
55162306a36Sopenharmony_ci	}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	return 0;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic int cs35l36_boost_event(struct snd_soc_dapm_widget *w,
55762306a36Sopenharmony_ci			       struct snd_kcontrol *kcontrol, int event)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	struct snd_soc_component *component =
56062306a36Sopenharmony_ci			snd_soc_dapm_to_component(w->dapm);
56162306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
56262306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	switch (event) {
56562306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
56662306a36Sopenharmony_ci		if (!cs35l36->pdata.extern_boost)
56762306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_PWR_CTRL2,
56862306a36Sopenharmony_ci					   CS35L36_BST_EN_MASK,
56962306a36Sopenharmony_ci					   CS35L36_BST_EN <<
57062306a36Sopenharmony_ci					   CS35L36_BST_EN_SHIFT);
57162306a36Sopenharmony_ci		break;
57262306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
57362306a36Sopenharmony_ci		if (!cs35l36->pdata.extern_boost)
57462306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_PWR_CTRL2,
57562306a36Sopenharmony_ci					   CS35L36_BST_EN_MASK,
57662306a36Sopenharmony_ci					   CS35L36_BST_DIS_VP <<
57762306a36Sopenharmony_ci					   CS35L36_BST_EN_SHIFT);
57862306a36Sopenharmony_ci		break;
57962306a36Sopenharmony_ci	default:
58062306a36Sopenharmony_ci		dev_dbg(component->dev, "Invalid event = 0x%x\n", event);
58162306a36Sopenharmony_ci		return -EINVAL;
58262306a36Sopenharmony_ci	}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	return 0;
58562306a36Sopenharmony_ci}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_cistatic const char * const cs35l36_chan_text[] = {
58862306a36Sopenharmony_ci	"RX1",
58962306a36Sopenharmony_ci	"RX2",
59062306a36Sopenharmony_ci};
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(chansel_enum, CS35L36_ASP_RX1_SLOT, 0,
59362306a36Sopenharmony_ci			    cs35l36_chan_text);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs35l36_chan_mux =
59662306a36Sopenharmony_ci		SOC_DAPM_ENUM("Input Mux", chansel_enum);
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_cistatic const struct snd_kcontrol_new amp_enable_ctrl =
59962306a36Sopenharmony_ci		SOC_DAPM_SINGLE_AUTODISABLE("Switch", CS35L36_AMP_OUT_MUTE,
60062306a36Sopenharmony_ci					    CS35L36_AMP_MUTE_SHIFT, 1, 1);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic const struct snd_kcontrol_new boost_ctrl =
60362306a36Sopenharmony_ci		SOC_DAPM_SINGLE_VIRT("Switch", 1);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_cistatic const char * const asp_tx_src_text[] = {
60662306a36Sopenharmony_ci	"Zero Fill", "ASPRX1", "VMON", "IMON", "ERRVOL", "VPMON", "VBSTMON"
60762306a36Sopenharmony_ci};
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cistatic const unsigned int asp_tx_src_values[] = {
61062306a36Sopenharmony_ci	0x00, 0x08, 0x18, 0x19, 0x20, 0x28, 0x29
61162306a36Sopenharmony_ci};
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx1_src_enum, CS35L36_ASP_TX1_SEL, 0,
61462306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
61562306a36Sopenharmony_ci				  asp_tx_src_values);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx1_src =
61862306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX1SRC", asp_tx1_src_enum);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx2_src_enum, CS35L36_ASP_TX2_SEL, 0,
62162306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
62262306a36Sopenharmony_ci				  asp_tx_src_values);
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx2_src =
62562306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX2SRC", asp_tx2_src_enum);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx3_src_enum, CS35L36_ASP_TX3_SEL, 0,
62862306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
62962306a36Sopenharmony_ci				  asp_tx_src_values);
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx3_src =
63262306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX3SRC", asp_tx3_src_enum);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx4_src_enum, CS35L36_ASP_TX4_SEL, 0,
63562306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
63662306a36Sopenharmony_ci				  asp_tx_src_values);
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx4_src =
63962306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX4SRC", asp_tx4_src_enum);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx5_src_enum, CS35L36_ASP_TX5_SEL, 0,
64262306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
64362306a36Sopenharmony_ci				  asp_tx_src_values);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx5_src =
64662306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX5SRC", asp_tx5_src_enum);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(asp_tx6_src_enum, CS35L36_ASP_TX6_SEL, 0,
64962306a36Sopenharmony_ci				  CS35L36_APS_TX_SEL_MASK, asp_tx_src_text,
65062306a36Sopenharmony_ci				  asp_tx_src_values);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_cistatic const struct snd_kcontrol_new asp_tx6_src =
65362306a36Sopenharmony_ci		SOC_DAPM_ENUM("ASPTX6SRC", asp_tx6_src_enum);
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget cs35l36_dapm_widgets[] = {
65662306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("Channel Mux", SND_SOC_NOPM, 0, 0, &cs35l36_chan_mux),
65762306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0, CS35L36_ASP_RX_TX_EN, 16, 0),
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L36_PWR_CTRL2, 0, 0, NULL, 0,
66062306a36Sopenharmony_ci			       cs35l36_main_amp_event, SND_SOC_DAPM_POST_PMD |
66162306a36Sopenharmony_ci			       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPK"),
66462306a36Sopenharmony_ci	SND_SOC_DAPM_SWITCH("AMP Enable", SND_SOC_NOPM, 0, 1, &amp_enable_ctrl),
66562306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("CLASS H", CS35L36_PWR_CTRL3, 4, 0, NULL, 0),
66662306a36Sopenharmony_ci	SND_SOC_DAPM_SWITCH_E("BOOST Enable", SND_SOC_NOPM, 0, 0, &boost_ctrl,
66762306a36Sopenharmony_ci			      cs35l36_boost_event, SND_SOC_DAPM_POST_PMD |
66862306a36Sopenharmony_ci			      SND_SOC_DAPM_POST_PMU),
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX1", NULL, 0, CS35L36_ASP_RX_TX_EN, 0, 0),
67162306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX2", NULL, 1, CS35L36_ASP_RX_TX_EN, 1, 0),
67262306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX3", NULL, 2, CS35L36_ASP_RX_TX_EN, 2, 0),
67362306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX4", NULL, 3, CS35L36_ASP_RX_TX_EN, 3, 0),
67462306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX5", NULL, 4, CS35L36_ASP_RX_TX_EN, 4, 0),
67562306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("ASPTX6", NULL, 5, CS35L36_ASP_RX_TX_EN, 5, 0),
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX1SRC", SND_SOC_NOPM, 0, 0, &asp_tx1_src),
67862306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX2SRC", SND_SOC_NOPM, 0, 0, &asp_tx2_src),
67962306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX3SRC", SND_SOC_NOPM, 0, 0, &asp_tx3_src),
68062306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX4SRC", SND_SOC_NOPM, 0, 0, &asp_tx4_src),
68162306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX5SRC", SND_SOC_NOPM, 0, 0, &asp_tx5_src),
68262306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ASPTX6SRC", SND_SOC_NOPM, 0, 0, &asp_tx6_src),
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L36_PWR_CTRL2, 12, 0),
68562306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L36_PWR_CTRL2, 13, 0),
68662306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L36_PWR_CTRL2, 8, 0),
68762306a36Sopenharmony_ci	SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L36_PWR_CTRL2, 9, 0),
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VP"),
69062306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VBST"),
69162306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("VSENSE"),
69262306a36Sopenharmony_ci};
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_cistatic const struct snd_soc_dapm_route cs35l36_audio_map[] = {
69562306a36Sopenharmony_ci	{"VPMON ADC", NULL, "VP"},
69662306a36Sopenharmony_ci	{"VBSTMON ADC", NULL, "VBST"},
69762306a36Sopenharmony_ci	{"IMON ADC", NULL, "VSENSE"},
69862306a36Sopenharmony_ci	{"VMON ADC", NULL, "VSENSE"},
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	{"ASPTX1SRC", "IMON", "IMON ADC"},
70162306a36Sopenharmony_ci	{"ASPTX1SRC", "VMON", "VMON ADC"},
70262306a36Sopenharmony_ci	{"ASPTX1SRC", "VBSTMON", "VBSTMON ADC"},
70362306a36Sopenharmony_ci	{"ASPTX1SRC", "VPMON", "VPMON ADC"},
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	{"ASPTX2SRC", "IMON", "IMON ADC"},
70662306a36Sopenharmony_ci	{"ASPTX2SRC", "VMON", "VMON ADC"},
70762306a36Sopenharmony_ci	{"ASPTX2SRC", "VBSTMON", "VBSTMON ADC"},
70862306a36Sopenharmony_ci	{"ASPTX2SRC", "VPMON", "VPMON ADC"},
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	{"ASPTX3SRC", "IMON", "IMON ADC"},
71162306a36Sopenharmony_ci	{"ASPTX3SRC", "VMON", "VMON ADC"},
71262306a36Sopenharmony_ci	{"ASPTX3SRC", "VBSTMON", "VBSTMON ADC"},
71362306a36Sopenharmony_ci	{"ASPTX3SRC", "VPMON", "VPMON ADC"},
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	{"ASPTX4SRC", "IMON", "IMON ADC"},
71662306a36Sopenharmony_ci	{"ASPTX4SRC", "VMON", "VMON ADC"},
71762306a36Sopenharmony_ci	{"ASPTX4SRC", "VBSTMON", "VBSTMON ADC"},
71862306a36Sopenharmony_ci	{"ASPTX4SRC", "VPMON", "VPMON ADC"},
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	{"ASPTX5SRC", "IMON", "IMON ADC"},
72162306a36Sopenharmony_ci	{"ASPTX5SRC", "VMON", "VMON ADC"},
72262306a36Sopenharmony_ci	{"ASPTX5SRC", "VBSTMON", "VBSTMON ADC"},
72362306a36Sopenharmony_ci	{"ASPTX5SRC", "VPMON", "VPMON ADC"},
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	{"ASPTX6SRC", "IMON", "IMON ADC"},
72662306a36Sopenharmony_ci	{"ASPTX6SRC", "VMON", "VMON ADC"},
72762306a36Sopenharmony_ci	{"ASPTX6SRC", "VBSTMON", "VBSTMON ADC"},
72862306a36Sopenharmony_ci	{"ASPTX6SRC", "VPMON", "VPMON ADC"},
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	{"ASPTX1", NULL, "ASPTX1SRC"},
73162306a36Sopenharmony_ci	{"ASPTX2", NULL, "ASPTX2SRC"},
73262306a36Sopenharmony_ci	{"ASPTX3", NULL, "ASPTX3SRC"},
73362306a36Sopenharmony_ci	{"ASPTX4", NULL, "ASPTX4SRC"},
73462306a36Sopenharmony_ci	{"ASPTX5", NULL, "ASPTX5SRC"},
73562306a36Sopenharmony_ci	{"ASPTX6", NULL, "ASPTX6SRC"},
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX1"},
73862306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX2"},
73962306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX3"},
74062306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX4"},
74162306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX5"},
74262306a36Sopenharmony_ci	{"AMP Capture", NULL, "ASPTX6"},
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	{"AMP Enable", "Switch", "AMP Playback"},
74562306a36Sopenharmony_ci	{"SDIN", NULL, "AMP Enable"},
74662306a36Sopenharmony_ci	{"Channel Mux", "RX1", "SDIN"},
74762306a36Sopenharmony_ci	{"Channel Mux", "RX2", "SDIN"},
74862306a36Sopenharmony_ci	{"BOOST Enable", "Switch", "Channel Mux"},
74962306a36Sopenharmony_ci	{"CLASS H", NULL, "BOOST Enable"},
75062306a36Sopenharmony_ci	{"Main AMP", NULL, "Channel Mux"},
75162306a36Sopenharmony_ci	{"Main AMP", NULL, "CLASS H"},
75262306a36Sopenharmony_ci	{"SPK", NULL, "Main AMP"},
75362306a36Sopenharmony_ci};
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic int cs35l36_set_dai_fmt(struct snd_soc_dai *component_dai,
75662306a36Sopenharmony_ci			       unsigned int fmt)
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
75962306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component_dai->component);
76062306a36Sopenharmony_ci	unsigned int asp_fmt, lrclk_fmt, sclk_fmt, clock_provider, clk_frc;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
76362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBP_CFP:
76462306a36Sopenharmony_ci		clock_provider = 1;
76562306a36Sopenharmony_ci		break;
76662306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBC_CFC:
76762306a36Sopenharmony_ci		clock_provider = 0;
76862306a36Sopenharmony_ci		break;
76962306a36Sopenharmony_ci	default:
77062306a36Sopenharmony_ci		return -EINVAL;
77162306a36Sopenharmony_ci	}
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL,
77462306a36Sopenharmony_ci				CS35L36_SCLK_MSTR_MASK,
77562306a36Sopenharmony_ci				clock_provider << CS35L36_SCLK_MSTR_SHIFT);
77662306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RATE_CTRL,
77762306a36Sopenharmony_ci				CS35L36_LRCLK_MSTR_MASK,
77862306a36Sopenharmony_ci				clock_provider << CS35L36_LRCLK_MSTR_SHIFT);
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
78162306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CONT:
78262306a36Sopenharmony_ci		clk_frc = 1;
78362306a36Sopenharmony_ci		break;
78462306a36Sopenharmony_ci	case SND_SOC_DAIFMT_GATED:
78562306a36Sopenharmony_ci		clk_frc = 0;
78662306a36Sopenharmony_ci		break;
78762306a36Sopenharmony_ci	default:
78862306a36Sopenharmony_ci		return -EINVAL;
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL,
79262306a36Sopenharmony_ci			   CS35L36_SCLK_FRC_MASK, clk_frc <<
79362306a36Sopenharmony_ci			   CS35L36_SCLK_FRC_SHIFT);
79462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RATE_CTRL,
79562306a36Sopenharmony_ci			   CS35L36_LRCLK_FRC_MASK, clk_frc <<
79662306a36Sopenharmony_ci			   CS35L36_LRCLK_FRC_SHIFT);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
79962306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
80062306a36Sopenharmony_ci		asp_fmt = 0;
80162306a36Sopenharmony_ci		break;
80262306a36Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
80362306a36Sopenharmony_ci		asp_fmt = 2;
80462306a36Sopenharmony_ci		break;
80562306a36Sopenharmony_ci	default:
80662306a36Sopenharmony_ci		return -EINVAL;
80762306a36Sopenharmony_ci	}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
81062306a36Sopenharmony_ci	case SND_SOC_DAIFMT_NB_IF:
81162306a36Sopenharmony_ci		lrclk_fmt = 1;
81262306a36Sopenharmony_ci		sclk_fmt = 0;
81362306a36Sopenharmony_ci		break;
81462306a36Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
81562306a36Sopenharmony_ci		lrclk_fmt = 0;
81662306a36Sopenharmony_ci		sclk_fmt = 1;
81762306a36Sopenharmony_ci		break;
81862306a36Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
81962306a36Sopenharmony_ci		lrclk_fmt = 1;
82062306a36Sopenharmony_ci		sclk_fmt = 1;
82162306a36Sopenharmony_ci		break;
82262306a36Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
82362306a36Sopenharmony_ci		lrclk_fmt = 0;
82462306a36Sopenharmony_ci		sclk_fmt = 0;
82562306a36Sopenharmony_ci		break;
82662306a36Sopenharmony_ci	default:
82762306a36Sopenharmony_ci		return -EINVAL;
82862306a36Sopenharmony_ci	}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RATE_CTRL,
83162306a36Sopenharmony_ci			   CS35L36_LRCLK_INV_MASK,
83262306a36Sopenharmony_ci			   lrclk_fmt << CS35L36_LRCLK_INV_SHIFT);
83362306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL,
83462306a36Sopenharmony_ci			   CS35L36_SCLK_INV_MASK,
83562306a36Sopenharmony_ci			   sclk_fmt << CS35L36_SCLK_INV_SHIFT);
83662306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_ASP_FORMAT,
83762306a36Sopenharmony_ci			   CS35L36_ASP_FMT_MASK, asp_fmt);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	return 0;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistruct cs35l36_global_fs_config {
84362306a36Sopenharmony_ci	int rate;
84462306a36Sopenharmony_ci	int fs_cfg;
84562306a36Sopenharmony_ci};
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_cistatic const struct cs35l36_global_fs_config cs35l36_fs_rates[] = {
84862306a36Sopenharmony_ci	{12000, 0x01},
84962306a36Sopenharmony_ci	{24000, 0x02},
85062306a36Sopenharmony_ci	{48000, 0x03},
85162306a36Sopenharmony_ci	{96000, 0x04},
85262306a36Sopenharmony_ci	{192000, 0x05},
85362306a36Sopenharmony_ci	{384000, 0x06},
85462306a36Sopenharmony_ci	{11025, 0x09},
85562306a36Sopenharmony_ci	{22050, 0x0A},
85662306a36Sopenharmony_ci	{44100, 0x0B},
85762306a36Sopenharmony_ci	{88200, 0x0C},
85862306a36Sopenharmony_ci	{176400, 0x0D},
85962306a36Sopenharmony_ci	{8000, 0x11},
86062306a36Sopenharmony_ci	{16000, 0x12},
86162306a36Sopenharmony_ci	{32000, 0x13},
86262306a36Sopenharmony_ci};
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_cistatic int cs35l36_pcm_hw_params(struct snd_pcm_substream *substream,
86562306a36Sopenharmony_ci				 struct snd_pcm_hw_params *params,
86662306a36Sopenharmony_ci				 struct snd_soc_dai *dai)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
86962306a36Sopenharmony_ci			snd_soc_component_get_drvdata(dai->component);
87062306a36Sopenharmony_ci	unsigned int asp_width, global_fs = params_rate(params);
87162306a36Sopenharmony_ci	int i;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l36_fs_rates); i++) {
87462306a36Sopenharmony_ci		if (global_fs == cs35l36_fs_rates[i].rate)
87562306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap,
87662306a36Sopenharmony_ci					   CS35L36_GLOBAL_CLK_CTRL,
87762306a36Sopenharmony_ci					   CS35L36_GLOBAL_FS_MASK,
87862306a36Sopenharmony_ci					   cs35l36_fs_rates[i].fs_cfg <<
87962306a36Sopenharmony_ci					   CS35L36_GLOBAL_FS_SHIFT);
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	switch (params_width(params)) {
88362306a36Sopenharmony_ci	case 16:
88462306a36Sopenharmony_ci		asp_width = CS35L36_ASP_WIDTH_16;
88562306a36Sopenharmony_ci		break;
88662306a36Sopenharmony_ci	case 24:
88762306a36Sopenharmony_ci		asp_width = CS35L36_ASP_WIDTH_24;
88862306a36Sopenharmony_ci		break;
88962306a36Sopenharmony_ci	case 32:
89062306a36Sopenharmony_ci		asp_width = CS35L36_ASP_WIDTH_32;
89162306a36Sopenharmony_ci		break;
89262306a36Sopenharmony_ci	default:
89362306a36Sopenharmony_ci		return -EINVAL;
89462306a36Sopenharmony_ci	}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
89762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_ASP_FRAME_CTRL,
89862306a36Sopenharmony_ci				   CS35L36_ASP_RX_WIDTH_MASK,
89962306a36Sopenharmony_ci				   asp_width << CS35L36_ASP_RX_WIDTH_SHIFT);
90062306a36Sopenharmony_ci	} else {
90162306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_ASP_FRAME_CTRL,
90262306a36Sopenharmony_ci				   CS35L36_ASP_TX_WIDTH_MASK,
90362306a36Sopenharmony_ci				   asp_width << CS35L36_ASP_TX_WIDTH_SHIFT);
90462306a36Sopenharmony_ci	}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	return 0;
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_cistatic int cs35l36_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
91062306a36Sopenharmony_ci				  unsigned int freq, int dir)
91162306a36Sopenharmony_ci{
91262306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
91362306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
91462306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
91562306a36Sopenharmony_ci	int fs1, fs2;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	if (freq > CS35L36_FS_NOM_6MHZ) {
91862306a36Sopenharmony_ci		fs1 = CS35L36_FS1_DEFAULT_VAL;
91962306a36Sopenharmony_ci		fs2 = CS35L36_FS2_DEFAULT_VAL;
92062306a36Sopenharmony_ci	} else {
92162306a36Sopenharmony_ci		fs1 = 3 * DIV_ROUND_UP(CS35L36_FS_NOM_6MHZ * 4, freq) + 4;
92262306a36Sopenharmony_ci		fs2 = 5 * DIV_ROUND_UP(CS35L36_FS_NOM_6MHZ * 4, freq) + 4;
92362306a36Sopenharmony_ci	}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
92662306a36Sopenharmony_ci			CS35L36_TEST_UNLOCK1);
92762306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
92862306a36Sopenharmony_ci			CS35L36_TEST_UNLOCK2);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_TST_FS_MON0,
93162306a36Sopenharmony_ci			   CS35L36_FS1_WINDOW_MASK | CS35L36_FS2_WINDOW_MASK,
93262306a36Sopenharmony_ci			   fs1 | (fs2 << CS35L36_FS2_WINDOW_SHIFT));
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
93562306a36Sopenharmony_ci			CS35L36_TEST_LOCK1);
93662306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
93762306a36Sopenharmony_ci			CS35L36_TEST_LOCK2);
93862306a36Sopenharmony_ci	return 0;
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic const struct cs35l36_pll_config *cs35l36_get_clk_config(
94262306a36Sopenharmony_ci		struct cs35l36_private *cs35l36, int freq)
94362306a36Sopenharmony_ci{
94462306a36Sopenharmony_ci	int i;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l36_pll_sysclk); i++) {
94762306a36Sopenharmony_ci		if (cs35l36_pll_sysclk[i].freq == freq)
94862306a36Sopenharmony_ci			return &cs35l36_pll_sysclk[i];
94962306a36Sopenharmony_ci	}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	return NULL;
95262306a36Sopenharmony_ci}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_cistatic const unsigned int cs35l36_src_rates[] = {
95562306a36Sopenharmony_ci	8000, 12000, 11025, 16000, 22050, 24000, 32000,
95662306a36Sopenharmony_ci	44100, 48000, 88200, 96000, 176400, 192000, 384000
95762306a36Sopenharmony_ci};
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list cs35l36_constraints = {
96062306a36Sopenharmony_ci	.count  = ARRAY_SIZE(cs35l36_src_rates),
96162306a36Sopenharmony_ci	.list   = cs35l36_src_rates,
96262306a36Sopenharmony_ci};
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_cistatic int cs35l36_pcm_startup(struct snd_pcm_substream *substream,
96562306a36Sopenharmony_ci			       struct snd_soc_dai *dai)
96662306a36Sopenharmony_ci{
96762306a36Sopenharmony_ci	snd_pcm_hw_constraint_list(substream->runtime, 0,
96862306a36Sopenharmony_ci				SNDRV_PCM_HW_PARAM_RATE, &cs35l36_constraints);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	return 0;
97162306a36Sopenharmony_ci}
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_cistatic const struct snd_soc_dai_ops cs35l36_ops = {
97462306a36Sopenharmony_ci	.startup = cs35l36_pcm_startup,
97562306a36Sopenharmony_ci	.set_fmt = cs35l36_set_dai_fmt,
97662306a36Sopenharmony_ci	.hw_params = cs35l36_pcm_hw_params,
97762306a36Sopenharmony_ci	.set_sysclk = cs35l36_dai_set_sysclk,
97862306a36Sopenharmony_ci};
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic struct snd_soc_dai_driver cs35l36_dai[] = {
98162306a36Sopenharmony_ci	{
98262306a36Sopenharmony_ci		.name = "cs35l36-pcm",
98362306a36Sopenharmony_ci		.id = 0,
98462306a36Sopenharmony_ci		.playback = {
98562306a36Sopenharmony_ci			.stream_name = "AMP Playback",
98662306a36Sopenharmony_ci			.channels_min = 1,
98762306a36Sopenharmony_ci			.channels_max = 8,
98862306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
98962306a36Sopenharmony_ci			.formats = CS35L36_RX_FORMATS,
99062306a36Sopenharmony_ci		},
99162306a36Sopenharmony_ci		.capture = {
99262306a36Sopenharmony_ci			.stream_name = "AMP Capture",
99362306a36Sopenharmony_ci			.channels_min = 1,
99462306a36Sopenharmony_ci			.channels_max = 8,
99562306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_KNOT,
99662306a36Sopenharmony_ci			.formats = CS35L36_TX_FORMATS,
99762306a36Sopenharmony_ci		},
99862306a36Sopenharmony_ci		.ops = &cs35l36_ops,
99962306a36Sopenharmony_ci		.symmetric_rate = 1,
100062306a36Sopenharmony_ci	},
100162306a36Sopenharmony_ci};
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic int cs35l36_component_set_sysclk(struct snd_soc_component *component,
100462306a36Sopenharmony_ci				int clk_id, int source, unsigned int freq,
100562306a36Sopenharmony_ci				int dir)
100662306a36Sopenharmony_ci{
100762306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
100862306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
100962306a36Sopenharmony_ci	const struct cs35l36_pll_config *clk_cfg;
101062306a36Sopenharmony_ci	int prev_clksrc;
101162306a36Sopenharmony_ci	bool pdm_switch;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	prev_clksrc = cs35l36->clksrc;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	switch (clk_id) {
101662306a36Sopenharmony_ci	case 0:
101762306a36Sopenharmony_ci		cs35l36->clksrc = CS35L36_PLLSRC_SCLK;
101862306a36Sopenharmony_ci		break;
101962306a36Sopenharmony_ci	case 1:
102062306a36Sopenharmony_ci		cs35l36->clksrc = CS35L36_PLLSRC_LRCLK;
102162306a36Sopenharmony_ci		break;
102262306a36Sopenharmony_ci	case 2:
102362306a36Sopenharmony_ci		cs35l36->clksrc = CS35L36_PLLSRC_PDMCLK;
102462306a36Sopenharmony_ci		break;
102562306a36Sopenharmony_ci	case 3:
102662306a36Sopenharmony_ci		cs35l36->clksrc = CS35L36_PLLSRC_SELF;
102762306a36Sopenharmony_ci		break;
102862306a36Sopenharmony_ci	case 4:
102962306a36Sopenharmony_ci		cs35l36->clksrc = CS35L36_PLLSRC_MCLK;
103062306a36Sopenharmony_ci		break;
103162306a36Sopenharmony_ci	default:
103262306a36Sopenharmony_ci		return -EINVAL;
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	clk_cfg = cs35l36_get_clk_config(cs35l36, freq);
103662306a36Sopenharmony_ci	if (clk_cfg == NULL) {
103762306a36Sopenharmony_ci		dev_err(component->dev, "Invalid CLK Config Freq: %d\n", freq);
103862306a36Sopenharmony_ci		return -EINVAL;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
104262306a36Sopenharmony_ci			   CS35L36_PLL_OPENLOOP_MASK,
104362306a36Sopenharmony_ci			   1 << CS35L36_PLL_OPENLOOP_SHIFT);
104462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
104562306a36Sopenharmony_ci			   CS35L36_REFCLK_FREQ_MASK,
104662306a36Sopenharmony_ci			   clk_cfg->clk_cfg << CS35L36_REFCLK_FREQ_SHIFT);
104762306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
104862306a36Sopenharmony_ci			   CS35L36_PLL_REFCLK_EN_MASK,
104962306a36Sopenharmony_ci			   0 << CS35L36_PLL_REFCLK_EN_SHIFT);
105062306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
105162306a36Sopenharmony_ci			   CS35L36_PLL_CLK_SEL_MASK,
105262306a36Sopenharmony_ci			   cs35l36->clksrc);
105362306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
105462306a36Sopenharmony_ci			   CS35L36_PLL_OPENLOOP_MASK,
105562306a36Sopenharmony_ci			   0 << CS35L36_PLL_OPENLOOP_SHIFT);
105662306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PLL_CLK_CTRL,
105762306a36Sopenharmony_ci			   CS35L36_PLL_REFCLK_EN_MASK,
105862306a36Sopenharmony_ci			   1 << CS35L36_PLL_REFCLK_EN_SHIFT);
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	if (cs35l36->rev_id == CS35L36_REV_A0) {
106162306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
106262306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK1);
106362306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
106462306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK2);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_DCO_CTRL, 0x00036DA8);
106762306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_MISC_CTRL, 0x0100EE0E);
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PLL_LOOP_PARAMS,
107062306a36Sopenharmony_ci				   CS35L36_PLL_IGAIN_MASK,
107162306a36Sopenharmony_ci				   CS35L36_PLL_IGAIN <<
107262306a36Sopenharmony_ci				   CS35L36_PLL_IGAIN_SHIFT);
107362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PLL_LOOP_PARAMS,
107462306a36Sopenharmony_ci				   CS35L36_PLL_FFL_IGAIN_MASK,
107562306a36Sopenharmony_ci				   clk_cfg->fll_igain);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
107862306a36Sopenharmony_ci			     CS35L36_TEST_LOCK1);
107962306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
108062306a36Sopenharmony_ci			     CS35L36_TEST_LOCK2);
108162306a36Sopenharmony_ci	}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	if (cs35l36->clksrc == CS35L36_PLLSRC_PDMCLK) {
108462306a36Sopenharmony_ci		pdm_switch = cs35l36->ldm_mode_sel &&
108562306a36Sopenharmony_ci			     (prev_clksrc != CS35L36_PLLSRC_PDMCLK);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci		if (pdm_switch)
108862306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_NG_CFG,
108962306a36Sopenharmony_ci					   CS35L36_NG_DELAY_MASK,
109062306a36Sopenharmony_ci					   0 << CS35L36_NG_DELAY_SHIFT);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_DAC_MSM_CFG,
109362306a36Sopenharmony_ci				   CS35L36_PDM_MODE_MASK,
109462306a36Sopenharmony_ci				   1 << CS35L36_PDM_MODE_SHIFT);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci		if (pdm_switch)
109762306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_NG_CFG,
109862306a36Sopenharmony_ci					   CS35L36_NG_DELAY_MASK,
109962306a36Sopenharmony_ci					   3 << CS35L36_NG_DELAY_SHIFT);
110062306a36Sopenharmony_ci	} else {
110162306a36Sopenharmony_ci		pdm_switch = cs35l36->ldm_mode_sel &&
110262306a36Sopenharmony_ci			     (prev_clksrc == CS35L36_PLLSRC_PDMCLK);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci		if (pdm_switch)
110562306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_NG_CFG,
110662306a36Sopenharmony_ci					   CS35L36_NG_DELAY_MASK,
110762306a36Sopenharmony_ci					   0 << CS35L36_NG_DELAY_SHIFT);
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_DAC_MSM_CFG,
111062306a36Sopenharmony_ci				   CS35L36_PDM_MODE_MASK,
111162306a36Sopenharmony_ci				   0 << CS35L36_PDM_MODE_SHIFT);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci		if (pdm_switch)
111462306a36Sopenharmony_ci			regmap_update_bits(cs35l36->regmap, CS35L36_NG_CFG,
111562306a36Sopenharmony_ci					   CS35L36_NG_DELAY_MASK,
111662306a36Sopenharmony_ci					   3 << CS35L36_NG_DELAY_SHIFT);
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	return 0;
112062306a36Sopenharmony_ci}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_cistatic int cs35l36_boost_inductor(struct cs35l36_private *cs35l36, int inductor)
112362306a36Sopenharmony_ci{
112462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_COEFF,
112562306a36Sopenharmony_ci			   CS35L36_BSTCVRT_K1_MASK, 0x3C);
112662306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_COEFF,
112762306a36Sopenharmony_ci			   CS35L36_BSTCVRT_K2_MASK,
112862306a36Sopenharmony_ci			   0x3C << CS35L36_BSTCVRT_K2_SHIFT);
112962306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_SW_FREQ,
113062306a36Sopenharmony_ci			   CS35L36_BSTCVRT_CCMFREQ_MASK, 0x00);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	switch (inductor) {
113362306a36Sopenharmony_ci	case 1000: /* 1 uH */
113462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_SLOPE_LBST,
113562306a36Sopenharmony_ci				   CS35L36_BSTCVRT_SLOPE_MASK,
113662306a36Sopenharmony_ci				   0x75 << CS35L36_BSTCVRT_SLOPE_SHIFT);
113762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_SLOPE_LBST,
113862306a36Sopenharmony_ci				   CS35L36_BSTCVRT_LBSTVAL_MASK, 0x00);
113962306a36Sopenharmony_ci		break;
114062306a36Sopenharmony_ci	case 1200: /* 1.2 uH */
114162306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_SLOPE_LBST,
114262306a36Sopenharmony_ci				   CS35L36_BSTCVRT_SLOPE_MASK,
114362306a36Sopenharmony_ci				   0x6B << CS35L36_BSTCVRT_SLOPE_SHIFT);
114462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_SLOPE_LBST,
114562306a36Sopenharmony_ci				   CS35L36_BSTCVRT_LBSTVAL_MASK, 0x01);
114662306a36Sopenharmony_ci		break;
114762306a36Sopenharmony_ci	default:
114862306a36Sopenharmony_ci		dev_err(cs35l36->dev, "%s Invalid Inductor Value %d uH\n",
114962306a36Sopenharmony_ci			__func__, inductor);
115062306a36Sopenharmony_ci		return -EINVAL;
115162306a36Sopenharmony_ci	}
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	return 0;
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_cistatic int cs35l36_component_probe(struct snd_soc_component *component)
115762306a36Sopenharmony_ci{
115862306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 =
115962306a36Sopenharmony_ci			snd_soc_component_get_drvdata(component);
116062306a36Sopenharmony_ci	int ret;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if ((cs35l36->rev_id == CS35L36_REV_A0) && cs35l36->pdata.dcm_mode) {
116362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_DCM_CTRL,
116462306a36Sopenharmony_ci				   CS35L36_DCM_AUTO_MASK,
116562306a36Sopenharmony_ci				   CS35L36_DCM_AUTO_MASK);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
116862306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK1);
116962306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
117062306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK2);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BST_TST_MANUAL,
117362306a36Sopenharmony_ci				   CS35L36_BST_MAN_IPKCOMP_MASK,
117462306a36Sopenharmony_ci				   0 << CS35L36_BST_MAN_IPKCOMP_SHIFT);
117562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BST_TST_MANUAL,
117662306a36Sopenharmony_ci				   CS35L36_BST_MAN_IPKCOMP_EN_MASK,
117762306a36Sopenharmony_ci				   CS35L36_BST_MAN_IPKCOMP_EN_MASK);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
118062306a36Sopenharmony_ci				CS35L36_TEST_LOCK1);
118162306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
118262306a36Sopenharmony_ci				CS35L36_TEST_LOCK2);
118362306a36Sopenharmony_ci	}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	if (cs35l36->pdata.amp_pcm_inv)
118662306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_AMP_DIG_VOL_CTRL,
118762306a36Sopenharmony_ci				   CS35L36_AMP_PCM_INV_MASK,
118862306a36Sopenharmony_ci				   CS35L36_AMP_PCM_INV_MASK);
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	if (cs35l36->pdata.multi_amp_mode)
119162306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL,
119262306a36Sopenharmony_ci				   CS35L36_ASP_TX_HIZ_MASK,
119362306a36Sopenharmony_ci				   CS35L36_ASP_TX_HIZ_MASK);
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	if (cs35l36->pdata.imon_pol_inv)
119662306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_VI_SPKMON_FILT,
119762306a36Sopenharmony_ci				   CS35L36_IMON_POL_MASK, 0);
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	if (cs35l36->pdata.vmon_pol_inv)
120062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_VI_SPKMON_FILT,
120162306a36Sopenharmony_ci				   CS35L36_VMON_POL_MASK, 0);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	if (cs35l36->pdata.bst_vctl)
120462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_VCTRL1,
120562306a36Sopenharmony_ci				   CS35L35_BSTCVRT_CTL_MASK,
120662306a36Sopenharmony_ci				   cs35l36->pdata.bst_vctl);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	if (cs35l36->pdata.bst_vctl_sel)
120962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_VCTRL2,
121062306a36Sopenharmony_ci				   CS35L35_BSTCVRT_CTL_SEL_MASK,
121162306a36Sopenharmony_ci				   cs35l36->pdata.bst_vctl_sel);
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	if (cs35l36->pdata.bst_ipk)
121462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_PEAK_CUR,
121562306a36Sopenharmony_ci				   CS35L36_BST_IPK_MASK,
121662306a36Sopenharmony_ci				   cs35l36->pdata.bst_ipk);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	if (cs35l36->pdata.boost_ind) {
121962306a36Sopenharmony_ci		ret = cs35l36_boost_inductor(cs35l36, cs35l36->pdata.boost_ind);
122062306a36Sopenharmony_ci		if (ret < 0) {
122162306a36Sopenharmony_ci			dev_err(cs35l36->dev,
122262306a36Sopenharmony_ci				"Boost inductor config failed(%d)\n", ret);
122362306a36Sopenharmony_ci			return ret;
122462306a36Sopenharmony_ci		}
122562306a36Sopenharmony_ci	}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	if (cs35l36->pdata.temp_warn_thld)
122862306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_DTEMP_WARN_THLD,
122962306a36Sopenharmony_ci				   CS35L36_TEMP_THLD_MASK,
123062306a36Sopenharmony_ci				   cs35l36->pdata.temp_warn_thld);
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	if (cs35l36->pdata.irq_drv_sel)
123362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PAD_INTERFACE,
123462306a36Sopenharmony_ci				   CS35L36_INT_DRV_SEL_MASK,
123562306a36Sopenharmony_ci				   cs35l36->pdata.irq_drv_sel <<
123662306a36Sopenharmony_ci				   CS35L36_INT_DRV_SEL_SHIFT);
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	if (cs35l36->pdata.irq_gpio_sel)
123962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PAD_INTERFACE,
124062306a36Sopenharmony_ci				   CS35L36_INT_GPIO_SEL_MASK,
124162306a36Sopenharmony_ci				   cs35l36->pdata.irq_gpio_sel <<
124262306a36Sopenharmony_ci				   CS35L36_INT_GPIO_SEL_SHIFT);
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	/*
124562306a36Sopenharmony_ci	 * Rev B0 has 2 versions
124662306a36Sopenharmony_ci	 * L36 is 10V
124762306a36Sopenharmony_ci	 * L37 is 12V
124862306a36Sopenharmony_ci	 * If L36 we need to clamp some values for safety
124962306a36Sopenharmony_ci	 * after probe has setup dt values. We want to make
125062306a36Sopenharmony_ci	 * sure we dont miss any values set in probe
125162306a36Sopenharmony_ci	 */
125262306a36Sopenharmony_ci	if (cs35l36->chip_version == CS35L36_10V_L36) {
125362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap,
125462306a36Sopenharmony_ci				   CS35L36_BSTCVRT_OVERVOLT_CTRL,
125562306a36Sopenharmony_ci				   CS35L36_BST_OVP_THLD_MASK,
125662306a36Sopenharmony_ci				   CS35L36_BST_OVP_THLD_11V);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
125962306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK1);
126062306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
126162306a36Sopenharmony_ci			     CS35L36_TEST_UNLOCK2);
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BST_ANA2_TEST,
126462306a36Sopenharmony_ci				   CS35L36_BST_OVP_TRIM_MASK,
126562306a36Sopenharmony_ci				   CS35L36_BST_OVP_TRIM_11V <<
126662306a36Sopenharmony_ci				   CS35L36_BST_OVP_TRIM_SHIFT);
126762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_VCTRL2,
126862306a36Sopenharmony_ci				   CS35L36_BST_CTRL_LIM_MASK,
126962306a36Sopenharmony_ci				   1 << CS35L36_BST_CTRL_LIM_SHIFT);
127062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_VCTRL1,
127162306a36Sopenharmony_ci				   CS35L35_BSTCVRT_CTL_MASK,
127262306a36Sopenharmony_ci				   CS35L36_BST_CTRL_10V_CLAMP);
127362306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
127462306a36Sopenharmony_ci			     CS35L36_TEST_LOCK1);
127562306a36Sopenharmony_ci		regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
127662306a36Sopenharmony_ci			     CS35L36_TEST_LOCK2);
127762306a36Sopenharmony_ci	}
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	/*
128062306a36Sopenharmony_ci	 * RevA and B require the disabling of
128162306a36Sopenharmony_ci	 * SYNC_GLOBAL_OVR when GLOBAL_EN = 0.
128262306a36Sopenharmony_ci	 * Just turn it off from default
128362306a36Sopenharmony_ci	 */
128462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_CTRL_OVRRIDE,
128562306a36Sopenharmony_ci			   CS35L36_SYNC_GLOBAL_OVR_MASK,
128662306a36Sopenharmony_ci			   0 << CS35L36_SYNC_GLOBAL_OVR_SHIFT);
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	return 0;
128962306a36Sopenharmony_ci}
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_cs35l36 = {
129262306a36Sopenharmony_ci	.probe			= &cs35l36_component_probe,
129362306a36Sopenharmony_ci	.set_sysclk		= cs35l36_component_set_sysclk,
129462306a36Sopenharmony_ci	.dapm_widgets		= cs35l36_dapm_widgets,
129562306a36Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(cs35l36_dapm_widgets),
129662306a36Sopenharmony_ci	.dapm_routes		= cs35l36_audio_map,
129762306a36Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(cs35l36_audio_map),
129862306a36Sopenharmony_ci	.controls		= cs35l36_aud_controls,
129962306a36Sopenharmony_ci	.num_controls		= ARRAY_SIZE(cs35l36_aud_controls),
130062306a36Sopenharmony_ci	.idle_bias_on		= 1,
130162306a36Sopenharmony_ci	.use_pmdown_time	= 1,
130262306a36Sopenharmony_ci	.endianness		= 1,
130362306a36Sopenharmony_ci};
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_cistatic struct regmap_config cs35l36_regmap = {
130662306a36Sopenharmony_ci	.reg_bits = 32,
130762306a36Sopenharmony_ci	.val_bits = 32,
130862306a36Sopenharmony_ci	.reg_stride = 4,
130962306a36Sopenharmony_ci	.max_register = CS35L36_PAC_PMEM_WORD1023,
131062306a36Sopenharmony_ci	.reg_defaults = cs35l36_reg,
131162306a36Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(cs35l36_reg),
131262306a36Sopenharmony_ci	.precious_reg = cs35l36_precious_reg,
131362306a36Sopenharmony_ci	.volatile_reg = cs35l36_volatile_reg,
131462306a36Sopenharmony_ci	.readable_reg = cs35l36_readable_reg,
131562306a36Sopenharmony_ci	.cache_type = REGCACHE_MAPLE,
131662306a36Sopenharmony_ci};
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_cistatic irqreturn_t cs35l36_irq(int irq, void *data)
131962306a36Sopenharmony_ci{
132062306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 = data;
132162306a36Sopenharmony_ci	unsigned int status[4];
132262306a36Sopenharmony_ci	unsigned int masks[4];
132362306a36Sopenharmony_ci	int ret = IRQ_NONE;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	/* ack the irq by reading all status registers */
132662306a36Sopenharmony_ci	regmap_bulk_read(cs35l36->regmap, CS35L36_INT1_STATUS, status,
132762306a36Sopenharmony_ci			 ARRAY_SIZE(status));
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	regmap_bulk_read(cs35l36->regmap, CS35L36_INT1_MASK, masks,
133062306a36Sopenharmony_ci			 ARRAY_SIZE(masks));
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	/* Check to see if unmasked bits are active */
133362306a36Sopenharmony_ci	if (!(status[0] & ~masks[0]) && !(status[1] & ~masks[1]) &&
133462306a36Sopenharmony_ci		!(status[2] & ~masks[2]) && !(status[3] & ~masks[3])) {
133562306a36Sopenharmony_ci		return IRQ_NONE;
133662306a36Sopenharmony_ci	}
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	/*
133962306a36Sopenharmony_ci	 * The following interrupts require a
134062306a36Sopenharmony_ci	 * protection release cycle to get the
134162306a36Sopenharmony_ci	 * speaker out of Safe-Mode.
134262306a36Sopenharmony_ci	 */
134362306a36Sopenharmony_ci	if (status[2] & CS35L36_AMP_SHORT_ERR) {
134462306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "Amp short error\n");
134562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
134662306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR_RLS, 0);
134762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
134862306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR_RLS,
134962306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR_RLS);
135062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
135162306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR_RLS, 0);
135262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT3_STATUS,
135362306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR,
135462306a36Sopenharmony_ci				   CS35L36_AMP_SHORT_ERR);
135562306a36Sopenharmony_ci		ret = IRQ_HANDLED;
135662306a36Sopenharmony_ci	}
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	if (status[0] & CS35L36_TEMP_WARN) {
135962306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "Over temperature warning\n");
136062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
136162306a36Sopenharmony_ci				   CS35L36_TEMP_WARN_ERR_RLS, 0);
136262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
136362306a36Sopenharmony_ci				   CS35L36_TEMP_WARN_ERR_RLS,
136462306a36Sopenharmony_ci				   CS35L36_TEMP_WARN_ERR_RLS);
136562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
136662306a36Sopenharmony_ci				   CS35L36_TEMP_WARN_ERR_RLS, 0);
136762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT1_STATUS,
136862306a36Sopenharmony_ci				   CS35L36_TEMP_WARN, CS35L36_TEMP_WARN);
136962306a36Sopenharmony_ci		ret = IRQ_HANDLED;
137062306a36Sopenharmony_ci	}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	if (status[0] & CS35L36_TEMP_ERR) {
137362306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "Over temperature error\n");
137462306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
137562306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, 0);
137662306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
137762306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, CS35L36_TEMP_ERR_RLS);
137862306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
137962306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, 0);
138062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT1_STATUS,
138162306a36Sopenharmony_ci				   CS35L36_TEMP_ERR, CS35L36_TEMP_ERR);
138262306a36Sopenharmony_ci		ret = IRQ_HANDLED;
138362306a36Sopenharmony_ci	}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	if (status[0] & CS35L36_BST_OVP_ERR) {
138662306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "VBST Over Voltage error\n");
138762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
138862306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, 0);
138962306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
139062306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, CS35L36_TEMP_ERR_RLS);
139162306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
139262306a36Sopenharmony_ci				   CS35L36_TEMP_ERR_RLS, 0);
139362306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT1_STATUS,
139462306a36Sopenharmony_ci				   CS35L36_BST_OVP_ERR, CS35L36_BST_OVP_ERR);
139562306a36Sopenharmony_ci		ret = IRQ_HANDLED;
139662306a36Sopenharmony_ci	}
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	if (status[0] & CS35L36_BST_DCM_UVP_ERR) {
139962306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "DCM VBST Under Voltage Error\n");
140062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
140162306a36Sopenharmony_ci				   CS35L36_BST_UVP_ERR_RLS, 0);
140262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
140362306a36Sopenharmony_ci				   CS35L36_BST_UVP_ERR_RLS,
140462306a36Sopenharmony_ci				   CS35L36_BST_UVP_ERR_RLS);
140562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
140662306a36Sopenharmony_ci				   CS35L36_BST_UVP_ERR_RLS, 0);
140762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT1_STATUS,
140862306a36Sopenharmony_ci				   CS35L36_BST_DCM_UVP_ERR,
140962306a36Sopenharmony_ci				   CS35L36_BST_DCM_UVP_ERR);
141062306a36Sopenharmony_ci		ret = IRQ_HANDLED;
141162306a36Sopenharmony_ci	}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	if (status[0] & CS35L36_BST_SHORT_ERR) {
141462306a36Sopenharmony_ci		dev_crit(cs35l36->dev, "LBST SHORT error!\n");
141562306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
141662306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR_RLS, 0);
141762306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
141862306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR_RLS,
141962306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR_RLS);
142062306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_PROTECT_REL_ERR,
142162306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR_RLS, 0);
142262306a36Sopenharmony_ci		regmap_update_bits(cs35l36->regmap, CS35L36_INT1_STATUS,
142362306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR,
142462306a36Sopenharmony_ci				   CS35L36_BST_SHORT_ERR);
142562306a36Sopenharmony_ci		ret = IRQ_HANDLED;
142662306a36Sopenharmony_ci	}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	return ret;
142962306a36Sopenharmony_ci}
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_cistatic int cs35l36_handle_of_data(struct i2c_client *i2c_client,
143262306a36Sopenharmony_ci				struct cs35l36_platform_data *pdata)
143362306a36Sopenharmony_ci{
143462306a36Sopenharmony_ci	struct device_node *np = i2c_client->dev.of_node;
143562306a36Sopenharmony_ci	struct cs35l36_vpbr_cfg *vpbr_config = &pdata->vpbr_config;
143662306a36Sopenharmony_ci	struct device_node *vpbr_node;
143762306a36Sopenharmony_ci	unsigned int val;
143862306a36Sopenharmony_ci	int ret;
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	if (!np)
144162306a36Sopenharmony_ci		return 0;
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ctl-millivolt", &val);
144462306a36Sopenharmony_ci	if (!ret) {
144562306a36Sopenharmony_ci		if (val < 2550 || val > 12000) {
144662306a36Sopenharmony_ci			dev_err(&i2c_client->dev,
144762306a36Sopenharmony_ci				"Invalid Boost Voltage %d mV\n", val);
144862306a36Sopenharmony_ci			return -EINVAL;
144962306a36Sopenharmony_ci		}
145062306a36Sopenharmony_ci		pdata->bst_vctl = (((val - 2550) / 100) + 1) << 1;
145162306a36Sopenharmony_ci	} else {
145262306a36Sopenharmony_ci		dev_err(&i2c_client->dev,
145362306a36Sopenharmony_ci			"Unable to find required parameter 'cirrus,boost-ctl-millivolt'");
145462306a36Sopenharmony_ci		return -EINVAL;
145562306a36Sopenharmony_ci	}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-ctl-select", &val);
145862306a36Sopenharmony_ci	if (!ret)
145962306a36Sopenharmony_ci		pdata->bst_vctl_sel = val | CS35L36_VALID_PDATA;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	ret = of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val);
146262306a36Sopenharmony_ci	if (!ret) {
146362306a36Sopenharmony_ci		if (val < 1600 || val > 4500) {
146462306a36Sopenharmony_ci			dev_err(&i2c_client->dev,
146562306a36Sopenharmony_ci				"Invalid Boost Peak Current %u mA\n", val);
146662306a36Sopenharmony_ci			return -EINVAL;
146762306a36Sopenharmony_ci		}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci		pdata->bst_ipk = (val - 1600) / 50;
147062306a36Sopenharmony_ci	} else {
147162306a36Sopenharmony_ci		dev_err(&i2c_client->dev,
147262306a36Sopenharmony_ci			"Unable to find required parameter 'cirrus,boost-peak-milliamp'");
147362306a36Sopenharmony_ci		return -EINVAL;
147462306a36Sopenharmony_ci	}
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	pdata->multi_amp_mode = of_property_read_bool(np,
147762306a36Sopenharmony_ci					"cirrus,multi-amp-mode");
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	pdata->dcm_mode = of_property_read_bool(np,
148062306a36Sopenharmony_ci					"cirrus,dcm-mode-enable");
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	pdata->amp_pcm_inv = of_property_read_bool(np,
148362306a36Sopenharmony_ci					"cirrus,amp-pcm-inv");
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	pdata->imon_pol_inv = of_property_read_bool(np,
148662306a36Sopenharmony_ci					"cirrus,imon-pol-inv");
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	pdata->vmon_pol_inv = of_property_read_bool(np,
148962306a36Sopenharmony_ci					"cirrus,vmon-pol-inv");
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,temp-warn-threshold", &val) >= 0)
149262306a36Sopenharmony_ci		pdata->temp_warn_thld = val | CS35L36_VALID_PDATA;
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val) >= 0) {
149562306a36Sopenharmony_ci		pdata->boost_ind = val;
149662306a36Sopenharmony_ci	} else {
149762306a36Sopenharmony_ci		dev_err(&i2c_client->dev, "Inductor not specified.\n");
149862306a36Sopenharmony_ci		return -EINVAL;
149962306a36Sopenharmony_ci	}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,irq-drive-select", &val) >= 0)
150262306a36Sopenharmony_ci		pdata->irq_drv_sel = val | CS35L36_VALID_PDATA;
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	if (of_property_read_u32(np, "cirrus,irq-gpio-select", &val) >= 0)
150562306a36Sopenharmony_ci		pdata->irq_gpio_sel = val | CS35L36_VALID_PDATA;
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	/* VPBR Config */
150862306a36Sopenharmony_ci	vpbr_node = of_get_child_by_name(np, "cirrus,vpbr-config");
150962306a36Sopenharmony_ci	vpbr_config->is_present = vpbr_node ? true : false;
151062306a36Sopenharmony_ci	if (vpbr_config->is_present) {
151162306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-en",
151262306a36Sopenharmony_ci					 &val) >= 0)
151362306a36Sopenharmony_ci			vpbr_config->vpbr_en = val;
151462306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-thld",
151562306a36Sopenharmony_ci					 &val) >= 0)
151662306a36Sopenharmony_ci			vpbr_config->vpbr_thld = val;
151762306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-atk-rate",
151862306a36Sopenharmony_ci					 &val) >= 0)
151962306a36Sopenharmony_ci			vpbr_config->vpbr_atk_rate = val;
152062306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-atk-vol",
152162306a36Sopenharmony_ci					 &val) >= 0)
152262306a36Sopenharmony_ci			vpbr_config->vpbr_atk_vol = val;
152362306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-max-attn",
152462306a36Sopenharmony_ci					 &val) >= 0)
152562306a36Sopenharmony_ci			vpbr_config->vpbr_max_attn = val;
152662306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-wait",
152762306a36Sopenharmony_ci					 &val) >= 0)
152862306a36Sopenharmony_ci			vpbr_config->vpbr_wait = val;
152962306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-rel-rate",
153062306a36Sopenharmony_ci					 &val) >= 0)
153162306a36Sopenharmony_ci			vpbr_config->vpbr_rel_rate = val;
153262306a36Sopenharmony_ci		if (of_property_read_u32(vpbr_node, "cirrus,vpbr-mute-en",
153362306a36Sopenharmony_ci					 &val) >= 0)
153462306a36Sopenharmony_ci			vpbr_config->vpbr_mute_en = val;
153562306a36Sopenharmony_ci	}
153662306a36Sopenharmony_ci	of_node_put(vpbr_node);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	return 0;
153962306a36Sopenharmony_ci}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_cistatic int cs35l36_pac(struct cs35l36_private *cs35l36)
154262306a36Sopenharmony_ci{
154362306a36Sopenharmony_ci	int ret, count;
154462306a36Sopenharmony_ci	unsigned int val;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	if (cs35l36->rev_id != CS35L36_REV_B0)
154762306a36Sopenharmony_ci		return 0;
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	/*
155062306a36Sopenharmony_ci	 * Magic code for internal PAC
155162306a36Sopenharmony_ci	 */
155262306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
155362306a36Sopenharmony_ci		     CS35L36_TEST_UNLOCK1);
155462306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
155562306a36Sopenharmony_ci		     CS35L36_TEST_UNLOCK2);
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	usleep_range(9500, 10500);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_PAC_CTL1,
156062306a36Sopenharmony_ci		     CS35L36_PAC_RESET);
156162306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_PAC_CTL3,
156262306a36Sopenharmony_ci		     CS35L36_PAC_MEM_ACCESS);
156362306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_PAC_PMEM_WORD0,
156462306a36Sopenharmony_ci		     CS35L36_B0_PAC_PATCH);
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_PAC_CTL3,
156762306a36Sopenharmony_ci		     CS35L36_PAC_MEM_ACCESS_CLR);
156862306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_PAC_CTL1,
156962306a36Sopenharmony_ci		     CS35L36_PAC_ENABLE_MASK);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	usleep_range(9500, 10500);
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	ret = regmap_read(cs35l36->regmap, CS35L36_INT4_STATUS, &val);
157462306a36Sopenharmony_ci	if (ret < 0) {
157562306a36Sopenharmony_ci		dev_err(cs35l36->dev, "Failed to read int4_status %d\n", ret);
157662306a36Sopenharmony_ci		return ret;
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	count = 0;
158062306a36Sopenharmony_ci	while (!(val & CS35L36_MCU_CONFIG_CLR)) {
158162306a36Sopenharmony_ci		usleep_range(100, 200);
158262306a36Sopenharmony_ci		count++;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci		ret = regmap_read(cs35l36->regmap, CS35L36_INT4_STATUS,
158562306a36Sopenharmony_ci				  &val);
158662306a36Sopenharmony_ci		if (ret < 0) {
158762306a36Sopenharmony_ci			dev_err(cs35l36->dev, "Failed to read int4_status %d\n",
158862306a36Sopenharmony_ci				ret);
158962306a36Sopenharmony_ci			return ret;
159062306a36Sopenharmony_ci		}
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci		if (count >= 100)
159362306a36Sopenharmony_ci			return -EINVAL;
159462306a36Sopenharmony_ci	}
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_INT4_STATUS,
159762306a36Sopenharmony_ci		     CS35L36_MCU_CONFIG_CLR);
159862306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PAC_CTL1,
159962306a36Sopenharmony_ci			   CS35L36_PAC_ENABLE_MASK, 0);
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
160262306a36Sopenharmony_ci		     CS35L36_TEST_LOCK1);
160362306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_TESTKEY_CTRL,
160462306a36Sopenharmony_ci		     CS35L36_TEST_LOCK2);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	return 0;
160762306a36Sopenharmony_ci}
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_cistatic void cs35l36_apply_vpbr_config(struct cs35l36_private *cs35l36)
161062306a36Sopenharmony_ci{
161162306a36Sopenharmony_ci	struct cs35l36_platform_data *pdata = &cs35l36->pdata;
161262306a36Sopenharmony_ci	struct cs35l36_vpbr_cfg *vpbr_config = &pdata->vpbr_config;
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PWR_CTRL3,
161562306a36Sopenharmony_ci			   CS35L36_VPBR_EN_MASK,
161662306a36Sopenharmony_ci			   vpbr_config->vpbr_en <<
161762306a36Sopenharmony_ci			   CS35L36_VPBR_EN_SHIFT);
161862306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
161962306a36Sopenharmony_ci			   CS35L36_VPBR_THLD_MASK,
162062306a36Sopenharmony_ci			   vpbr_config->vpbr_thld <<
162162306a36Sopenharmony_ci			   CS35L36_VPBR_THLD_SHIFT);
162262306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
162362306a36Sopenharmony_ci			   CS35L36_VPBR_MAX_ATTN_MASK,
162462306a36Sopenharmony_ci			   vpbr_config->vpbr_max_attn <<
162562306a36Sopenharmony_ci			   CS35L36_VPBR_MAX_ATTN_SHIFT);
162662306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
162762306a36Sopenharmony_ci			   CS35L36_VPBR_ATK_VOL_MASK,
162862306a36Sopenharmony_ci			   vpbr_config->vpbr_atk_vol <<
162962306a36Sopenharmony_ci			   CS35L36_VPBR_ATK_VOL_SHIFT);
163062306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
163162306a36Sopenharmony_ci			   CS35L36_VPBR_ATK_RATE_MASK,
163262306a36Sopenharmony_ci			   vpbr_config->vpbr_atk_rate <<
163362306a36Sopenharmony_ci			   CS35L36_VPBR_ATK_RATE_SHIFT);
163462306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
163562306a36Sopenharmony_ci			   CS35L36_VPBR_WAIT_MASK,
163662306a36Sopenharmony_ci			   vpbr_config->vpbr_wait <<
163762306a36Sopenharmony_ci			   CS35L36_VPBR_WAIT_SHIFT);
163862306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
163962306a36Sopenharmony_ci			   CS35L36_VPBR_REL_RATE_MASK,
164062306a36Sopenharmony_ci			   vpbr_config->vpbr_rel_rate <<
164162306a36Sopenharmony_ci			   CS35L36_VPBR_REL_RATE_SHIFT);
164262306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_VPBR_CFG,
164362306a36Sopenharmony_ci			   CS35L36_VPBR_MUTE_EN_MASK,
164462306a36Sopenharmony_ci			   vpbr_config->vpbr_mute_en <<
164562306a36Sopenharmony_ci			   CS35L36_VPBR_MUTE_EN_SHIFT);
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cistatic const struct reg_sequence cs35l36_reva0_errata_patch[] = {
164962306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,		CS35L36_TEST_UNLOCK1 },
165062306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,		CS35L36_TEST_UNLOCK2 },
165162306a36Sopenharmony_ci	/* Errata Writes */
165262306a36Sopenharmony_ci	{ CS35L36_OTP_CTRL1,		0x00002060 },
165362306a36Sopenharmony_ci	{ CS35L36_OTP_CTRL2,		0x00000001 },
165462306a36Sopenharmony_ci	{ CS35L36_OTP_CTRL1,		0x00002460 },
165562306a36Sopenharmony_ci	{ CS35L36_OTP_CTRL2,		0x00000001 },
165662306a36Sopenharmony_ci	{ 0x00002088,			0x012A1838 },
165762306a36Sopenharmony_ci	{ 0x00003014,			0x0100EE0E },
165862306a36Sopenharmony_ci	{ 0x00003008,			0x0008184A },
165962306a36Sopenharmony_ci	{ 0x00007418,			0x509001C8 },
166062306a36Sopenharmony_ci	{ 0x00007064,			0x0929A800 },
166162306a36Sopenharmony_ci	{ 0x00002D10,			0x0002C01C },
166262306a36Sopenharmony_ci	{ 0x0000410C,			0x00000A11 },
166362306a36Sopenharmony_ci	{ 0x00006E08,			0x8B19140C },
166462306a36Sopenharmony_ci	{ 0x00006454,			0x0300000A },
166562306a36Sopenharmony_ci	{ CS35L36_AMP_NG_CTRL,		0x000020EF },
166662306a36Sopenharmony_ci	{ 0x00007E34,			0x0000000E },
166762306a36Sopenharmony_ci	{ 0x0000410C,			0x00000A11 },
166862306a36Sopenharmony_ci	{ 0x00007410,			0x20514B00 },
166962306a36Sopenharmony_ci	/* PAC Config */
167062306a36Sopenharmony_ci	{ CS35L36_CTRL_OVRRIDE,		0x00000000 },
167162306a36Sopenharmony_ci	{ CS35L36_PAC_INT0_CTRL,	0x00860001 },
167262306a36Sopenharmony_ci	{ CS35L36_PAC_INT1_CTRL,	0x00860001 },
167362306a36Sopenharmony_ci	{ CS35L36_PAC_INT2_CTRL,	0x00860001 },
167462306a36Sopenharmony_ci	{ CS35L36_PAC_INT3_CTRL,	0x00860001 },
167562306a36Sopenharmony_ci	{ CS35L36_PAC_INT4_CTRL,	0x00860001 },
167662306a36Sopenharmony_ci	{ CS35L36_PAC_INT5_CTRL,	0x00860001 },
167762306a36Sopenharmony_ci	{ CS35L36_PAC_INT6_CTRL,	0x00860001 },
167862306a36Sopenharmony_ci	{ CS35L36_PAC_INT7_CTRL,	0x00860001 },
167962306a36Sopenharmony_ci	{ CS35L36_PAC_INT_FLUSH_CTRL,	0x000000FF },
168062306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,		CS35L36_TEST_LOCK1 },
168162306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,		CS35L36_TEST_LOCK2 },
168262306a36Sopenharmony_ci};
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_cistatic const struct reg_sequence cs35l36_revb0_errata_patch[] = {
168562306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,	CS35L36_TEST_UNLOCK1 },
168662306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL, CS35L36_TEST_UNLOCK2 },
168762306a36Sopenharmony_ci	{ 0x00007064,		0x0929A800 },
168862306a36Sopenharmony_ci	{ 0x00007850,		0x00002FA9 },
168962306a36Sopenharmony_ci	{ 0x00007854,		0x0003F1D5 },
169062306a36Sopenharmony_ci	{ 0x00007858,		0x0003F5E3 },
169162306a36Sopenharmony_ci	{ 0x0000785C,		0x00001137 },
169262306a36Sopenharmony_ci	{ 0x00007860,		0x0001A7A5 },
169362306a36Sopenharmony_ci	{ 0x00007864,		0x0002F16A },
169462306a36Sopenharmony_ci	{ 0x00007868,		0x00003E21 },
169562306a36Sopenharmony_ci	{ 0x00007848,		0x00000001 },
169662306a36Sopenharmony_ci	{ 0x00003854,		0x05180240 },
169762306a36Sopenharmony_ci	{ 0x00007418,		0x509001C8 },
169862306a36Sopenharmony_ci	{ 0x0000394C,		0x028764BD },
169962306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL,	CS35L36_TEST_LOCK1 },
170062306a36Sopenharmony_ci	{ CS35L36_TESTKEY_CTRL, CS35L36_TEST_LOCK2 },
170162306a36Sopenharmony_ci};
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_cistatic int cs35l36_i2c_probe(struct i2c_client *i2c_client)
170462306a36Sopenharmony_ci{
170562306a36Sopenharmony_ci	struct cs35l36_private *cs35l36;
170662306a36Sopenharmony_ci	struct device *dev = &i2c_client->dev;
170762306a36Sopenharmony_ci	struct cs35l36_platform_data *pdata = dev_get_platdata(dev);
170862306a36Sopenharmony_ci	struct irq_data *irq_d;
170962306a36Sopenharmony_ci	int ret, irq_pol, chip_irq_pol, i;
171062306a36Sopenharmony_ci	u32 reg_id, reg_revid, l37_id_reg;
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	cs35l36 = devm_kzalloc(dev, sizeof(struct cs35l36_private), GFP_KERNEL);
171362306a36Sopenharmony_ci	if (!cs35l36)
171462306a36Sopenharmony_ci		return -ENOMEM;
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci	cs35l36->dev = dev;
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	i2c_set_clientdata(i2c_client, cs35l36);
171962306a36Sopenharmony_ci	cs35l36->regmap = devm_regmap_init_i2c(i2c_client, &cs35l36_regmap);
172062306a36Sopenharmony_ci	if (IS_ERR(cs35l36->regmap)) {
172162306a36Sopenharmony_ci		ret = PTR_ERR(cs35l36->regmap);
172262306a36Sopenharmony_ci		dev_err(dev, "regmap_init() failed: %d\n", ret);
172362306a36Sopenharmony_ci		return ret;
172462306a36Sopenharmony_ci	}
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	cs35l36->num_supplies = ARRAY_SIZE(cs35l36_supplies);
172762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cs35l36_supplies); i++)
172862306a36Sopenharmony_ci		cs35l36->supplies[i].supply = cs35l36_supplies[i];
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	ret = devm_regulator_bulk_get(dev, cs35l36->num_supplies,
173162306a36Sopenharmony_ci				      cs35l36->supplies);
173262306a36Sopenharmony_ci	if (ret != 0) {
173362306a36Sopenharmony_ci		dev_err(dev, "Failed to request core supplies: %d\n", ret);
173462306a36Sopenharmony_ci		return ret;
173562306a36Sopenharmony_ci	}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	if (pdata) {
173862306a36Sopenharmony_ci		cs35l36->pdata = *pdata;
173962306a36Sopenharmony_ci	} else {
174062306a36Sopenharmony_ci		pdata = devm_kzalloc(dev, sizeof(struct cs35l36_platform_data),
174162306a36Sopenharmony_ci				     GFP_KERNEL);
174262306a36Sopenharmony_ci		if (!pdata)
174362306a36Sopenharmony_ci			return -ENOMEM;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci		if (i2c_client->dev.of_node) {
174662306a36Sopenharmony_ci			ret = cs35l36_handle_of_data(i2c_client, pdata);
174762306a36Sopenharmony_ci			if (ret != 0)
174862306a36Sopenharmony_ci				return ret;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci		}
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci		cs35l36->pdata = *pdata;
175362306a36Sopenharmony_ci	}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	ret = regulator_bulk_enable(cs35l36->num_supplies, cs35l36->supplies);
175662306a36Sopenharmony_ci	if (ret != 0) {
175762306a36Sopenharmony_ci		dev_err(dev, "Failed to enable core supplies: %d\n", ret);
175862306a36Sopenharmony_ci		return ret;
175962306a36Sopenharmony_ci	}
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	/* returning NULL can be an option if in stereo mode */
176262306a36Sopenharmony_ci	cs35l36->reset_gpio = devm_gpiod_get_optional(dev, "reset",
176362306a36Sopenharmony_ci						      GPIOD_OUT_LOW);
176462306a36Sopenharmony_ci	if (IS_ERR(cs35l36->reset_gpio)) {
176562306a36Sopenharmony_ci		ret = PTR_ERR(cs35l36->reset_gpio);
176662306a36Sopenharmony_ci		cs35l36->reset_gpio = NULL;
176762306a36Sopenharmony_ci		if (ret == -EBUSY) {
176862306a36Sopenharmony_ci			dev_info(dev, "Reset line busy, assuming shared reset\n");
176962306a36Sopenharmony_ci		} else {
177062306a36Sopenharmony_ci			dev_err(dev, "Failed to get reset GPIO: %d\n", ret);
177162306a36Sopenharmony_ci			goto err_disable_regs;
177262306a36Sopenharmony_ci		}
177362306a36Sopenharmony_ci	}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	if (cs35l36->reset_gpio)
177662306a36Sopenharmony_ci		gpiod_set_value_cansleep(cs35l36->reset_gpio, 1);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	usleep_range(2000, 2100);
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	/* initialize amplifier */
178162306a36Sopenharmony_ci	ret = regmap_read(cs35l36->regmap, CS35L36_SW_RESET, &reg_id);
178262306a36Sopenharmony_ci	if (ret < 0) {
178362306a36Sopenharmony_ci		dev_err(dev, "Get Device ID failed %d\n", ret);
178462306a36Sopenharmony_ci		goto err;
178562306a36Sopenharmony_ci	}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	if (reg_id != CS35L36_CHIP_ID) {
178862306a36Sopenharmony_ci		dev_err(dev, "Device ID (%X). Expected ID %X\n", reg_id,
178962306a36Sopenharmony_ci			CS35L36_CHIP_ID);
179062306a36Sopenharmony_ci		ret = -ENODEV;
179162306a36Sopenharmony_ci		goto err;
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	ret = regmap_read(cs35l36->regmap, CS35L36_REV_ID, &reg_revid);
179562306a36Sopenharmony_ci	if (ret < 0) {
179662306a36Sopenharmony_ci		dev_err(&i2c_client->dev, "Get Revision ID failed %d\n", ret);
179762306a36Sopenharmony_ci		goto err;
179862306a36Sopenharmony_ci	}
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	cs35l36->rev_id = reg_revid >> 8;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	ret = regmap_read(cs35l36->regmap, CS35L36_OTP_MEM30, &l37_id_reg);
180362306a36Sopenharmony_ci	if (ret < 0) {
180462306a36Sopenharmony_ci		dev_err(&i2c_client->dev, "Failed to read otp_id Register %d\n",
180562306a36Sopenharmony_ci			ret);
180662306a36Sopenharmony_ci		goto err;
180762306a36Sopenharmony_ci	}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	if ((l37_id_reg & CS35L36_OTP_REV_MASK) == CS35L36_OTP_REV_L37)
181062306a36Sopenharmony_ci		cs35l36->chip_version = CS35L36_12V_L37;
181162306a36Sopenharmony_ci	else
181262306a36Sopenharmony_ci		cs35l36->chip_version = CS35L36_10V_L36;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	switch (cs35l36->rev_id) {
181562306a36Sopenharmony_ci	case CS35L36_REV_A0:
181662306a36Sopenharmony_ci		ret = regmap_register_patch(cs35l36->regmap,
181762306a36Sopenharmony_ci				cs35l36_reva0_errata_patch,
181862306a36Sopenharmony_ci				ARRAY_SIZE(cs35l36_reva0_errata_patch));
181962306a36Sopenharmony_ci		if (ret < 0) {
182062306a36Sopenharmony_ci			dev_err(dev, "Failed to apply A0 errata patch %d\n",
182162306a36Sopenharmony_ci				ret);
182262306a36Sopenharmony_ci			goto err;
182362306a36Sopenharmony_ci		}
182462306a36Sopenharmony_ci		break;
182562306a36Sopenharmony_ci	case CS35L36_REV_B0:
182662306a36Sopenharmony_ci		ret = cs35l36_pac(cs35l36);
182762306a36Sopenharmony_ci		if (ret < 0) {
182862306a36Sopenharmony_ci			dev_err(dev, "Failed to Trim OTP %d\n", ret);
182962306a36Sopenharmony_ci			goto err;
183062306a36Sopenharmony_ci		}
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci		ret = regmap_register_patch(cs35l36->regmap,
183362306a36Sopenharmony_ci				cs35l36_revb0_errata_patch,
183462306a36Sopenharmony_ci				ARRAY_SIZE(cs35l36_revb0_errata_patch));
183562306a36Sopenharmony_ci		if (ret < 0) {
183662306a36Sopenharmony_ci			dev_err(dev, "Failed to apply B0 errata patch %d\n",
183762306a36Sopenharmony_ci				ret);
183862306a36Sopenharmony_ci			goto err;
183962306a36Sopenharmony_ci		}
184062306a36Sopenharmony_ci		break;
184162306a36Sopenharmony_ci	}
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	if (pdata->vpbr_config.is_present)
184462306a36Sopenharmony_ci		cs35l36_apply_vpbr_config(cs35l36);
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	irq_d = irq_get_irq_data(i2c_client->irq);
184762306a36Sopenharmony_ci	if (!irq_d) {
184862306a36Sopenharmony_ci		dev_err(&i2c_client->dev, "Invalid IRQ: %d\n", i2c_client->irq);
184962306a36Sopenharmony_ci		ret = -ENODEV;
185062306a36Sopenharmony_ci		goto err;
185162306a36Sopenharmony_ci	}
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	irq_pol = irqd_get_trigger_type(irq_d);
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	switch (irq_pol) {
185662306a36Sopenharmony_ci	case IRQF_TRIGGER_FALLING:
185762306a36Sopenharmony_ci	case IRQF_TRIGGER_LOW:
185862306a36Sopenharmony_ci		chip_irq_pol = 0;
185962306a36Sopenharmony_ci		break;
186062306a36Sopenharmony_ci	case IRQF_TRIGGER_RISING:
186162306a36Sopenharmony_ci	case IRQF_TRIGGER_HIGH:
186262306a36Sopenharmony_ci		chip_irq_pol = 1;
186362306a36Sopenharmony_ci		break;
186462306a36Sopenharmony_ci	default:
186562306a36Sopenharmony_ci		dev_err(cs35l36->dev, "Invalid IRQ polarity: %d\n", irq_pol);
186662306a36Sopenharmony_ci		ret = -EINVAL;
186762306a36Sopenharmony_ci		goto err;
186862306a36Sopenharmony_ci	}
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PAD_INTERFACE,
187162306a36Sopenharmony_ci			   CS35L36_INT_POL_SEL_MASK,
187262306a36Sopenharmony_ci			   chip_irq_pol << CS35L36_INT_POL_SEL_SHIFT);
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	ret = devm_request_threaded_irq(dev, i2c_client->irq, NULL, cs35l36_irq,
187562306a36Sopenharmony_ci					IRQF_ONESHOT | irq_pol, "cs35l36",
187662306a36Sopenharmony_ci					cs35l36);
187762306a36Sopenharmony_ci	if (ret != 0) {
187862306a36Sopenharmony_ci		dev_err(dev, "Failed to request IRQ: %d\n", ret);
187962306a36Sopenharmony_ci		goto err;
188062306a36Sopenharmony_ci	}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	regmap_update_bits(cs35l36->regmap, CS35L36_PAD_INTERFACE,
188362306a36Sopenharmony_ci			   CS35L36_INT_OUTPUT_EN_MASK, 1);
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	/* Set interrupt masks for critical errors */
188662306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_INT1_MASK,
188762306a36Sopenharmony_ci		     CS35L36_INT1_MASK_DEFAULT);
188862306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_INT3_MASK,
188962306a36Sopenharmony_ci		     CS35L36_INT3_MASK_DEFAULT);
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	dev_info(&i2c_client->dev, "Cirrus Logic CS35L%d, Revision: %02X\n",
189262306a36Sopenharmony_ci		 cs35l36->chip_version, reg_revid >> 8);
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	ret =  devm_snd_soc_register_component(dev, &soc_component_dev_cs35l36,
189562306a36Sopenharmony_ci					       cs35l36_dai,
189662306a36Sopenharmony_ci					       ARRAY_SIZE(cs35l36_dai));
189762306a36Sopenharmony_ci	if (ret < 0) {
189862306a36Sopenharmony_ci		dev_err(dev, "%s: Register component failed %d\n", __func__,
189962306a36Sopenharmony_ci			ret);
190062306a36Sopenharmony_ci		goto err;
190162306a36Sopenharmony_ci	}
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	return 0;
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_cierr:
190662306a36Sopenharmony_ci	gpiod_set_value_cansleep(cs35l36->reset_gpio, 0);
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_cierr_disable_regs:
190962306a36Sopenharmony_ci	regulator_bulk_disable(cs35l36->num_supplies, cs35l36->supplies);
191062306a36Sopenharmony_ci	return ret;
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic void cs35l36_i2c_remove(struct i2c_client *client)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	struct cs35l36_private *cs35l36 = i2c_get_clientdata(client);
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	/* Reset interrupt masks for device removal */
191862306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_INT1_MASK,
191962306a36Sopenharmony_ci		     CS35L36_INT1_MASK_RESET);
192062306a36Sopenharmony_ci	regmap_write(cs35l36->regmap, CS35L36_INT3_MASK,
192162306a36Sopenharmony_ci		     CS35L36_INT3_MASK_RESET);
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	if (cs35l36->reset_gpio)
192462306a36Sopenharmony_ci		gpiod_set_value_cansleep(cs35l36->reset_gpio, 0);
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	regulator_bulk_disable(cs35l36->num_supplies, cs35l36->supplies);
192762306a36Sopenharmony_ci}
192862306a36Sopenharmony_cistatic const struct of_device_id cs35l36_of_match[] = {
192962306a36Sopenharmony_ci	{.compatible = "cirrus,cs35l36"},
193062306a36Sopenharmony_ci	{},
193162306a36Sopenharmony_ci};
193262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cs35l36_of_match);
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_cistatic const struct i2c_device_id cs35l36_id[] = {
193562306a36Sopenharmony_ci	{"cs35l36", 0},
193662306a36Sopenharmony_ci	{}
193762306a36Sopenharmony_ci};
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, cs35l36_id);
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_cistatic struct i2c_driver cs35l36_i2c_driver = {
194262306a36Sopenharmony_ci	.driver = {
194362306a36Sopenharmony_ci		.name = "cs35l36",
194462306a36Sopenharmony_ci		.of_match_table = cs35l36_of_match,
194562306a36Sopenharmony_ci	},
194662306a36Sopenharmony_ci	.id_table = cs35l36_id,
194762306a36Sopenharmony_ci	.probe = cs35l36_i2c_probe,
194862306a36Sopenharmony_ci	.remove = cs35l36_i2c_remove,
194962306a36Sopenharmony_ci};
195062306a36Sopenharmony_cimodule_i2c_driver(cs35l36_i2c_driver);
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC CS35L36 driver");
195362306a36Sopenharmony_ciMODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
195462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1955