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, ®); 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, &_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, ®_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, ®_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