162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// Copyright (c) 2022, Analog Devices Inc. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 562306a36Sopenharmony_ci#include <linux/i2c.h> 662306a36Sopenharmony_ci#include <linux/module.h> 762306a36Sopenharmony_ci#include <sound/pcm_params.h> 862306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 962306a36Sopenharmony_ci#include <sound/soc.h> 1062306a36Sopenharmony_ci#include <linux/gpio.h> 1162306a36Sopenharmony_ci#include <sound/tlv.h> 1262306a36Sopenharmony_ci#include "max98396.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic const char * const max98396_core_supplies[MAX98396_NUM_CORE_SUPPLIES] = { 1562306a36Sopenharmony_ci "avdd", 1662306a36Sopenharmony_ci "dvdd", 1762306a36Sopenharmony_ci "dvddio", 1862306a36Sopenharmony_ci}; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic struct reg_default max98396_reg[] = { 2162306a36Sopenharmony_ci {MAX98396_R2000_SW_RESET, 0x00}, 2262306a36Sopenharmony_ci {MAX98396_R2001_INT_RAW1, 0x00}, 2362306a36Sopenharmony_ci {MAX98396_R2002_INT_RAW2, 0x00}, 2462306a36Sopenharmony_ci {MAX98396_R2003_INT_RAW3, 0x00}, 2562306a36Sopenharmony_ci {MAX98396_R2004_INT_RAW4, 0x00}, 2662306a36Sopenharmony_ci {MAX98396_R2006_INT_STATE1, 0x00}, 2762306a36Sopenharmony_ci {MAX98396_R2007_INT_STATE2, 0x00}, 2862306a36Sopenharmony_ci {MAX98396_R2008_INT_STATE3, 0x00}, 2962306a36Sopenharmony_ci {MAX98396_R2009_INT_STATE4, 0x00}, 3062306a36Sopenharmony_ci {MAX98396_R200B_INT_FLAG1, 0x00}, 3162306a36Sopenharmony_ci {MAX98396_R200C_INT_FLAG2, 0x00}, 3262306a36Sopenharmony_ci {MAX98396_R200D_INT_FLAG3, 0x00}, 3362306a36Sopenharmony_ci {MAX98396_R200E_INT_FLAG4, 0x00}, 3462306a36Sopenharmony_ci {MAX98396_R2010_INT_EN1, 0x02}, 3562306a36Sopenharmony_ci {MAX98396_R2011_INT_EN2, 0x00}, 3662306a36Sopenharmony_ci {MAX98396_R2012_INT_EN3, 0x00}, 3762306a36Sopenharmony_ci {MAX98396_R2013_INT_EN4, 0x00}, 3862306a36Sopenharmony_ci {MAX98396_R2015_INT_FLAG_CLR1, 0x00}, 3962306a36Sopenharmony_ci {MAX98396_R2016_INT_FLAG_CLR2, 0x00}, 4062306a36Sopenharmony_ci {MAX98396_R2017_INT_FLAG_CLR3, 0x00}, 4162306a36Sopenharmony_ci {MAX98396_R2018_INT_FLAG_CLR4, 0x00}, 4262306a36Sopenharmony_ci {MAX98396_R201F_IRQ_CTRL, 0x00}, 4362306a36Sopenharmony_ci {MAX98396_R2020_THERM_WARN_THRESH, 0x46}, 4462306a36Sopenharmony_ci {MAX98396_R2021_THERM_WARN_THRESH2, 0x46}, 4562306a36Sopenharmony_ci {MAX98396_R2022_THERM_SHDN_THRESH, 0x64}, 4662306a36Sopenharmony_ci {MAX98396_R2023_THERM_HYSTERESIS, 0x02}, 4762306a36Sopenharmony_ci {MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5}, 4862306a36Sopenharmony_ci {MAX98396_R2027_THERM_FOLDBACK_EN, 0x01}, 4962306a36Sopenharmony_ci {MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32}, 5062306a36Sopenharmony_ci {MAX98396_R2033_NOISEGATE_MODE_EN, 0x00}, 5162306a36Sopenharmony_ci {MAX98396_R2038_CLK_MON_CTRL, 0x00}, 5262306a36Sopenharmony_ci {MAX98396_R2039_DATA_MON_CTRL, 0x00}, 5362306a36Sopenharmony_ci {MAX98396_R203F_ENABLE_CTRLS, 0x0F}, 5462306a36Sopenharmony_ci {MAX98396_R2040_PIN_CFG, 0x55}, 5562306a36Sopenharmony_ci {MAX98396_R2041_PCM_MODE_CFG, 0xC0}, 5662306a36Sopenharmony_ci {MAX98396_R2042_PCM_CLK_SETUP, 0x04}, 5762306a36Sopenharmony_ci {MAX98396_R2043_PCM_SR_SETUP, 0x88}, 5862306a36Sopenharmony_ci {MAX98396_R2044_PCM_TX_CTRL_1, 0x00}, 5962306a36Sopenharmony_ci {MAX98396_R2045_PCM_TX_CTRL_2, 0x00}, 6062306a36Sopenharmony_ci {MAX98396_R2046_PCM_TX_CTRL_3, 0x00}, 6162306a36Sopenharmony_ci {MAX98396_R2047_PCM_TX_CTRL_4, 0x00}, 6262306a36Sopenharmony_ci {MAX98396_R2048_PCM_TX_CTRL_5, 0x00}, 6362306a36Sopenharmony_ci {MAX98396_R2049_PCM_TX_CTRL_6, 0x00}, 6462306a36Sopenharmony_ci {MAX98396_R204A_PCM_TX_CTRL_7, 0x00}, 6562306a36Sopenharmony_ci {MAX98396_R204B_PCM_TX_CTRL_8, 0x00}, 6662306a36Sopenharmony_ci {MAX98396_R204C_PCM_TX_HIZ_CTRL_1, 0xFF}, 6762306a36Sopenharmony_ci {MAX98396_R204D_PCM_TX_HIZ_CTRL_2, 0xFF}, 6862306a36Sopenharmony_ci {MAX98396_R204E_PCM_TX_HIZ_CTRL_3, 0xFF}, 6962306a36Sopenharmony_ci {MAX98396_R204F_PCM_TX_HIZ_CTRL_4, 0xFF}, 7062306a36Sopenharmony_ci {MAX98396_R2050_PCM_TX_HIZ_CTRL_5, 0xFF}, 7162306a36Sopenharmony_ci {MAX98396_R2051_PCM_TX_HIZ_CTRL_6, 0xFF}, 7262306a36Sopenharmony_ci {MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 0xFF}, 7362306a36Sopenharmony_ci {MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 0xFF}, 7462306a36Sopenharmony_ci {MAX98396_R2055_PCM_RX_SRC1, 0x00}, 7562306a36Sopenharmony_ci {MAX98396_R2056_PCM_RX_SRC2, 0x00}, 7662306a36Sopenharmony_ci {MAX98396_R2058_PCM_BYPASS_SRC, 0x00}, 7762306a36Sopenharmony_ci {MAX98396_R205D_PCM_TX_SRC_EN, 0x00}, 7862306a36Sopenharmony_ci {MAX98396_R205E_PCM_RX_EN, 0x00}, 7962306a36Sopenharmony_ci {MAX98396_R205F_PCM_TX_EN, 0x00}, 8062306a36Sopenharmony_ci {MAX98396_R2070_ICC_RX_EN_A, 0x00}, 8162306a36Sopenharmony_ci {MAX98396_R2071_ICC_RX_EN_B, 0x00}, 8262306a36Sopenharmony_ci {MAX98396_R2072_ICC_TX_CTRL, 0x00}, 8362306a36Sopenharmony_ci {MAX98396_R207F_ICC_EN, 0x00}, 8462306a36Sopenharmony_ci {MAX98396_R2083_TONE_GEN_DC_CFG, 0x04}, 8562306a36Sopenharmony_ci {MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00}, 8662306a36Sopenharmony_ci {MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00}, 8762306a36Sopenharmony_ci {MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00}, 8862306a36Sopenharmony_ci {MAX98396_R208F_TONE_GEN_EN, 0x00}, 8962306a36Sopenharmony_ci {MAX98396_R2090_AMP_VOL_CTRL, 0x00}, 9062306a36Sopenharmony_ci {MAX98396_R2091_AMP_PATH_GAIN, 0x0B}, 9162306a36Sopenharmony_ci {MAX98396_R2092_AMP_DSP_CFG, 0x23}, 9262306a36Sopenharmony_ci {MAX98396_R2093_SSM_CFG, 0x0D}, 9362306a36Sopenharmony_ci {MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12}, 9462306a36Sopenharmony_ci {MAX98396_R2095_SPK_CLS_DG_HDR, 0x17}, 9562306a36Sopenharmony_ci {MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17}, 9662306a36Sopenharmony_ci {MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00}, 9762306a36Sopenharmony_ci {MAX98396_R2098_SPK_CLS_DG_MODE, 0x00}, 9862306a36Sopenharmony_ci {MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03}, 9962306a36Sopenharmony_ci {MAX98396_R209A_SPK_EDGE_CTRL, 0x00}, 10062306a36Sopenharmony_ci {MAX98396_R209C_SPK_EDGE_CTRL1, 0x0A}, 10162306a36Sopenharmony_ci {MAX98396_R209D_SPK_EDGE_CTRL2, 0xAA}, 10262306a36Sopenharmony_ci {MAX98396_R209E_AMP_CLIP_GAIN, 0x00}, 10362306a36Sopenharmony_ci {MAX98396_R209F_BYPASS_PATH_CFG, 0x00}, 10462306a36Sopenharmony_ci {MAX98396_R20A0_AMP_SUPPLY_CTL, 0x00}, 10562306a36Sopenharmony_ci {MAX98396_R20AF_AMP_EN, 0x00}, 10662306a36Sopenharmony_ci {MAX98396_R20B0_ADC_SR, 0x30}, 10762306a36Sopenharmony_ci {MAX98396_R20B1_ADC_PVDD_CFG, 0x00}, 10862306a36Sopenharmony_ci {MAX98396_R20B2_ADC_VBAT_CFG, 0x00}, 10962306a36Sopenharmony_ci {MAX98396_R20B3_ADC_THERMAL_CFG, 0x00}, 11062306a36Sopenharmony_ci {MAX98396_R20B4_ADC_READBACK_CTRL1, 0x00}, 11162306a36Sopenharmony_ci {MAX98396_R20B5_ADC_READBACK_CTRL2, 0x00}, 11262306a36Sopenharmony_ci {MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0x00}, 11362306a36Sopenharmony_ci {MAX98396_R20B7_ADC_PVDD_READBACK_LSB, 0x00}, 11462306a36Sopenharmony_ci {MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0x00}, 11562306a36Sopenharmony_ci {MAX98396_R20B9_ADC_VBAT_READBACK_LSB, 0x00}, 11662306a36Sopenharmony_ci {MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0x00}, 11762306a36Sopenharmony_ci {MAX98396_R20BB_ADC_TEMP_READBACK_LSB, 0x00}, 11862306a36Sopenharmony_ci {MAX98396_R20BC_ADC_LO_PVDD_READBACK_MSB, 0x00}, 11962306a36Sopenharmony_ci {MAX98396_R20BD_ADC_LO_PVDD_READBACK_LSB, 0x00}, 12062306a36Sopenharmony_ci {MAX98396_R20BE_ADC_LO_VBAT_READBACK_MSB, 0x00}, 12162306a36Sopenharmony_ci {MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00}, 12262306a36Sopenharmony_ci {MAX98396_R20C7_ADC_CFG, 0x00}, 12362306a36Sopenharmony_ci {MAX98396_R20D0_DHT_CFG1, 0x00}, 12462306a36Sopenharmony_ci {MAX98396_R20D1_LIMITER_CFG1, 0x08}, 12562306a36Sopenharmony_ci {MAX98396_R20D2_LIMITER_CFG2, 0x00}, 12662306a36Sopenharmony_ci {MAX98396_R20D3_DHT_CFG2, 0x14}, 12762306a36Sopenharmony_ci {MAX98396_R20D4_DHT_CFG3, 0x02}, 12862306a36Sopenharmony_ci {MAX98396_R20D5_DHT_CFG4, 0x04}, 12962306a36Sopenharmony_ci {MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07}, 13062306a36Sopenharmony_ci {MAX98396_R20DF_DHT_EN, 0x00}, 13162306a36Sopenharmony_ci {MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04}, 13262306a36Sopenharmony_ci {MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00}, 13362306a36Sopenharmony_ci {MAX98396_R20E5_BPE_STATE, 0x00}, 13462306a36Sopenharmony_ci {MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00}, 13562306a36Sopenharmony_ci {MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00}, 13662306a36Sopenharmony_ci {MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00}, 13762306a36Sopenharmony_ci {MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00}, 13862306a36Sopenharmony_ci {MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00}, 13962306a36Sopenharmony_ci {MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00}, 14062306a36Sopenharmony_ci {MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00}, 14162306a36Sopenharmony_ci {MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00}, 14262306a36Sopenharmony_ci {MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00}, 14362306a36Sopenharmony_ci {MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00}, 14462306a36Sopenharmony_ci {MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00}, 14562306a36Sopenharmony_ci {MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00}, 14662306a36Sopenharmony_ci {MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00}, 14762306a36Sopenharmony_ci {MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00}, 14862306a36Sopenharmony_ci {MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00}, 14962306a36Sopenharmony_ci {MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00}, 15062306a36Sopenharmony_ci {MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00}, 15162306a36Sopenharmony_ci {MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00}, 15262306a36Sopenharmony_ci {MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00}, 15362306a36Sopenharmony_ci {MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00}, 15462306a36Sopenharmony_ci {MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00}, 15562306a36Sopenharmony_ci {MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00}, 15662306a36Sopenharmony_ci {MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00}, 15762306a36Sopenharmony_ci {MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00}, 15862306a36Sopenharmony_ci {MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00}, 15962306a36Sopenharmony_ci {MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00}, 16062306a36Sopenharmony_ci {MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00}, 16162306a36Sopenharmony_ci {MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00}, 16262306a36Sopenharmony_ci {MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00}, 16362306a36Sopenharmony_ci {MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00}, 16462306a36Sopenharmony_ci {MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00}, 16562306a36Sopenharmony_ci {MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00}, 16662306a36Sopenharmony_ci {MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00}, 16762306a36Sopenharmony_ci {MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00}, 16862306a36Sopenharmony_ci {MAX98396_R2108_BPE_SUPPLY_SRC, 0x00}, 16962306a36Sopenharmony_ci {MAX98396_R2109_BPE_LOW_STATE, 0x00}, 17062306a36Sopenharmony_ci {MAX98396_R210A_BPE_LOW_GAIN, 0x00}, 17162306a36Sopenharmony_ci {MAX98396_R210B_BPE_LOW_LIMITER, 0x00}, 17262306a36Sopenharmony_ci {MAX98396_R210D_BPE_EN, 0x00}, 17362306a36Sopenharmony_ci {MAX98396_R210E_AUTO_RESTART, 0x00}, 17462306a36Sopenharmony_ci {MAX98396_R210F_GLOBAL_EN, 0x00}, 17562306a36Sopenharmony_ci {MAX98396_R21FF_REVISION_ID, 0x00}, 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic struct reg_default max98397_reg[] = { 17962306a36Sopenharmony_ci {MAX98396_R2000_SW_RESET, 0x00}, 18062306a36Sopenharmony_ci {MAX98396_R2001_INT_RAW1, 0x00}, 18162306a36Sopenharmony_ci {MAX98396_R2002_INT_RAW2, 0x00}, 18262306a36Sopenharmony_ci {MAX98396_R2003_INT_RAW3, 0x00}, 18362306a36Sopenharmony_ci {MAX98396_R2004_INT_RAW4, 0x00}, 18462306a36Sopenharmony_ci {MAX98396_R2006_INT_STATE1, 0x00}, 18562306a36Sopenharmony_ci {MAX98396_R2007_INT_STATE2, 0x00}, 18662306a36Sopenharmony_ci {MAX98396_R2008_INT_STATE3, 0x00}, 18762306a36Sopenharmony_ci {MAX98396_R2009_INT_STATE4, 0x00}, 18862306a36Sopenharmony_ci {MAX98396_R200B_INT_FLAG1, 0x00}, 18962306a36Sopenharmony_ci {MAX98396_R200C_INT_FLAG2, 0x00}, 19062306a36Sopenharmony_ci {MAX98396_R200D_INT_FLAG3, 0x00}, 19162306a36Sopenharmony_ci {MAX98396_R200E_INT_FLAG4, 0x00}, 19262306a36Sopenharmony_ci {MAX98396_R2010_INT_EN1, 0x02}, 19362306a36Sopenharmony_ci {MAX98396_R2011_INT_EN2, 0x00}, 19462306a36Sopenharmony_ci {MAX98396_R2012_INT_EN3, 0x00}, 19562306a36Sopenharmony_ci {MAX98396_R2013_INT_EN4, 0x00}, 19662306a36Sopenharmony_ci {MAX98396_R2015_INT_FLAG_CLR1, 0x00}, 19762306a36Sopenharmony_ci {MAX98396_R2016_INT_FLAG_CLR2, 0x00}, 19862306a36Sopenharmony_ci {MAX98396_R2017_INT_FLAG_CLR3, 0x00}, 19962306a36Sopenharmony_ci {MAX98396_R2018_INT_FLAG_CLR4, 0x00}, 20062306a36Sopenharmony_ci {MAX98396_R201F_IRQ_CTRL, 0x00}, 20162306a36Sopenharmony_ci {MAX98396_R2020_THERM_WARN_THRESH, 0x46}, 20262306a36Sopenharmony_ci {MAX98396_R2021_THERM_WARN_THRESH2, 0x46}, 20362306a36Sopenharmony_ci {MAX98396_R2022_THERM_SHDN_THRESH, 0x64}, 20462306a36Sopenharmony_ci {MAX98396_R2023_THERM_HYSTERESIS, 0x02}, 20562306a36Sopenharmony_ci {MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5}, 20662306a36Sopenharmony_ci {MAX98396_R2027_THERM_FOLDBACK_EN, 0x01}, 20762306a36Sopenharmony_ci {MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32}, 20862306a36Sopenharmony_ci {MAX98396_R2033_NOISEGATE_MODE_EN, 0x00}, 20962306a36Sopenharmony_ci {MAX98396_R2038_CLK_MON_CTRL, 0x00}, 21062306a36Sopenharmony_ci {MAX98396_R2039_DATA_MON_CTRL, 0x00}, 21162306a36Sopenharmony_ci {MAX98397_R203A_SPK_MON_THRESH, 0x03}, 21262306a36Sopenharmony_ci {MAX98396_R203F_ENABLE_CTRLS, 0x0F}, 21362306a36Sopenharmony_ci {MAX98396_R2040_PIN_CFG, 0x55}, 21462306a36Sopenharmony_ci {MAX98396_R2041_PCM_MODE_CFG, 0xC0}, 21562306a36Sopenharmony_ci {MAX98396_R2042_PCM_CLK_SETUP, 0x04}, 21662306a36Sopenharmony_ci {MAX98396_R2043_PCM_SR_SETUP, 0x88}, 21762306a36Sopenharmony_ci {MAX98396_R2044_PCM_TX_CTRL_1, 0x00}, 21862306a36Sopenharmony_ci {MAX98396_R2045_PCM_TX_CTRL_2, 0x00}, 21962306a36Sopenharmony_ci {MAX98396_R2046_PCM_TX_CTRL_3, 0x00}, 22062306a36Sopenharmony_ci {MAX98396_R2047_PCM_TX_CTRL_4, 0x00}, 22162306a36Sopenharmony_ci {MAX98396_R2048_PCM_TX_CTRL_5, 0x00}, 22262306a36Sopenharmony_ci {MAX98396_R2049_PCM_TX_CTRL_6, 0x00}, 22362306a36Sopenharmony_ci {MAX98396_R204A_PCM_TX_CTRL_7, 0x00}, 22462306a36Sopenharmony_ci {MAX98396_R204B_PCM_TX_CTRL_8, 0x00}, 22562306a36Sopenharmony_ci {MAX98397_R204C_PCM_TX_CTRL_9, 0x00}, 22662306a36Sopenharmony_ci {MAX98397_R204D_PCM_TX_HIZ_CTRL_1, 0xFF}, 22762306a36Sopenharmony_ci {MAX98397_R204E_PCM_TX_HIZ_CTRL_2, 0xFF}, 22862306a36Sopenharmony_ci {MAX98397_R204F_PCM_TX_HIZ_CTRL_3, 0xFF}, 22962306a36Sopenharmony_ci {MAX98397_R2050_PCM_TX_HIZ_CTRL_4, 0xFF}, 23062306a36Sopenharmony_ci {MAX98397_R2051_PCM_TX_HIZ_CTRL_5, 0xFF}, 23162306a36Sopenharmony_ci {MAX98397_R2052_PCM_TX_HIZ_CTRL_6, 0xFF}, 23262306a36Sopenharmony_ci {MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 0xFF}, 23362306a36Sopenharmony_ci {MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 0xFF}, 23462306a36Sopenharmony_ci {MAX98397_R2056_PCM_RX_SRC1, 0x00}, 23562306a36Sopenharmony_ci {MAX98397_R2057_PCM_RX_SRC2, 0x00}, 23662306a36Sopenharmony_ci {MAX98396_R2058_PCM_BYPASS_SRC, 0x00}, 23762306a36Sopenharmony_ci {MAX98396_R205D_PCM_TX_SRC_EN, 0x00}, 23862306a36Sopenharmony_ci {MAX98396_R205E_PCM_RX_EN, 0x00}, 23962306a36Sopenharmony_ci {MAX98396_R205F_PCM_TX_EN, 0x00}, 24062306a36Sopenharmony_ci {MAX98397_R2060_PCM_TX_SUPPLY_SEL, 0x00}, 24162306a36Sopenharmony_ci {MAX98396_R2070_ICC_RX_EN_A, 0x00}, 24262306a36Sopenharmony_ci {MAX98396_R2071_ICC_RX_EN_B, 0x00}, 24362306a36Sopenharmony_ci {MAX98396_R2072_ICC_TX_CTRL, 0x00}, 24462306a36Sopenharmony_ci {MAX98396_R207F_ICC_EN, 0x00}, 24562306a36Sopenharmony_ci {MAX98396_R2083_TONE_GEN_DC_CFG, 0x04}, 24662306a36Sopenharmony_ci {MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00}, 24762306a36Sopenharmony_ci {MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00}, 24862306a36Sopenharmony_ci {MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00}, 24962306a36Sopenharmony_ci {MAX98396_R208F_TONE_GEN_EN, 0x00}, 25062306a36Sopenharmony_ci {MAX98396_R2090_AMP_VOL_CTRL, 0x00}, 25162306a36Sopenharmony_ci {MAX98396_R2091_AMP_PATH_GAIN, 0x12}, 25262306a36Sopenharmony_ci {MAX98396_R2092_AMP_DSP_CFG, 0x22}, 25362306a36Sopenharmony_ci {MAX98396_R2093_SSM_CFG, 0x08}, 25462306a36Sopenharmony_ci {MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12}, 25562306a36Sopenharmony_ci {MAX98396_R2095_SPK_CLS_DG_HDR, 0x17}, 25662306a36Sopenharmony_ci {MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17}, 25762306a36Sopenharmony_ci {MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00}, 25862306a36Sopenharmony_ci {MAX98396_R2098_SPK_CLS_DG_MODE, 0x00}, 25962306a36Sopenharmony_ci {MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03}, 26062306a36Sopenharmony_ci {MAX98396_R209A_SPK_EDGE_CTRL, 0x00}, 26162306a36Sopenharmony_ci {MAX98397_R209B_SPK_PATH_WB_ONLY, 0x00}, 26262306a36Sopenharmony_ci {MAX98396_R209C_SPK_EDGE_CTRL1, 0x03}, 26362306a36Sopenharmony_ci {MAX98396_R209D_SPK_EDGE_CTRL2, 0xFC}, 26462306a36Sopenharmony_ci {MAX98396_R209E_AMP_CLIP_GAIN, 0x00}, 26562306a36Sopenharmony_ci {MAX98396_R209F_BYPASS_PATH_CFG, 0x00}, 26662306a36Sopenharmony_ci {MAX98396_R20AF_AMP_EN, 0x00}, 26762306a36Sopenharmony_ci {MAX98396_R20B0_ADC_SR, 0x30}, 26862306a36Sopenharmony_ci {MAX98396_R20B1_ADC_PVDD_CFG, 0x00}, 26962306a36Sopenharmony_ci {MAX98396_R20B2_ADC_VBAT_CFG, 0x00}, 27062306a36Sopenharmony_ci {MAX98396_R20B3_ADC_THERMAL_CFG, 0x00}, 27162306a36Sopenharmony_ci {MAX98397_R20B4_ADC_VDDH_CFG, 0x00}, 27262306a36Sopenharmony_ci {MAX98397_R20B5_ADC_READBACK_CTRL1, 0x00}, 27362306a36Sopenharmony_ci {MAX98397_R20B6_ADC_READBACK_CTRL2, 0x00}, 27462306a36Sopenharmony_ci {MAX98397_R20B7_ADC_PVDD_READBACK_MSB, 0x00}, 27562306a36Sopenharmony_ci {MAX98397_R20B8_ADC_PVDD_READBACK_LSB, 0x00}, 27662306a36Sopenharmony_ci {MAX98397_R20B9_ADC_VBAT_READBACK_MSB, 0x00}, 27762306a36Sopenharmony_ci {MAX98397_R20BA_ADC_VBAT_READBACK_LSB, 0x00}, 27862306a36Sopenharmony_ci {MAX98397_R20BB_ADC_TEMP_READBACK_MSB, 0x00}, 27962306a36Sopenharmony_ci {MAX98397_R20BC_ADC_TEMP_READBACK_LSB, 0x00}, 28062306a36Sopenharmony_ci {MAX98397_R20BD_ADC_VDDH__READBACK_MSB, 0x00}, 28162306a36Sopenharmony_ci {MAX98397_R20BE_ADC_VDDH_READBACK_LSB, 0x00}, 28262306a36Sopenharmony_ci {MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00}, 28362306a36Sopenharmony_ci {MAX98397_R20C3_ADC_LO_VDDH_READBACK_MSB, 0x00}, 28462306a36Sopenharmony_ci {MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB, 0x00}, 28562306a36Sopenharmony_ci {MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE, 0x04}, 28662306a36Sopenharmony_ci {MAX98396_R20C7_ADC_CFG, 0x00}, 28762306a36Sopenharmony_ci {MAX98396_R20D0_DHT_CFG1, 0x00}, 28862306a36Sopenharmony_ci {MAX98396_R20D1_LIMITER_CFG1, 0x08}, 28962306a36Sopenharmony_ci {MAX98396_R20D2_LIMITER_CFG2, 0x00}, 29062306a36Sopenharmony_ci {MAX98396_R20D3_DHT_CFG2, 0x14}, 29162306a36Sopenharmony_ci {MAX98396_R20D4_DHT_CFG3, 0x02}, 29262306a36Sopenharmony_ci {MAX98396_R20D5_DHT_CFG4, 0x04}, 29362306a36Sopenharmony_ci {MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07}, 29462306a36Sopenharmony_ci {MAX98396_R20DF_DHT_EN, 0x00}, 29562306a36Sopenharmony_ci {MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04}, 29662306a36Sopenharmony_ci {MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00}, 29762306a36Sopenharmony_ci {MAX98396_R20E5_BPE_STATE, 0x00}, 29862306a36Sopenharmony_ci {MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00}, 29962306a36Sopenharmony_ci {MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00}, 30062306a36Sopenharmony_ci {MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00}, 30162306a36Sopenharmony_ci {MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00}, 30262306a36Sopenharmony_ci {MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00}, 30362306a36Sopenharmony_ci {MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00}, 30462306a36Sopenharmony_ci {MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00}, 30562306a36Sopenharmony_ci {MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00}, 30662306a36Sopenharmony_ci {MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00}, 30762306a36Sopenharmony_ci {MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00}, 30862306a36Sopenharmony_ci {MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00}, 30962306a36Sopenharmony_ci {MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00}, 31062306a36Sopenharmony_ci {MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00}, 31162306a36Sopenharmony_ci {MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00}, 31262306a36Sopenharmony_ci {MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00}, 31362306a36Sopenharmony_ci {MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00}, 31462306a36Sopenharmony_ci {MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00}, 31562306a36Sopenharmony_ci {MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00}, 31662306a36Sopenharmony_ci {MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00}, 31762306a36Sopenharmony_ci {MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00}, 31862306a36Sopenharmony_ci {MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00}, 31962306a36Sopenharmony_ci {MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00}, 32062306a36Sopenharmony_ci {MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00}, 32162306a36Sopenharmony_ci {MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00}, 32262306a36Sopenharmony_ci {MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00}, 32362306a36Sopenharmony_ci {MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00}, 32462306a36Sopenharmony_ci {MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00}, 32562306a36Sopenharmony_ci {MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00}, 32662306a36Sopenharmony_ci {MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00}, 32762306a36Sopenharmony_ci {MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00}, 32862306a36Sopenharmony_ci {MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00}, 32962306a36Sopenharmony_ci {MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00}, 33062306a36Sopenharmony_ci {MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00}, 33162306a36Sopenharmony_ci {MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00}, 33262306a36Sopenharmony_ci {MAX98396_R2108_BPE_SUPPLY_SRC, 0x00}, 33362306a36Sopenharmony_ci {MAX98396_R2109_BPE_LOW_STATE, 0x00}, 33462306a36Sopenharmony_ci {MAX98396_R210A_BPE_LOW_GAIN, 0x00}, 33562306a36Sopenharmony_ci {MAX98396_R210B_BPE_LOW_LIMITER, 0x00}, 33662306a36Sopenharmony_ci {MAX98396_R210D_BPE_EN, 0x00}, 33762306a36Sopenharmony_ci {MAX98396_R210E_AUTO_RESTART, 0x00}, 33862306a36Sopenharmony_ci {MAX98396_R210F_GLOBAL_EN, 0x00}, 33962306a36Sopenharmony_ci {MAX98397_R22FF_REVISION_ID, 0x00}, 34062306a36Sopenharmony_ci}; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic void max98396_global_enable_onoff(struct regmap *regmap, bool onoff) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci regmap_write(regmap, MAX98396_R210F_GLOBAL_EN, onoff ? 1 : 0); 34562306a36Sopenharmony_ci usleep_range(11000, 12000); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int max98396_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 35162306a36Sopenharmony_ci struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component); 35262306a36Sopenharmony_ci unsigned int format_mask, format = 0; 35362306a36Sopenharmony_ci unsigned int bclk_pol = 0; 35462306a36Sopenharmony_ci int ret, status; 35562306a36Sopenharmony_ci int reg; 35662306a36Sopenharmony_ci bool update = false; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci format_mask = MAX98396_PCM_MODE_CFG_FORMAT_MASK | 35962306a36Sopenharmony_ci MAX98396_PCM_MODE_CFG_LRCLKEDGE; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 36462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 36762306a36Sopenharmony_ci format = MAX98396_PCM_MODE_CFG_LRCLKEDGE; 36862306a36Sopenharmony_ci break; 36962306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 37062306a36Sopenharmony_ci bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE; 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 37362306a36Sopenharmony_ci bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE; 37462306a36Sopenharmony_ci format = MAX98396_PCM_MODE_CFG_LRCLKEDGE; 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci default: 37862306a36Sopenharmony_ci dev_err(component->dev, "DAI invert mode %d unsupported\n", 37962306a36Sopenharmony_ci fmt & SND_SOC_DAIFMT_INV_MASK); 38062306a36Sopenharmony_ci return -EINVAL; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* interface format */ 38462306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 38562306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 38662306a36Sopenharmony_ci format |= MAX98396_PCM_FORMAT_I2S; 38762306a36Sopenharmony_ci break; 38862306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 38962306a36Sopenharmony_ci format |= MAX98396_PCM_FORMAT_LJ; 39062306a36Sopenharmony_ci break; 39162306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 39262306a36Sopenharmony_ci format |= MAX98396_PCM_FORMAT_TDM_MODE1; 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 39562306a36Sopenharmony_ci format |= MAX98396_PCM_FORMAT_TDM_MODE0; 39662306a36Sopenharmony_ci break; 39762306a36Sopenharmony_ci default: 39862306a36Sopenharmony_ci dev_err(component->dev, "DAI format %d unsupported\n", 39962306a36Sopenharmony_ci fmt & SND_SOC_DAIFMT_FORMAT_MASK); 40062306a36Sopenharmony_ci return -EINVAL; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status); 40462306a36Sopenharmony_ci if (ret < 0) 40562306a36Sopenharmony_ci return -EINVAL; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (status) { 40862306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, ®); 40962306a36Sopenharmony_ci if (ret < 0) 41062306a36Sopenharmony_ci return -EINVAL; 41162306a36Sopenharmony_ci if (format != (reg & format_mask)) { 41262306a36Sopenharmony_ci update = true; 41362306a36Sopenharmony_ci } else { 41462306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, 41562306a36Sopenharmony_ci MAX98396_R2042_PCM_CLK_SETUP, ®); 41662306a36Sopenharmony_ci if (ret < 0) 41762306a36Sopenharmony_ci return -EINVAL; 41862306a36Sopenharmony_ci if (bclk_pol != (reg & MAX98396_PCM_MODE_CFG_BCLKEDGE)) 41962306a36Sopenharmony_ci update = true; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci /* GLOBAL_EN OFF prior to pcm mode, clock configuration change */ 42262306a36Sopenharmony_ci if (update) 42362306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, false); 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 42762306a36Sopenharmony_ci MAX98396_R2041_PCM_MODE_CFG, 42862306a36Sopenharmony_ci format_mask, format); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 43162306a36Sopenharmony_ci MAX98396_R2042_PCM_CLK_SETUP, 43262306a36Sopenharmony_ci MAX98396_PCM_MODE_CFG_BCLKEDGE, 43362306a36Sopenharmony_ci bclk_pol); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (status && update) 43662306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, true); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci return 0; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci#define MAX98396_BSEL_32 0x2 44262306a36Sopenharmony_ci#define MAX98396_BSEL_48 0x3 44362306a36Sopenharmony_ci#define MAX98396_BSEL_64 0x4 44462306a36Sopenharmony_ci#define MAX98396_BSEL_96 0x5 44562306a36Sopenharmony_ci#define MAX98396_BSEL_128 0x6 44662306a36Sopenharmony_ci#define MAX98396_BSEL_192 0x7 44762306a36Sopenharmony_ci#define MAX98396_BSEL_256 0x8 44862306a36Sopenharmony_ci#define MAX98396_BSEL_384 0x9 44962306a36Sopenharmony_ci#define MAX98396_BSEL_512 0xa 45062306a36Sopenharmony_ci#define MAX98396_BSEL_320 0xb 45162306a36Sopenharmony_ci#define MAX98396_BSEL_250 0xc 45262306a36Sopenharmony_ci#define MAX98396_BSEL_125 0xd 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci/* Refer to table 5 in the datasheet */ 45562306a36Sopenharmony_cistatic const struct max98396_pcm_config { 45662306a36Sopenharmony_ci int in, out, width, bsel, max_sr; 45762306a36Sopenharmony_ci} max98396_pcm_configs[] = { 45862306a36Sopenharmony_ci { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 192000 }, 45962306a36Sopenharmony_ci { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 192000 }, 46062306a36Sopenharmony_ci { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 192000 }, 46162306a36Sopenharmony_ci { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, 46262306a36Sopenharmony_ci { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 192000 }, 46362306a36Sopenharmony_ci { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 192000 }, 46462306a36Sopenharmony_ci { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 192000 }, 46562306a36Sopenharmony_ci { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, 46662306a36Sopenharmony_ci { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, 46762306a36Sopenharmony_ci { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 96000 }, 46862306a36Sopenharmony_ci { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 96000 }, 46962306a36Sopenharmony_ci { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 96000 }, 47062306a36Sopenharmony_ci { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, 47162306a36Sopenharmony_ci { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 96000 }, 47262306a36Sopenharmony_ci { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 96000 }, 47362306a36Sopenharmony_ci { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 96000 }, 47462306a36Sopenharmony_ci { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, 47562306a36Sopenharmony_ci { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, 47662306a36Sopenharmony_ci { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, 47762306a36Sopenharmony_ci { .in = 8, .out = 16, .width = 16, .bsel = MAX98396_BSEL_128, .max_sr = 96000 }, 47862306a36Sopenharmony_ci { .in = 8, .out = 24, .width = 24, .bsel = MAX98396_BSEL_192, .max_sr = 96000 }, 47962306a36Sopenharmony_ci { .in = 8, .out = 32, .width = 32, .bsel = MAX98396_BSEL_256, .max_sr = 96000 }, 48062306a36Sopenharmony_ci { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, 48162306a36Sopenharmony_ci { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, 48262306a36Sopenharmony_ci { .in = 16, .out = 32, .width = 16, .bsel = MAX98396_BSEL_256, .max_sr = 96000 }, 48362306a36Sopenharmony_ci { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, 48462306a36Sopenharmony_ci { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, 48562306a36Sopenharmony_ci { .in = 10, .out = 40, .width = 32, .bsel = MAX98396_BSEL_320, .max_sr = 48000 }, 48662306a36Sopenharmony_ci { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, 48762306a36Sopenharmony_ci { .in = 16, .out = 48, .width = 24, .bsel = MAX98396_BSEL_384, .max_sr = 48000 }, 48862306a36Sopenharmony_ci { .in = 16, .out = 64, .width = 32, .bsel = MAX98396_BSEL_512, .max_sr = 48000 }, 48962306a36Sopenharmony_ci}; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic int max98396_pcm_config_index(int in_slots, int out_slots, int width) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci int i; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max98396_pcm_configs); i++) { 49662306a36Sopenharmony_ci const struct max98396_pcm_config *c = &max98396_pcm_configs[i]; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (in_slots == c->in && out_slots <= c->out && width == c->width) 49962306a36Sopenharmony_ci return i; 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci return -1; 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic int max98396_dai_hw_params(struct snd_pcm_substream *substream, 50662306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 50762306a36Sopenharmony_ci struct snd_soc_dai *dai) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 51062306a36Sopenharmony_ci struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component); 51162306a36Sopenharmony_ci unsigned int sampling_rate = 0; 51262306a36Sopenharmony_ci unsigned int chan_sz = 0; 51362306a36Sopenharmony_ci int ret, reg, status, bsel = 0; 51462306a36Sopenharmony_ci bool update = false; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* pcm mode configuration */ 51762306a36Sopenharmony_ci switch (snd_pcm_format_width(params_format(params))) { 51862306a36Sopenharmony_ci case 16: 51962306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16; 52062306a36Sopenharmony_ci break; 52162306a36Sopenharmony_ci case 24: 52262306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24; 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case 32: 52562306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32; 52662306a36Sopenharmony_ci break; 52762306a36Sopenharmony_ci default: 52862306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 52962306a36Sopenharmony_ci params_format(params)); 53062306a36Sopenharmony_ci goto err; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci dev_dbg(component->dev, "format supported %d", 53462306a36Sopenharmony_ci params_format(params)); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci /* sampling rate configuration */ 53762306a36Sopenharmony_ci switch (params_rate(params)) { 53862306a36Sopenharmony_ci case 8000: 53962306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_8000; 54062306a36Sopenharmony_ci break; 54162306a36Sopenharmony_ci case 11025: 54262306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_11025; 54362306a36Sopenharmony_ci break; 54462306a36Sopenharmony_ci case 12000: 54562306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_12000; 54662306a36Sopenharmony_ci break; 54762306a36Sopenharmony_ci case 16000: 54862306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_16000; 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci case 22050: 55162306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_22050; 55262306a36Sopenharmony_ci break; 55362306a36Sopenharmony_ci case 24000: 55462306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_24000; 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci case 32000: 55762306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_32000; 55862306a36Sopenharmony_ci break; 55962306a36Sopenharmony_ci case 44100: 56062306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_44100; 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci case 48000: 56362306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_48000; 56462306a36Sopenharmony_ci break; 56562306a36Sopenharmony_ci case 88200: 56662306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_88200; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case 96000: 56962306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_96000; 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci case 192000: 57262306a36Sopenharmony_ci sampling_rate = MAX98396_PCM_SR_192000; 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci default: 57562306a36Sopenharmony_ci dev_err(component->dev, "rate %d not supported\n", 57662306a36Sopenharmony_ci params_rate(params)); 57762306a36Sopenharmony_ci goto err; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if (max98396->tdm_mode) { 58162306a36Sopenharmony_ci if (params_rate(params) > max98396->tdm_max_samplerate) { 58262306a36Sopenharmony_ci dev_err(component->dev, "TDM sample rate %d too high", 58362306a36Sopenharmony_ci params_rate(params)); 58462306a36Sopenharmony_ci goto err; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci } else { 58762306a36Sopenharmony_ci /* BCLK configuration */ 58862306a36Sopenharmony_ci ret = max98396_pcm_config_index(params_channels(params), 58962306a36Sopenharmony_ci params_channels(params), 59062306a36Sopenharmony_ci snd_pcm_format_width(params_format(params))); 59162306a36Sopenharmony_ci if (ret < 0) { 59262306a36Sopenharmony_ci dev_err(component->dev, 59362306a36Sopenharmony_ci "no PCM config for %d channels, format %d\n", 59462306a36Sopenharmony_ci params_channels(params), params_format(params)); 59562306a36Sopenharmony_ci goto err; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci bsel = max98396_pcm_configs[ret].bsel; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (params_rate(params) > max98396_pcm_configs[ret].max_sr) { 60162306a36Sopenharmony_ci dev_err(component->dev, "sample rate %d too high", 60262306a36Sopenharmony_ci params_rate(params)); 60362306a36Sopenharmony_ci goto err; 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status); 60862306a36Sopenharmony_ci if (ret < 0) 60962306a36Sopenharmony_ci goto err; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci if (status) { 61262306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, ®); 61362306a36Sopenharmony_ci if (ret < 0) 61462306a36Sopenharmony_ci goto err; 61562306a36Sopenharmony_ci if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK)) { 61662306a36Sopenharmony_ci update = true; 61762306a36Sopenharmony_ci } else { 61862306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R2043_PCM_SR_SETUP, ®); 61962306a36Sopenharmony_ci if (ret < 0) 62062306a36Sopenharmony_ci goto err; 62162306a36Sopenharmony_ci if (sampling_rate != (reg & MAX98396_PCM_SR_MASK)) 62262306a36Sopenharmony_ci update = true; 62362306a36Sopenharmony_ci } 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* GLOBAL_EN OFF prior to channel size and sampling rate change */ 62662306a36Sopenharmony_ci if (update) 62762306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, false); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci /* set channel size */ 63162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, 63262306a36Sopenharmony_ci MAX98396_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* set DAI_SR to correct LRCLK frequency */ 63562306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, MAX98396_R2043_PCM_SR_SETUP, 63662306a36Sopenharmony_ci MAX98396_PCM_SR_MASK, sampling_rate); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci /* set sampling rate of IV */ 63962306a36Sopenharmony_ci if (max98396->interleave_mode && 64062306a36Sopenharmony_ci sampling_rate > MAX98396_PCM_SR_16000) 64162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 64262306a36Sopenharmony_ci MAX98396_R2043_PCM_SR_SETUP, 64362306a36Sopenharmony_ci MAX98396_IVADC_SR_MASK, 64462306a36Sopenharmony_ci (sampling_rate - 3) 64562306a36Sopenharmony_ci << MAX98396_IVADC_SR_SHIFT); 64662306a36Sopenharmony_ci else 64762306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 64862306a36Sopenharmony_ci MAX98396_R2043_PCM_SR_SETUP, 64962306a36Sopenharmony_ci MAX98396_IVADC_SR_MASK, 65062306a36Sopenharmony_ci sampling_rate << MAX98396_IVADC_SR_SHIFT); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (bsel) 65362306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 65462306a36Sopenharmony_ci MAX98396_R2042_PCM_CLK_SETUP, 65562306a36Sopenharmony_ci MAX98396_PCM_CLK_SETUP_BSEL_MASK, 65662306a36Sopenharmony_ci bsel); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (status && update) 65962306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, true); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return 0; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cierr: 66462306a36Sopenharmony_ci return -EINVAL; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic int max98396_dai_tdm_slot(struct snd_soc_dai *dai, 66862306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 66962306a36Sopenharmony_ci int slots, int slot_width) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 67262306a36Sopenharmony_ci struct max98396_priv *max98396 = 67362306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 67462306a36Sopenharmony_ci int bsel; 67562306a36Sopenharmony_ci unsigned int chan_sz = 0; 67662306a36Sopenharmony_ci int ret, status; 67762306a36Sopenharmony_ci int reg; 67862306a36Sopenharmony_ci bool update = false; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (!tx_mask && !rx_mask && !slots && !slot_width) 68162306a36Sopenharmony_ci max98396->tdm_mode = false; 68262306a36Sopenharmony_ci else 68362306a36Sopenharmony_ci max98396->tdm_mode = true; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci /* BCLK configuration */ 68662306a36Sopenharmony_ci ret = max98396_pcm_config_index(slots, slots, slot_width); 68762306a36Sopenharmony_ci if (ret < 0) { 68862306a36Sopenharmony_ci dev_err(component->dev, "no TDM config for %d slots %d bits\n", 68962306a36Sopenharmony_ci slots, slot_width); 69062306a36Sopenharmony_ci return -EINVAL; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci bsel = max98396_pcm_configs[ret].bsel; 69462306a36Sopenharmony_ci max98396->tdm_max_samplerate = max98396_pcm_configs[ret].max_sr; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci /* Channel size configuration */ 69762306a36Sopenharmony_ci switch (slot_width) { 69862306a36Sopenharmony_ci case 16: 69962306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16; 70062306a36Sopenharmony_ci break; 70162306a36Sopenharmony_ci case 24: 70262306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24; 70362306a36Sopenharmony_ci break; 70462306a36Sopenharmony_ci case 32: 70562306a36Sopenharmony_ci chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32; 70662306a36Sopenharmony_ci break; 70762306a36Sopenharmony_ci default: 70862306a36Sopenharmony_ci dev_err(component->dev, "slot width %d unsupported\n", 70962306a36Sopenharmony_ci slot_width); 71062306a36Sopenharmony_ci return -EINVAL; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status); 71462306a36Sopenharmony_ci if (ret < 0) 71562306a36Sopenharmony_ci return -EINVAL; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (status) { 71862306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R2042_PCM_CLK_SETUP, ®); 71962306a36Sopenharmony_ci if (ret < 0) 72062306a36Sopenharmony_ci return -EINVAL; 72162306a36Sopenharmony_ci if (bsel != (reg & MAX98396_PCM_CLK_SETUP_BSEL_MASK)) { 72262306a36Sopenharmony_ci update = true; 72362306a36Sopenharmony_ci } else { 72462306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, ®); 72562306a36Sopenharmony_ci if (ret < 0) 72662306a36Sopenharmony_ci return -EINVAL; 72762306a36Sopenharmony_ci if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK)) 72862306a36Sopenharmony_ci update = true; 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /* GLOBAL_EN OFF prior to channel size and BCLK per LRCLK change */ 73262306a36Sopenharmony_ci if (update) 73362306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, false); 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 73762306a36Sopenharmony_ci MAX98396_R2042_PCM_CLK_SETUP, 73862306a36Sopenharmony_ci MAX98396_PCM_CLK_SETUP_BSEL_MASK, 73962306a36Sopenharmony_ci bsel); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 74262306a36Sopenharmony_ci MAX98396_R2041_PCM_MODE_CFG, 74362306a36Sopenharmony_ci MAX98396_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci /* Rx slot configuration */ 74662306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) { 74762306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 74862306a36Sopenharmony_ci MAX98396_R2056_PCM_RX_SRC2, 74962306a36Sopenharmony_ci MAX98396_PCM_DMIX_CH0_SRC_MASK, 75062306a36Sopenharmony_ci rx_mask); 75162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 75262306a36Sopenharmony_ci MAX98396_R2056_PCM_RX_SRC2, 75362306a36Sopenharmony_ci MAX98396_PCM_DMIX_CH1_SRC_MASK, 75462306a36Sopenharmony_ci rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT); 75562306a36Sopenharmony_ci } else { 75662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 75762306a36Sopenharmony_ci MAX98397_R2057_PCM_RX_SRC2, 75862306a36Sopenharmony_ci MAX98396_PCM_DMIX_CH0_SRC_MASK, 75962306a36Sopenharmony_ci rx_mask); 76062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 76162306a36Sopenharmony_ci MAX98397_R2057_PCM_RX_SRC2, 76262306a36Sopenharmony_ci MAX98396_PCM_DMIX_CH1_SRC_MASK, 76362306a36Sopenharmony_ci rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT); 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* Tx slot Hi-Z configuration */ 76762306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) { 76862306a36Sopenharmony_ci regmap_write(max98396->regmap, 76962306a36Sopenharmony_ci MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 77062306a36Sopenharmony_ci ~tx_mask & 0xFF); 77162306a36Sopenharmony_ci regmap_write(max98396->regmap, 77262306a36Sopenharmony_ci MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 77362306a36Sopenharmony_ci (~tx_mask & 0xFF00) >> 8); 77462306a36Sopenharmony_ci } else { 77562306a36Sopenharmony_ci regmap_write(max98396->regmap, 77662306a36Sopenharmony_ci MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 77762306a36Sopenharmony_ci ~tx_mask & 0xFF); 77862306a36Sopenharmony_ci regmap_write(max98396->regmap, 77962306a36Sopenharmony_ci MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 78062306a36Sopenharmony_ci (~tx_mask & 0xFF00) >> 8); 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (status && update) 78462306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, true); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return 0; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci#define MAX98396_RATES SNDRV_PCM_RATE_8000_192000 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci#define MAX98396_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 79262306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98396_dai_ops = { 79562306a36Sopenharmony_ci .set_fmt = max98396_dai_set_fmt, 79662306a36Sopenharmony_ci .hw_params = max98396_dai_hw_params, 79762306a36Sopenharmony_ci .set_tdm_slot = max98396_dai_tdm_slot, 79862306a36Sopenharmony_ci}; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic int max98396_dac_event(struct snd_soc_dapm_widget *w, 80162306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct snd_soc_component *component = 80462306a36Sopenharmony_ci snd_soc_dapm_to_component(w->dapm); 80562306a36Sopenharmony_ci struct max98396_priv *max98396 = 80662306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci switch (event) { 80962306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 81062306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, true); 81162306a36Sopenharmony_ci break; 81262306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 81362306a36Sopenharmony_ci max98396_global_enable_onoff(max98396->regmap, false); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci max98396->tdm_mode = false; 81662306a36Sopenharmony_ci break; 81762306a36Sopenharmony_ci default: 81862306a36Sopenharmony_ci return 0; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci return 0; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic bool max98396_readable_register(struct device *dev, unsigned int reg) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci switch (reg) { 82662306a36Sopenharmony_ci case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4: 82762306a36Sopenharmony_ci case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4: 82862306a36Sopenharmony_ci case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4: 82962306a36Sopenharmony_ci case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4: 83062306a36Sopenharmony_ci case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4: 83162306a36Sopenharmony_ci case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET: 83262306a36Sopenharmony_ci case MAX98396_R2027_THERM_FOLDBACK_EN: 83362306a36Sopenharmony_ci case MAX98396_R2030_NOISEGATE_MODE_CTRL: 83462306a36Sopenharmony_ci case MAX98396_R2033_NOISEGATE_MODE_EN: 83562306a36Sopenharmony_ci case MAX98396_R2038_CLK_MON_CTRL ... MAX98396_R2039_DATA_MON_CTRL: 83662306a36Sopenharmony_ci case MAX98396_R203F_ENABLE_CTRLS ... MAX98396_R2053_PCM_TX_HIZ_CTRL_8: 83762306a36Sopenharmony_ci case MAX98396_R2055_PCM_RX_SRC1 ... MAX98396_R2056_PCM_RX_SRC2: 83862306a36Sopenharmony_ci case MAX98396_R2058_PCM_BYPASS_SRC: 83962306a36Sopenharmony_ci case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98396_R205F_PCM_TX_EN: 84062306a36Sopenharmony_ci case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL: 84162306a36Sopenharmony_ci case MAX98396_R207F_ICC_EN: 84262306a36Sopenharmony_ci case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3: 84362306a36Sopenharmony_ci case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209A_SPK_EDGE_CTRL: 84462306a36Sopenharmony_ci case MAX98396_R209C_SPK_EDGE_CTRL1 ... MAX98396_R20A0_AMP_SUPPLY_CTL: 84562306a36Sopenharmony_ci case MAX98396_R20AF_AMP_EN ... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB: 84662306a36Sopenharmony_ci case MAX98396_R20C7_ADC_CFG: 84762306a36Sopenharmony_ci case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG: 84862306a36Sopenharmony_ci case MAX98396_R20DF_DHT_EN: 84962306a36Sopenharmony_ci case MAX98396_R20E0_IV_SENSE_PATH_CFG: 85062306a36Sopenharmony_ci case MAX98396_R20E4_IV_SENSE_PATH_EN 85162306a36Sopenharmony_ci ... MAX98396_R2106_BPE_THRESH_HYSTERESIS: 85262306a36Sopenharmony_ci case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER: 85362306a36Sopenharmony_ci case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN: 85462306a36Sopenharmony_ci case MAX98396_R21FF_REVISION_ID: 85562306a36Sopenharmony_ci return true; 85662306a36Sopenharmony_ci default: 85762306a36Sopenharmony_ci return false; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci}; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_cistatic bool max98396_volatile_reg(struct device *dev, unsigned int reg) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci switch (reg) { 86462306a36Sopenharmony_ci case MAX98396_R2000_SW_RESET: 86562306a36Sopenharmony_ci case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4: 86662306a36Sopenharmony_ci case MAX98396_R2041_PCM_MODE_CFG: 86762306a36Sopenharmony_ci case MAX98396_R20B6_ADC_PVDD_READBACK_MSB 86862306a36Sopenharmony_ci ... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB: 86962306a36Sopenharmony_ci case MAX98396_R20E5_BPE_STATE: 87062306a36Sopenharmony_ci case MAX98396_R2109_BPE_LOW_STATE 87162306a36Sopenharmony_ci ... MAX98396_R210B_BPE_LOW_LIMITER: 87262306a36Sopenharmony_ci case MAX98396_R210F_GLOBAL_EN: 87362306a36Sopenharmony_ci case MAX98396_R21FF_REVISION_ID: 87462306a36Sopenharmony_ci return true; 87562306a36Sopenharmony_ci default: 87662306a36Sopenharmony_ci return false; 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_cistatic bool max98397_readable_register(struct device *dev, unsigned int reg) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci switch (reg) { 88362306a36Sopenharmony_ci case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4: 88462306a36Sopenharmony_ci case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4: 88562306a36Sopenharmony_ci case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4: 88662306a36Sopenharmony_ci case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4: 88762306a36Sopenharmony_ci case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4: 88862306a36Sopenharmony_ci case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET: 88962306a36Sopenharmony_ci case MAX98396_R2027_THERM_FOLDBACK_EN: 89062306a36Sopenharmony_ci case MAX98396_R2030_NOISEGATE_MODE_CTRL: 89162306a36Sopenharmony_ci case MAX98396_R2033_NOISEGATE_MODE_EN: 89262306a36Sopenharmony_ci case MAX98396_R2038_CLK_MON_CTRL ... MAX98397_R203A_SPK_MON_THRESH: 89362306a36Sopenharmony_ci case MAX98396_R203F_ENABLE_CTRLS ... MAX98397_R2054_PCM_TX_HIZ_CTRL_8: 89462306a36Sopenharmony_ci case MAX98397_R2056_PCM_RX_SRC1... MAX98396_R2058_PCM_BYPASS_SRC: 89562306a36Sopenharmony_ci case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98397_R2060_PCM_TX_SUPPLY_SEL: 89662306a36Sopenharmony_ci case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL: 89762306a36Sopenharmony_ci case MAX98396_R207F_ICC_EN: 89862306a36Sopenharmony_ci case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3: 89962306a36Sopenharmony_ci case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209F_BYPASS_PATH_CFG: 90062306a36Sopenharmony_ci case MAX98396_R20AF_AMP_EN ... MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE: 90162306a36Sopenharmony_ci case MAX98396_R20C7_ADC_CFG: 90262306a36Sopenharmony_ci case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG: 90362306a36Sopenharmony_ci case MAX98396_R20DF_DHT_EN: 90462306a36Sopenharmony_ci case MAX98396_R20E0_IV_SENSE_PATH_CFG: 90562306a36Sopenharmony_ci case MAX98396_R20E4_IV_SENSE_PATH_EN 90662306a36Sopenharmony_ci ... MAX98396_R2106_BPE_THRESH_HYSTERESIS: 90762306a36Sopenharmony_ci case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER: 90862306a36Sopenharmony_ci case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN: 90962306a36Sopenharmony_ci case MAX98397_R22FF_REVISION_ID: 91062306a36Sopenharmony_ci return true; 91162306a36Sopenharmony_ci default: 91262306a36Sopenharmony_ci return false; 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci}; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_cistatic bool max98397_volatile_reg(struct device *dev, unsigned int reg) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci switch (reg) { 91962306a36Sopenharmony_ci case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4: 92062306a36Sopenharmony_ci case MAX98396_R2041_PCM_MODE_CFG: 92162306a36Sopenharmony_ci case MAX98397_R20B7_ADC_PVDD_READBACK_MSB 92262306a36Sopenharmony_ci ... MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB: 92362306a36Sopenharmony_ci case MAX98396_R20E5_BPE_STATE: 92462306a36Sopenharmony_ci case MAX98396_R2109_BPE_LOW_STATE 92562306a36Sopenharmony_ci ... MAX98396_R210B_BPE_LOW_LIMITER: 92662306a36Sopenharmony_ci case MAX98396_R210F_GLOBAL_EN: 92762306a36Sopenharmony_ci case MAX98397_R22FF_REVISION_ID: 92862306a36Sopenharmony_ci return true; 92962306a36Sopenharmony_ci default: 93062306a36Sopenharmony_ci return false; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic const char * const max98396_op_mod_text[] = { 93562306a36Sopenharmony_ci "DG", "PVDD", "VBAT", 93662306a36Sopenharmony_ci}; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_op_mod_enum, 93962306a36Sopenharmony_ci MAX98396_R2098_SPK_CLS_DG_MODE, 94062306a36Sopenharmony_ci 0, max98396_op_mod_text); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(max98396_digital_tlv, -6350, 50, 1); 94362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98396_spk_tlv, 94462306a36Sopenharmony_ci 0, 0x11, TLV_DB_SCALE_ITEM(400, 100, 0), 94562306a36Sopenharmony_ci); 94662306a36Sopenharmony_cistatic DECLARE_TLV_DB_RANGE(max98397_digital_tlv, 94762306a36Sopenharmony_ci 0, 0x4A, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), 94862306a36Sopenharmony_ci 0x4B, 0xFF, TLV_DB_SCALE_ITEM(-9000, 50, 0), 94962306a36Sopenharmony_ci); 95062306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98397_spk_tlv, 95162306a36Sopenharmony_ci 0, 0x15, TLV_DB_SCALE_ITEM(600, 100, 0), 95262306a36Sopenharmony_ci); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_cistatic int max98396_mux_get(struct snd_kcontrol *kcontrol, 95562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 95662306a36Sopenharmony_ci{ 95762306a36Sopenharmony_ci struct snd_soc_component *component = 95862306a36Sopenharmony_ci snd_soc_dapm_kcontrol_component(kcontrol); 95962306a36Sopenharmony_ci struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component); 96062306a36Sopenharmony_ci int reg, val; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 96362306a36Sopenharmony_ci reg = MAX98396_R2055_PCM_RX_SRC1; 96462306a36Sopenharmony_ci else 96562306a36Sopenharmony_ci reg = MAX98397_R2056_PCM_RX_SRC1; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci regmap_read(max98396->regmap, reg, &val); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = val; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci return 0; 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic int max98396_mux_put(struct snd_kcontrol *kcontrol, 97562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci struct snd_soc_component *component = 97862306a36Sopenharmony_ci snd_soc_dapm_kcontrol_component(kcontrol); 97962306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 98062306a36Sopenharmony_ci struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component); 98162306a36Sopenharmony_ci struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 98262306a36Sopenharmony_ci unsigned int *item = ucontrol->value.enumerated.item; 98362306a36Sopenharmony_ci int reg, val; 98462306a36Sopenharmony_ci int change; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci if (item[0] >= e->items) 98762306a36Sopenharmony_ci return -EINVAL; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 99262306a36Sopenharmony_ci reg = MAX98396_R2055_PCM_RX_SRC1; 99362306a36Sopenharmony_ci else 99462306a36Sopenharmony_ci reg = MAX98397_R2056_PCM_RX_SRC1; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci change = snd_soc_component_test_bits(component, reg, 99762306a36Sopenharmony_ci MAX98396_PCM_RX_MASK, val); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci if (change) 100062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, reg, 100162306a36Sopenharmony_ci MAX98396_PCM_RX_MASK, val); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL); 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci return change; 100662306a36Sopenharmony_ci} 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_cistatic const char * const max98396_switch_text[] = { 100962306a36Sopenharmony_ci "Left", "Right", "LeftRight"}; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(dai_sel_enum, SND_SOC_NOPM, 0, 101262306a36Sopenharmony_ci max98396_switch_text); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98396_dai_mux = 101562306a36Sopenharmony_ci SOC_DAPM_ENUM_EXT("DAI Sel Mux", dai_sel_enum, 101662306a36Sopenharmony_ci max98396_mux_get, max98396_mux_put); 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98396_vi_control = 101962306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", MAX98396_R205F_PCM_TX_EN, 0, 1, 0); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98396_dapm_widgets[] = { 102262306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", 102362306a36Sopenharmony_ci MAX98396_R20AF_AMP_EN, 0, 0, max98396_dac_event, 102462306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 102562306a36Sopenharmony_ci SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, 102662306a36Sopenharmony_ci &max98396_dai_mux), 102762306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("BE_OUT"), 102862306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0, 102962306a36Sopenharmony_ci MAX98396_R20E4_IV_SENSE_PATH_EN, 0, 0), 103062306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0, 103162306a36Sopenharmony_ci MAX98396_R20E4_IV_SENSE_PATH_EN, 1, 0), 103262306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0, 103362306a36Sopenharmony_ci &max98396_vi_control), 103462306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("VMON"), 103562306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("IMON"), 103662306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("FBMON"), 103762306a36Sopenharmony_ci}; 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_cistatic const char * const max98396_thermal_thresh_text[] = { 104062306a36Sopenharmony_ci "50C", "51C", "52C", "53C", "54C", "55C", "56C", "57C", 104162306a36Sopenharmony_ci "58C", "59C", "60C", "61C", "62C", "63C", "64C", "65C", 104262306a36Sopenharmony_ci "66C", "67C", "68C", "69C", "70C", "71C", "72C", "73C", 104362306a36Sopenharmony_ci "74C", "75C", "76C", "77C", "78C", "79C", "80C", "81C", 104462306a36Sopenharmony_ci "82C", "83C", "84C", "85C", "86C", "87C", "88C", "89C", 104562306a36Sopenharmony_ci "90C", "91C", "92C", "93C", "94C", "95C", "96C", "97C", 104662306a36Sopenharmony_ci "98C", "99C", "100C", "101C", "102C", "103C", "104C", "105C", 104762306a36Sopenharmony_ci "106C", "107C", "108C", "109C", "110C", "111C", "112C", "113C", 104862306a36Sopenharmony_ci "114C", "115C", "116C", "117C", "118C", "119C", "120C", "121C", 104962306a36Sopenharmony_ci "122C", "123C", "124C", "125C", "126C", "127C", "128C", "129C", 105062306a36Sopenharmony_ci "130C", "131C", "132C", "133C", "134C", "135C", "136C", "137C", 105162306a36Sopenharmony_ci "138C", "139C", "140C", "141C", "142C", "143C", "144C", "145C", 105262306a36Sopenharmony_ci "146C", "147C", "148C", "149C", "150C" 105362306a36Sopenharmony_ci}; 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh1_enum, 105662306a36Sopenharmony_ci MAX98396_R2020_THERM_WARN_THRESH, 0, 105762306a36Sopenharmony_ci max98396_thermal_thresh_text); 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh2_enum, 106062306a36Sopenharmony_ci MAX98396_R2021_THERM_WARN_THRESH2, 0, 106162306a36Sopenharmony_ci max98396_thermal_thresh_text); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_shdn_thresh_enum, 106462306a36Sopenharmony_ci MAX98396_R2022_THERM_SHDN_THRESH, 0, 106562306a36Sopenharmony_ci max98396_thermal_thresh_text); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_cistatic const char * const max98396_thermal_hyteresis_text[] = { 106862306a36Sopenharmony_ci "2C", "5C", "7C", "10C" 106962306a36Sopenharmony_ci}; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_hysteresis_enum, 107262306a36Sopenharmony_ci MAX98396_R2023_THERM_HYSTERESIS, 0, 107362306a36Sopenharmony_ci max98396_thermal_hyteresis_text); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_cistatic const char * const max98396_foldback_slope_text[] = { 107662306a36Sopenharmony_ci "0.25", "0.5", "1.0", "2.0" 107762306a36Sopenharmony_ci}; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope1_enum, 108062306a36Sopenharmony_ci MAX98396_R2024_THERM_FOLDBACK_SET, 108162306a36Sopenharmony_ci MAX98396_THERM_FB_SLOPE1_SHIFT, 108262306a36Sopenharmony_ci max98396_foldback_slope_text); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope2_enum, 108562306a36Sopenharmony_ci MAX98396_R2024_THERM_FOLDBACK_SET, 108662306a36Sopenharmony_ci MAX98396_THERM_FB_SLOPE2_SHIFT, 108762306a36Sopenharmony_ci max98396_foldback_slope_text); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_cistatic const char * const max98396_foldback_reltime_text[] = { 109062306a36Sopenharmony_ci "3ms", "10ms", "100ms", "300ms" 109162306a36Sopenharmony_ci}; 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_reltime_enum, 109462306a36Sopenharmony_ci MAX98396_R2024_THERM_FOLDBACK_SET, 109562306a36Sopenharmony_ci MAX98396_THERM_FB_REL_SHIFT, 109662306a36Sopenharmony_ci max98396_foldback_reltime_text); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic const char * const max98396_foldback_holdtime_text[] = { 109962306a36Sopenharmony_ci "0ms", "20ms", "40ms", "80ms" 110062306a36Sopenharmony_ci}; 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_holdtime_enum, 110362306a36Sopenharmony_ci MAX98396_R2024_THERM_FOLDBACK_SET, 110462306a36Sopenharmony_ci MAX98396_THERM_FB_HOLD_SHIFT, 110562306a36Sopenharmony_ci max98396_foldback_holdtime_text); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_cistatic int max98396_adc_value_get(struct snd_kcontrol *kcontrol, 110862306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 111162306a36Sopenharmony_ci struct soc_mixer_control *mc = 111262306a36Sopenharmony_ci (struct soc_mixer_control *)kcontrol->private_value; 111362306a36Sopenharmony_ci struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component); 111462306a36Sopenharmony_ci int ret; 111562306a36Sopenharmony_ci u8 val[2]; 111662306a36Sopenharmony_ci int reg = mc->reg; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci /* ADC value is not available if the device is powered down */ 111962306a36Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) 112062306a36Sopenharmony_ci goto exit; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98397) { 112362306a36Sopenharmony_ci switch (mc->reg) { 112462306a36Sopenharmony_ci case MAX98396_R20B6_ADC_PVDD_READBACK_MSB: 112562306a36Sopenharmony_ci reg = MAX98397_R20B7_ADC_PVDD_READBACK_MSB; 112662306a36Sopenharmony_ci break; 112762306a36Sopenharmony_ci case MAX98396_R20B8_ADC_VBAT_READBACK_MSB: 112862306a36Sopenharmony_ci reg = MAX98397_R20B9_ADC_VBAT_READBACK_MSB; 112962306a36Sopenharmony_ci break; 113062306a36Sopenharmony_ci case MAX98396_R20BA_ADC_TEMP_READBACK_MSB: 113162306a36Sopenharmony_ci reg = MAX98397_R20BB_ADC_TEMP_READBACK_MSB; 113262306a36Sopenharmony_ci break; 113362306a36Sopenharmony_ci default: 113462306a36Sopenharmony_ci goto exit; 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci ret = regmap_raw_read(max98396->regmap, reg, &val, 2); 113962306a36Sopenharmony_ci if (ret) 114062306a36Sopenharmony_ci goto exit; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci /* ADC readback bits[8:0] rearrangement */ 114362306a36Sopenharmony_ci ucontrol->value.integer.value[0] = (val[0] << 1) | (val[1] & 1); 114462306a36Sopenharmony_ci return 0; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ciexit: 114762306a36Sopenharmony_ci ucontrol->value.integer.value[0] = 0; 114862306a36Sopenharmony_ci return 0; 114962306a36Sopenharmony_ci} 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98396_snd_controls[] = { 115262306a36Sopenharmony_ci /* Volume */ 115362306a36Sopenharmony_ci SOC_SINGLE_TLV("Digital Volume", MAX98396_R2090_AMP_VOL_CTRL, 115462306a36Sopenharmony_ci 0, 0x7F, 1, max98396_digital_tlv), 115562306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker Volume", MAX98396_R2091_AMP_PATH_GAIN, 115662306a36Sopenharmony_ci 0, 0x11, 0, max98396_spk_tlv), 115762306a36Sopenharmony_ci /* Volume Ramp Up/Down Enable*/ 115862306a36Sopenharmony_ci SOC_SINGLE("Ramp Up Switch", MAX98396_R2092_AMP_DSP_CFG, 115962306a36Sopenharmony_ci MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0), 116062306a36Sopenharmony_ci SOC_SINGLE("Ramp Down Switch", MAX98396_R2092_AMP_DSP_CFG, 116162306a36Sopenharmony_ci MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0), 116262306a36Sopenharmony_ci /* Clock Monitor Enable */ 116362306a36Sopenharmony_ci SOC_SINGLE("CLK Monitor Switch", MAX98396_R203F_ENABLE_CTRLS, 116462306a36Sopenharmony_ci MAX98396_CTRL_CMON_EN_SHIFT, 1, 0), 116562306a36Sopenharmony_ci /* Dither Enable */ 116662306a36Sopenharmony_ci SOC_SINGLE("Dither Switch", MAX98396_R2092_AMP_DSP_CFG, 116762306a36Sopenharmony_ci MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0), 116862306a36Sopenharmony_ci SOC_SINGLE("IV Dither Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 116962306a36Sopenharmony_ci MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0), 117062306a36Sopenharmony_ci /* DC Blocker Enable */ 117162306a36Sopenharmony_ci SOC_SINGLE("DC Blocker Switch", MAX98396_R2092_AMP_DSP_CFG, 117262306a36Sopenharmony_ci MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0), 117362306a36Sopenharmony_ci SOC_SINGLE("IV DC Blocker Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 117462306a36Sopenharmony_ci MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0), 117562306a36Sopenharmony_ci /* Speaker Safe Mode Enable */ 117662306a36Sopenharmony_ci SOC_SINGLE("Safe Mode Switch", MAX98396_R2092_AMP_DSP_CFG, 117762306a36Sopenharmony_ci MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0), 117862306a36Sopenharmony_ci /* Wideband Filter Enable */ 117962306a36Sopenharmony_ci SOC_SINGLE("WB Filter Switch", MAX98396_R2092_AMP_DSP_CFG, 118062306a36Sopenharmony_ci MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0), 118162306a36Sopenharmony_ci SOC_SINGLE("IV WB Filter Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 118262306a36Sopenharmony_ci MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0), 118362306a36Sopenharmony_ci /* Dynamic Headroom Tracking */ 118462306a36Sopenharmony_ci SOC_SINGLE("DHT Switch", MAX98396_R20DF_DHT_EN, 0, 1, 0), 118562306a36Sopenharmony_ci /* Brownout Protection Engine */ 118662306a36Sopenharmony_ci SOC_SINGLE("BPE Switch", MAX98396_R210D_BPE_EN, 0, 1, 0), 118762306a36Sopenharmony_ci SOC_SINGLE("BPE Limiter Switch", MAX98396_R210D_BPE_EN, 1, 1, 0), 118862306a36Sopenharmony_ci /* Bypass Path Enable */ 118962306a36Sopenharmony_ci SOC_SINGLE("Bypass Path Switch", 119062306a36Sopenharmony_ci MAX98396_R205E_PCM_RX_EN, 1, 1, 0), 119162306a36Sopenharmony_ci /* Speaker Operation Mode */ 119262306a36Sopenharmony_ci SOC_ENUM("OP Mode", max98396_op_mod_enum), 119362306a36Sopenharmony_ci /* Auto Restart functions */ 119462306a36Sopenharmony_ci SOC_SINGLE("CMON Auto Restart Switch", MAX98396_R2038_CLK_MON_CTRL, 119562306a36Sopenharmony_ci MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0), 119662306a36Sopenharmony_ci SOC_SINGLE("PVDD Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 119762306a36Sopenharmony_ci MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0), 119862306a36Sopenharmony_ci SOC_SINGLE("VBAT Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 119962306a36Sopenharmony_ci MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0), 120062306a36Sopenharmony_ci SOC_SINGLE("THERM Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 120162306a36Sopenharmony_ci MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0), 120262306a36Sopenharmony_ci SOC_SINGLE("OVC Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 120362306a36Sopenharmony_ci MAX98396_OVC_RESTART_SHFT, 1, 0), 120462306a36Sopenharmony_ci /* Thermal Threshold */ 120562306a36Sopenharmony_ci SOC_ENUM("THERM Thresh1", max98396_thermal_warn_thresh1_enum), 120662306a36Sopenharmony_ci SOC_ENUM("THERM Thresh2", max98396_thermal_warn_thresh2_enum), 120762306a36Sopenharmony_ci SOC_ENUM("THERM SHDN Thresh", max98396_thermal_shdn_thresh_enum), 120862306a36Sopenharmony_ci SOC_ENUM("THERM Hysteresis", max98396_thermal_hysteresis_enum), 120962306a36Sopenharmony_ci SOC_SINGLE("THERM Foldback Switch", 121062306a36Sopenharmony_ci MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0), 121162306a36Sopenharmony_ci SOC_ENUM("THERM Slope1", max98396_thermal_fb_slope1_enum), 121262306a36Sopenharmony_ci SOC_ENUM("THERM Slope2", max98396_thermal_fb_slope2_enum), 121362306a36Sopenharmony_ci SOC_ENUM("THERM Release", max98396_thermal_fb_reltime_enum), 121462306a36Sopenharmony_ci SOC_ENUM("THERM Hold", max98396_thermal_fb_holdtime_enum), 121562306a36Sopenharmony_ci /* ADC */ 121662306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC PVDD", MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0, 121762306a36Sopenharmony_ci max98396_adc_value_get, NULL), 121862306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC VBAT", MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0, 121962306a36Sopenharmony_ci max98396_adc_value_get, NULL), 122062306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC TEMP", MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0, 122162306a36Sopenharmony_ci max98396_adc_value_get, NULL), 122262306a36Sopenharmony_ci}; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98397_snd_controls[] = { 122562306a36Sopenharmony_ci /* Volume */ 122662306a36Sopenharmony_ci SOC_SINGLE_TLV("Digital Volume", MAX98396_R2090_AMP_VOL_CTRL, 122762306a36Sopenharmony_ci 0, 0xFF, 1, max98397_digital_tlv), 122862306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker Volume", MAX98396_R2091_AMP_PATH_GAIN, 122962306a36Sopenharmony_ci 0, 0x15, 0, max98397_spk_tlv), 123062306a36Sopenharmony_ci /* Volume Ramp Up/Down Enable*/ 123162306a36Sopenharmony_ci SOC_SINGLE("Ramp Up Switch", MAX98396_R2092_AMP_DSP_CFG, 123262306a36Sopenharmony_ci MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0), 123362306a36Sopenharmony_ci SOC_SINGLE("Ramp Down Switch", MAX98396_R2092_AMP_DSP_CFG, 123462306a36Sopenharmony_ci MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0), 123562306a36Sopenharmony_ci /* Clock Monitor Enable */ 123662306a36Sopenharmony_ci SOC_SINGLE("CLK Monitor Switch", MAX98396_R203F_ENABLE_CTRLS, 123762306a36Sopenharmony_ci MAX98396_CTRL_CMON_EN_SHIFT, 1, 0), 123862306a36Sopenharmony_ci /* Dither Enable */ 123962306a36Sopenharmony_ci SOC_SINGLE("Dither Switch", MAX98396_R2092_AMP_DSP_CFG, 124062306a36Sopenharmony_ci MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0), 124162306a36Sopenharmony_ci SOC_SINGLE("IV Dither Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 124262306a36Sopenharmony_ci MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0), 124362306a36Sopenharmony_ci /* DC Blocker Enable */ 124462306a36Sopenharmony_ci SOC_SINGLE("DC Blocker Switch", MAX98396_R2092_AMP_DSP_CFG, 124562306a36Sopenharmony_ci MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0), 124662306a36Sopenharmony_ci SOC_SINGLE("IV DC Blocker Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 124762306a36Sopenharmony_ci MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0), 124862306a36Sopenharmony_ci /* Speaker Safe Mode Enable */ 124962306a36Sopenharmony_ci SOC_SINGLE("Safe Mode Switch", MAX98396_R2092_AMP_DSP_CFG, 125062306a36Sopenharmony_ci MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0), 125162306a36Sopenharmony_ci /* Wideband Filter Enable */ 125262306a36Sopenharmony_ci SOC_SINGLE("WB Filter Switch", MAX98396_R2092_AMP_DSP_CFG, 125362306a36Sopenharmony_ci MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0), 125462306a36Sopenharmony_ci SOC_SINGLE("IV WB Filter Switch", MAX98396_R20E0_IV_SENSE_PATH_CFG, 125562306a36Sopenharmony_ci MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0), 125662306a36Sopenharmony_ci /* Dynamic Headroom Tracking */ 125762306a36Sopenharmony_ci SOC_SINGLE("DHT Switch", MAX98396_R20DF_DHT_EN, 0, 1, 0), 125862306a36Sopenharmony_ci /* Brownout Protection Engine */ 125962306a36Sopenharmony_ci SOC_SINGLE("BPE Switch", MAX98396_R210D_BPE_EN, 0, 1, 0), 126062306a36Sopenharmony_ci SOC_SINGLE("BPE Limiter Switch", MAX98396_R210D_BPE_EN, 1, 1, 0), 126162306a36Sopenharmony_ci /* Bypass Path Enable */ 126262306a36Sopenharmony_ci SOC_SINGLE("Bypass Path Switch", 126362306a36Sopenharmony_ci MAX98396_R205E_PCM_RX_EN, 1, 1, 0), 126462306a36Sopenharmony_ci /* Speaker Operation Mode */ 126562306a36Sopenharmony_ci SOC_ENUM("OP Mode", max98396_op_mod_enum), 126662306a36Sopenharmony_ci /* Auto Restart functions */ 126762306a36Sopenharmony_ci SOC_SINGLE("CMON Auto Restart Switch", MAX98396_R2038_CLK_MON_CTRL, 126862306a36Sopenharmony_ci MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0), 126962306a36Sopenharmony_ci SOC_SINGLE("PVDD Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 127062306a36Sopenharmony_ci MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0), 127162306a36Sopenharmony_ci SOC_SINGLE("VBAT Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 127262306a36Sopenharmony_ci MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0), 127362306a36Sopenharmony_ci SOC_SINGLE("THERM Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 127462306a36Sopenharmony_ci MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0), 127562306a36Sopenharmony_ci SOC_SINGLE("OVC Auto Restart Switch", MAX98396_R210E_AUTO_RESTART, 127662306a36Sopenharmony_ci MAX98396_OVC_RESTART_SHFT, 1, 0), 127762306a36Sopenharmony_ci /* Thermal Threshold */ 127862306a36Sopenharmony_ci SOC_ENUM("THERM Thresh1", max98396_thermal_warn_thresh1_enum), 127962306a36Sopenharmony_ci SOC_ENUM("THERM Thresh2", max98396_thermal_warn_thresh2_enum), 128062306a36Sopenharmony_ci SOC_ENUM("THERM SHDN Thresh", max98396_thermal_shdn_thresh_enum), 128162306a36Sopenharmony_ci SOC_ENUM("THERM Hysteresis", max98396_thermal_hysteresis_enum), 128262306a36Sopenharmony_ci SOC_SINGLE("THERM Foldback Switch", 128362306a36Sopenharmony_ci MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0), 128462306a36Sopenharmony_ci SOC_ENUM("THERM Slope1", max98396_thermal_fb_slope1_enum), 128562306a36Sopenharmony_ci SOC_ENUM("THERM Slope2", max98396_thermal_fb_slope2_enum), 128662306a36Sopenharmony_ci SOC_ENUM("THERM Release", max98396_thermal_fb_reltime_enum), 128762306a36Sopenharmony_ci SOC_ENUM("THERM Hold", max98396_thermal_fb_holdtime_enum), 128862306a36Sopenharmony_ci /* ADC */ 128962306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC PVDD", MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0, 129062306a36Sopenharmony_ci max98396_adc_value_get, NULL), 129162306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC VBAT", MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0, 129262306a36Sopenharmony_ci max98396_adc_value_get, NULL), 129362306a36Sopenharmony_ci SOC_SINGLE_EXT("ADC TEMP", MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0, 129462306a36Sopenharmony_ci max98396_adc_value_get, NULL), 129562306a36Sopenharmony_ci}; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98396_audio_map[] = { 129862306a36Sopenharmony_ci /* Plabyack */ 129962306a36Sopenharmony_ci {"DAI Sel Mux", "Left", "Amp Enable"}, 130062306a36Sopenharmony_ci {"DAI Sel Mux", "Right", "Amp Enable"}, 130162306a36Sopenharmony_ci {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 130262306a36Sopenharmony_ci {"BE_OUT", NULL, "DAI Sel Mux"}, 130362306a36Sopenharmony_ci /* Capture */ 130462306a36Sopenharmony_ci { "VI Sense", "Switch", "VMON" }, 130562306a36Sopenharmony_ci { "VI Sense", "Switch", "IMON" }, 130662306a36Sopenharmony_ci { "Voltage Sense", NULL, "VI Sense" }, 130762306a36Sopenharmony_ci { "Current Sense", NULL, "VI Sense" }, 130862306a36Sopenharmony_ci}; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98396_dai[] = { 131162306a36Sopenharmony_ci { 131262306a36Sopenharmony_ci .name = "max98396-aif1", 131362306a36Sopenharmony_ci .playback = { 131462306a36Sopenharmony_ci .stream_name = "HiFi Playback", 131562306a36Sopenharmony_ci .channels_min = 1, 131662306a36Sopenharmony_ci .channels_max = 2, 131762306a36Sopenharmony_ci .rates = MAX98396_RATES, 131862306a36Sopenharmony_ci .formats = MAX98396_FORMATS, 131962306a36Sopenharmony_ci }, 132062306a36Sopenharmony_ci .capture = { 132162306a36Sopenharmony_ci .stream_name = "HiFi Capture", 132262306a36Sopenharmony_ci .channels_min = 1, 132362306a36Sopenharmony_ci .channels_max = 2, 132462306a36Sopenharmony_ci .rates = MAX98396_RATES, 132562306a36Sopenharmony_ci .formats = MAX98396_FORMATS, 132662306a36Sopenharmony_ci }, 132762306a36Sopenharmony_ci .ops = &max98396_dai_ops, 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci}; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98397_dai[] = { 133262306a36Sopenharmony_ci { 133362306a36Sopenharmony_ci .name = "max98397-aif1", 133462306a36Sopenharmony_ci .playback = { 133562306a36Sopenharmony_ci .stream_name = "HiFi Playback", 133662306a36Sopenharmony_ci .channels_min = 1, 133762306a36Sopenharmony_ci .channels_max = 2, 133862306a36Sopenharmony_ci .rates = MAX98396_RATES, 133962306a36Sopenharmony_ci .formats = MAX98396_FORMATS, 134062306a36Sopenharmony_ci }, 134162306a36Sopenharmony_ci .capture = { 134262306a36Sopenharmony_ci .stream_name = "HiFi Capture", 134362306a36Sopenharmony_ci .channels_min = 1, 134462306a36Sopenharmony_ci .channels_max = 2, 134562306a36Sopenharmony_ci .rates = MAX98396_RATES, 134662306a36Sopenharmony_ci .formats = MAX98396_FORMATS, 134762306a36Sopenharmony_ci }, 134862306a36Sopenharmony_ci .ops = &max98396_dai_ops, 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci}; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic void max98396_reset(struct max98396_priv *max98396, struct device *dev) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci int ret, reg, count; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci /* Software Reset */ 135762306a36Sopenharmony_ci ret = regmap_write(max98396->regmap, 135862306a36Sopenharmony_ci MAX98396_R2000_SW_RESET, 1); 135962306a36Sopenharmony_ci if (ret) 136062306a36Sopenharmony_ci dev_err(dev, "Reset command failed. (ret:%d)\n", ret); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci count = 0; 136362306a36Sopenharmony_ci while (count < 3) { 136462306a36Sopenharmony_ci usleep_range(5000, 6000); 136562306a36Sopenharmony_ci /* Software Reset Verification */ 136662306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, 136762306a36Sopenharmony_ci GET_REG_ADDR_REV_ID(max98396->device_id), ®); 136862306a36Sopenharmony_ci if (!ret) { 136962306a36Sopenharmony_ci dev_info(dev, "Reset completed (retry:%d)\n", count); 137062306a36Sopenharmony_ci return; 137162306a36Sopenharmony_ci } 137262306a36Sopenharmony_ci count++; 137362306a36Sopenharmony_ci } 137462306a36Sopenharmony_ci dev_err(dev, "Reset failed. (ret:%d)\n", ret); 137562306a36Sopenharmony_ci} 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_cistatic int max98396_probe(struct snd_soc_component *component) 137862306a36Sopenharmony_ci{ 137962306a36Sopenharmony_ci struct max98396_priv *max98396 = 138062306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci /* Software Reset */ 138362306a36Sopenharmony_ci max98396_reset(max98396, component->dev); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci /* L/R mix configuration */ 138662306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) { 138762306a36Sopenharmony_ci regmap_write(max98396->regmap, 138862306a36Sopenharmony_ci MAX98396_R2055_PCM_RX_SRC1, 0x02); 138962306a36Sopenharmony_ci regmap_write(max98396->regmap, 139062306a36Sopenharmony_ci MAX98396_R2056_PCM_RX_SRC2, 0x10); 139162306a36Sopenharmony_ci } else { 139262306a36Sopenharmony_ci regmap_write(max98396->regmap, 139362306a36Sopenharmony_ci MAX98397_R2056_PCM_RX_SRC1, 0x02); 139462306a36Sopenharmony_ci regmap_write(max98396->regmap, 139562306a36Sopenharmony_ci MAX98397_R2057_PCM_RX_SRC2, 0x10); 139662306a36Sopenharmony_ci } 139762306a36Sopenharmony_ci /* Supply control */ 139862306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 139962306a36Sopenharmony_ci MAX98396_R20A0_AMP_SUPPLY_CTL, 140062306a36Sopenharmony_ci MAX98396_AMP_SUPPLY_NOVBAT, 140162306a36Sopenharmony_ci (max98396->vbat == NULL) ? 140262306a36Sopenharmony_ci MAX98396_AMP_SUPPLY_NOVBAT : 0); 140362306a36Sopenharmony_ci /* Enable DC blocker */ 140462306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 140562306a36Sopenharmony_ci MAX98396_R2092_AMP_DSP_CFG, 1, 1); 140662306a36Sopenharmony_ci /* Enable IV Monitor DC blocker */ 140762306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 140862306a36Sopenharmony_ci MAX98396_R20E0_IV_SENSE_PATH_CFG, 140962306a36Sopenharmony_ci MAX98396_IV_SENSE_DCBLK_EN_MASK, 141062306a36Sopenharmony_ci MAX98396_IV_SENSE_DCBLK_EN_MASK); 141162306a36Sopenharmony_ci /* Configure default data output sources */ 141262306a36Sopenharmony_ci regmap_write(max98396->regmap, 141362306a36Sopenharmony_ci MAX98396_R205D_PCM_TX_SRC_EN, 3); 141462306a36Sopenharmony_ci /* Enable Wideband Filter */ 141562306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 141662306a36Sopenharmony_ci MAX98396_R2092_AMP_DSP_CFG, 0x40, 0x40); 141762306a36Sopenharmony_ci /* Enable IV Wideband Filter */ 141862306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 141962306a36Sopenharmony_ci MAX98396_R20E0_IV_SENSE_PATH_CFG, 8, 8); 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci /* Enable Bypass Source */ 142262306a36Sopenharmony_ci regmap_write(max98396->regmap, 142362306a36Sopenharmony_ci MAX98396_R2058_PCM_BYPASS_SRC, 142462306a36Sopenharmony_ci max98396->bypass_slot); 142562306a36Sopenharmony_ci /* Voltage, current slot configuration */ 142662306a36Sopenharmony_ci regmap_write(max98396->regmap, 142762306a36Sopenharmony_ci MAX98396_R2044_PCM_TX_CTRL_1, 142862306a36Sopenharmony_ci max98396->v_slot); 142962306a36Sopenharmony_ci regmap_write(max98396->regmap, 143062306a36Sopenharmony_ci MAX98396_R2045_PCM_TX_CTRL_2, 143162306a36Sopenharmony_ci max98396->i_slot); 143262306a36Sopenharmony_ci regmap_write(max98396->regmap, 143362306a36Sopenharmony_ci MAX98396_R204A_PCM_TX_CTRL_7, 143462306a36Sopenharmony_ci max98396->spkfb_slot); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci if (max98396->v_slot < 8) 143762306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 143862306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 143962306a36Sopenharmony_ci MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 144062306a36Sopenharmony_ci 1 << max98396->v_slot, 0); 144162306a36Sopenharmony_ci else 144262306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 144362306a36Sopenharmony_ci MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 144462306a36Sopenharmony_ci 1 << max98396->v_slot, 0); 144562306a36Sopenharmony_ci else 144662306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 144762306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 144862306a36Sopenharmony_ci MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 144962306a36Sopenharmony_ci 1 << (max98396->v_slot - 8), 0); 145062306a36Sopenharmony_ci else 145162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 145262306a36Sopenharmony_ci MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 145362306a36Sopenharmony_ci 1 << (max98396->v_slot - 8), 0); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci if (max98396->i_slot < 8) 145662306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 145762306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 145862306a36Sopenharmony_ci MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 145962306a36Sopenharmony_ci 1 << max98396->i_slot, 0); 146062306a36Sopenharmony_ci else 146162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 146262306a36Sopenharmony_ci MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 146362306a36Sopenharmony_ci 1 << max98396->i_slot, 0); 146462306a36Sopenharmony_ci else 146562306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 146662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 146762306a36Sopenharmony_ci MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 146862306a36Sopenharmony_ci 1 << (max98396->i_slot - 8), 0); 146962306a36Sopenharmony_ci else 147062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 147162306a36Sopenharmony_ci MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 147262306a36Sopenharmony_ci 1 << (max98396->i_slot - 8), 0); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci /* Set interleave mode */ 147562306a36Sopenharmony_ci if (max98396->interleave_mode) 147662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 147762306a36Sopenharmony_ci MAX98396_R2041_PCM_MODE_CFG, 147862306a36Sopenharmony_ci MAX98396_PCM_TX_CH_INTERLEAVE_MASK, 147962306a36Sopenharmony_ci MAX98396_PCM_TX_CH_INTERLEAVE_MASK); 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 148262306a36Sopenharmony_ci MAX98396_R2038_CLK_MON_CTRL, 148362306a36Sopenharmony_ci MAX98396_CLK_MON_AUTO_RESTART_MASK, 148462306a36Sopenharmony_ci MAX98396_CLK_MON_AUTO_RESTART_MASK); 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 148762306a36Sopenharmony_ci MAX98396_R203F_ENABLE_CTRLS, 148862306a36Sopenharmony_ci MAX98396_CTRL_DMON_STUCK_EN_MASK, 148962306a36Sopenharmony_ci max98396->dmon_stuck_enable ? 149062306a36Sopenharmony_ci MAX98396_CTRL_DMON_STUCK_EN_MASK : 0); 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 149362306a36Sopenharmony_ci MAX98396_R203F_ENABLE_CTRLS, 149462306a36Sopenharmony_ci MAX98396_CTRL_DMON_MAG_EN_MASK, 149562306a36Sopenharmony_ci max98396->dmon_mag_enable ? 149662306a36Sopenharmony_ci MAX98396_CTRL_DMON_MAG_EN_MASK : 0); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci switch (max98396->dmon_duration) { 149962306a36Sopenharmony_ci case 64: 150062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 150162306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 150262306a36Sopenharmony_ci MAX98396_DMON_DURATION_MASK, 0); 150362306a36Sopenharmony_ci break; 150462306a36Sopenharmony_ci case 256: 150562306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 150662306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 150762306a36Sopenharmony_ci MAX98396_DMON_DURATION_MASK, 1); 150862306a36Sopenharmony_ci break; 150962306a36Sopenharmony_ci case 1024: 151062306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 151162306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 151262306a36Sopenharmony_ci MAX98396_DMON_DURATION_MASK, 2); 151362306a36Sopenharmony_ci break; 151462306a36Sopenharmony_ci case 4096: 151562306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 151662306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 151762306a36Sopenharmony_ci MAX98396_DMON_DURATION_MASK, 3); 151862306a36Sopenharmony_ci break; 151962306a36Sopenharmony_ci default: 152062306a36Sopenharmony_ci dev_err(component->dev, "Invalid DMON duration %d\n", 152162306a36Sopenharmony_ci max98396->dmon_duration); 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci switch (max98396->dmon_stuck_threshold) { 152562306a36Sopenharmony_ci case 15: 152662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 152762306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 152862306a36Sopenharmony_ci MAX98396_DMON_STUCK_THRESH_MASK, 152962306a36Sopenharmony_ci 0 << MAX98396_DMON_STUCK_THRESH_SHIFT); 153062306a36Sopenharmony_ci break; 153162306a36Sopenharmony_ci case 13: 153262306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 153362306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 153462306a36Sopenharmony_ci MAX98396_DMON_STUCK_THRESH_MASK, 153562306a36Sopenharmony_ci 1 << MAX98396_DMON_STUCK_THRESH_SHIFT); 153662306a36Sopenharmony_ci break; 153762306a36Sopenharmony_ci case 22: 153862306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 153962306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 154062306a36Sopenharmony_ci MAX98396_DMON_STUCK_THRESH_MASK, 154162306a36Sopenharmony_ci 2 << MAX98396_DMON_STUCK_THRESH_SHIFT); 154262306a36Sopenharmony_ci break; 154362306a36Sopenharmony_ci case 9: 154462306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 154562306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 154662306a36Sopenharmony_ci MAX98396_DMON_STUCK_THRESH_MASK, 154762306a36Sopenharmony_ci 3 << MAX98396_DMON_STUCK_THRESH_SHIFT); 154862306a36Sopenharmony_ci break; 154962306a36Sopenharmony_ci default: 155062306a36Sopenharmony_ci dev_err(component->dev, "Invalid DMON stuck threshold %d\n", 155162306a36Sopenharmony_ci max98396->dmon_stuck_threshold); 155262306a36Sopenharmony_ci } 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci switch (max98396->dmon_mag_threshold) { 155562306a36Sopenharmony_ci case 2 ... 5: 155662306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 155762306a36Sopenharmony_ci MAX98396_R2039_DATA_MON_CTRL, 155862306a36Sopenharmony_ci MAX98396_DMON_STUCK_THRESH_MASK, 155962306a36Sopenharmony_ci (5 - max98396->dmon_mag_threshold) 156062306a36Sopenharmony_ci << MAX98396_DMON_MAG_THRESH_SHIFT); 156162306a36Sopenharmony_ci break; 156262306a36Sopenharmony_ci default: 156362306a36Sopenharmony_ci dev_err(component->dev, "Invalid DMON magnitude threshold %d\n", 156462306a36Sopenharmony_ci max98396->dmon_mag_threshold); 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci /* Speaker Amplifier PCM RX Enable by default */ 156862306a36Sopenharmony_ci regmap_update_bits(max98396->regmap, 156962306a36Sopenharmony_ci MAX98396_R205E_PCM_RX_EN, 157062306a36Sopenharmony_ci MAX98396_PCM_RX_EN_MASK, 1); 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci return 0; 157362306a36Sopenharmony_ci} 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 157662306a36Sopenharmony_cistatic int max98396_suspend(struct device *dev) 157762306a36Sopenharmony_ci{ 157862306a36Sopenharmony_ci struct max98396_priv *max98396 = dev_get_drvdata(dev); 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci regcache_cache_only(max98396->regmap, true); 158162306a36Sopenharmony_ci regcache_mark_dirty(max98396->regmap); 158262306a36Sopenharmony_ci regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES, 158362306a36Sopenharmony_ci max98396->core_supplies); 158462306a36Sopenharmony_ci if (max98396->pvdd) 158562306a36Sopenharmony_ci regulator_disable(max98396->pvdd); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci if (max98396->vbat) 158862306a36Sopenharmony_ci regulator_disable(max98396->vbat); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci return 0; 159162306a36Sopenharmony_ci} 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_cistatic int max98396_resume(struct device *dev) 159462306a36Sopenharmony_ci{ 159562306a36Sopenharmony_ci struct max98396_priv *max98396 = dev_get_drvdata(dev); 159662306a36Sopenharmony_ci int ret; 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES, 159962306a36Sopenharmony_ci max98396->core_supplies); 160062306a36Sopenharmony_ci if (ret < 0) 160162306a36Sopenharmony_ci return ret; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (max98396->pvdd) { 160462306a36Sopenharmony_ci ret = regulator_enable(max98396->pvdd); 160562306a36Sopenharmony_ci if (ret < 0) 160662306a36Sopenharmony_ci return ret; 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci if (max98396->vbat) { 161062306a36Sopenharmony_ci ret = regulator_enable(max98396->vbat); 161162306a36Sopenharmony_ci if (ret < 0) 161262306a36Sopenharmony_ci return ret; 161362306a36Sopenharmony_ci } 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci regcache_cache_only(max98396->regmap, false); 161662306a36Sopenharmony_ci max98396_reset(max98396, dev); 161762306a36Sopenharmony_ci regcache_sync(max98396->regmap); 161862306a36Sopenharmony_ci return 0; 161962306a36Sopenharmony_ci} 162062306a36Sopenharmony_ci#endif 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_cistatic const struct dev_pm_ops max98396_pm = { 162362306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(max98396_suspend, max98396_resume) 162462306a36Sopenharmony_ci}; 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_max98396 = { 162762306a36Sopenharmony_ci .probe = max98396_probe, 162862306a36Sopenharmony_ci .controls = max98396_snd_controls, 162962306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98396_snd_controls), 163062306a36Sopenharmony_ci .dapm_widgets = max98396_dapm_widgets, 163162306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98396_dapm_widgets), 163262306a36Sopenharmony_ci .dapm_routes = max98396_audio_map, 163362306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98396_audio_map), 163462306a36Sopenharmony_ci .idle_bias_on = 1, 163562306a36Sopenharmony_ci .use_pmdown_time = 1, 163662306a36Sopenharmony_ci .endianness = 1, 163762306a36Sopenharmony_ci}; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_max98397 = { 164062306a36Sopenharmony_ci .probe = max98396_probe, 164162306a36Sopenharmony_ci .controls = max98397_snd_controls, 164262306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98397_snd_controls), 164362306a36Sopenharmony_ci .dapm_widgets = max98396_dapm_widgets, 164462306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98396_dapm_widgets), 164562306a36Sopenharmony_ci .dapm_routes = max98396_audio_map, 164662306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98396_audio_map), 164762306a36Sopenharmony_ci .idle_bias_on = 1, 164862306a36Sopenharmony_ci .use_pmdown_time = 1, 164962306a36Sopenharmony_ci .endianness = 1, 165062306a36Sopenharmony_ci}; 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_cistatic const struct regmap_config max98396_regmap = { 165362306a36Sopenharmony_ci .reg_bits = 16, 165462306a36Sopenharmony_ci .val_bits = 8, 165562306a36Sopenharmony_ci .max_register = MAX98396_R21FF_REVISION_ID, 165662306a36Sopenharmony_ci .reg_defaults = max98396_reg, 165762306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98396_reg), 165862306a36Sopenharmony_ci .readable_reg = max98396_readable_register, 165962306a36Sopenharmony_ci .volatile_reg = max98396_volatile_reg, 166062306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 166162306a36Sopenharmony_ci}; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_cistatic const struct regmap_config max98397_regmap = { 166462306a36Sopenharmony_ci .reg_bits = 16, 166562306a36Sopenharmony_ci .val_bits = 8, 166662306a36Sopenharmony_ci .max_register = MAX98397_R22FF_REVISION_ID, 166762306a36Sopenharmony_ci .reg_defaults = max98397_reg, 166862306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98397_reg), 166962306a36Sopenharmony_ci .readable_reg = max98397_readable_register, 167062306a36Sopenharmony_ci .volatile_reg = max98397_volatile_reg, 167162306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 167262306a36Sopenharmony_ci}; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_cistatic void max98396_read_device_property(struct device *dev, 167562306a36Sopenharmony_ci struct max98396_priv *max98396) 167662306a36Sopenharmony_ci{ 167762306a36Sopenharmony_ci int value; 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,vmon-slot-no", &value)) 168062306a36Sopenharmony_ci max98396->v_slot = value & 0xF; 168162306a36Sopenharmony_ci else 168262306a36Sopenharmony_ci max98396->v_slot = 0; 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,imon-slot-no", &value)) 168562306a36Sopenharmony_ci max98396->i_slot = value & 0xF; 168662306a36Sopenharmony_ci else 168762306a36Sopenharmony_ci max98396->i_slot = 1; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,spkfb-slot-no", &value)) 169062306a36Sopenharmony_ci max98396->spkfb_slot = value & 0xF; 169162306a36Sopenharmony_ci else 169262306a36Sopenharmony_ci max98396->spkfb_slot = 2; 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,bypass-slot-no", &value)) 169562306a36Sopenharmony_ci max98396->bypass_slot = value & 0xF; 169662306a36Sopenharmony_ci else 169762306a36Sopenharmony_ci max98396->bypass_slot = 0; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci max98396->dmon_stuck_enable = 170062306a36Sopenharmony_ci device_property_read_bool(dev, "adi,dmon-stuck-enable"); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,dmon-stuck-threshold-bits", &value)) 170362306a36Sopenharmony_ci max98396->dmon_stuck_threshold = value; 170462306a36Sopenharmony_ci else 170562306a36Sopenharmony_ci max98396->dmon_stuck_threshold = 15; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci max98396->dmon_mag_enable = 170862306a36Sopenharmony_ci device_property_read_bool(dev, "adi,dmon-magnitude-enable"); 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,dmon-magnitude-threshold-bits", &value)) 171162306a36Sopenharmony_ci max98396->dmon_mag_threshold = value; 171262306a36Sopenharmony_ci else 171362306a36Sopenharmony_ci max98396->dmon_mag_threshold = 5; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,dmon-duration-ms", &value)) 171662306a36Sopenharmony_ci max98396->dmon_duration = value; 171762306a36Sopenharmony_ci else 171862306a36Sopenharmony_ci max98396->dmon_duration = 64; 171962306a36Sopenharmony_ci} 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_cistatic void max98396_core_supplies_disable(void *priv) 172262306a36Sopenharmony_ci{ 172362306a36Sopenharmony_ci struct max98396_priv *max98396 = priv; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES, 172662306a36Sopenharmony_ci max98396->core_supplies); 172762306a36Sopenharmony_ci} 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_cistatic void max98396_supply_disable(void *r) 173062306a36Sopenharmony_ci{ 173162306a36Sopenharmony_ci regulator_disable((struct regulator *) r); 173262306a36Sopenharmony_ci} 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_cistatic int max98396_i2c_probe(struct i2c_client *i2c) 173562306a36Sopenharmony_ci{ 173662306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 173762306a36Sopenharmony_ci struct max98396_priv *max98396 = NULL; 173862306a36Sopenharmony_ci int i, ret, reg; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci max98396 = devm_kzalloc(&i2c->dev, sizeof(*max98396), GFP_KERNEL); 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci if (!max98396) { 174362306a36Sopenharmony_ci ret = -ENOMEM; 174462306a36Sopenharmony_ci return ret; 174562306a36Sopenharmony_ci } 174662306a36Sopenharmony_ci i2c_set_clientdata(i2c, max98396); 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci max98396->device_id = id->driver_data; 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci /* regmap initialization */ 175162306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 175262306a36Sopenharmony_ci max98396->regmap = devm_regmap_init_i2c(i2c, &max98396_regmap); 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci else 175562306a36Sopenharmony_ci max98396->regmap = devm_regmap_init_i2c(i2c, &max98397_regmap); 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci if (IS_ERR(max98396->regmap)) { 175862306a36Sopenharmony_ci ret = PTR_ERR(max98396->regmap); 175962306a36Sopenharmony_ci dev_err(&i2c->dev, 176062306a36Sopenharmony_ci "Failed to allocate regmap: %d\n", ret); 176162306a36Sopenharmony_ci return ret; 176262306a36Sopenharmony_ci } 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci /* Obtain regulator supplies */ 176562306a36Sopenharmony_ci for (i = 0; i < MAX98396_NUM_CORE_SUPPLIES; i++) 176662306a36Sopenharmony_ci max98396->core_supplies[i].supply = max98396_core_supplies[i]; 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci ret = devm_regulator_bulk_get(&i2c->dev, MAX98396_NUM_CORE_SUPPLIES, 176962306a36Sopenharmony_ci max98396->core_supplies); 177062306a36Sopenharmony_ci if (ret < 0) { 177162306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to request core supplies: %d\n", ret); 177262306a36Sopenharmony_ci return ret; 177362306a36Sopenharmony_ci } 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci max98396->vbat = devm_regulator_get_optional(&i2c->dev, "vbat"); 177662306a36Sopenharmony_ci if (IS_ERR(max98396->vbat)) { 177762306a36Sopenharmony_ci if (PTR_ERR(max98396->vbat) == -EPROBE_DEFER) 177862306a36Sopenharmony_ci return -EPROBE_DEFER; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci max98396->vbat = NULL; 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci max98396->pvdd = devm_regulator_get_optional(&i2c->dev, "pvdd"); 178462306a36Sopenharmony_ci if (IS_ERR(max98396->pvdd)) { 178562306a36Sopenharmony_ci if (PTR_ERR(max98396->pvdd) == -EPROBE_DEFER) 178662306a36Sopenharmony_ci return -EPROBE_DEFER; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci max98396->pvdd = NULL; 178962306a36Sopenharmony_ci } 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES, 179262306a36Sopenharmony_ci max98396->core_supplies); 179362306a36Sopenharmony_ci if (ret < 0) { 179462306a36Sopenharmony_ci dev_err(&i2c->dev, "Unable to enable core supplies: %d", ret); 179562306a36Sopenharmony_ci return ret; 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci ret = devm_add_action_or_reset(&i2c->dev, max98396_core_supplies_disable, 179962306a36Sopenharmony_ci max98396); 180062306a36Sopenharmony_ci if (ret < 0) 180162306a36Sopenharmony_ci return ret; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci if (max98396->pvdd) { 180462306a36Sopenharmony_ci ret = regulator_enable(max98396->pvdd); 180562306a36Sopenharmony_ci if (ret < 0) 180662306a36Sopenharmony_ci return ret; 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci ret = devm_add_action_or_reset(&i2c->dev, 180962306a36Sopenharmony_ci max98396_supply_disable, 181062306a36Sopenharmony_ci max98396->pvdd); 181162306a36Sopenharmony_ci if (ret < 0) 181262306a36Sopenharmony_ci return ret; 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci if (max98396->vbat) { 181662306a36Sopenharmony_ci ret = regulator_enable(max98396->vbat); 181762306a36Sopenharmony_ci if (ret < 0) 181862306a36Sopenharmony_ci return ret; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci ret = devm_add_action_or_reset(&i2c->dev, 182162306a36Sopenharmony_ci max98396_supply_disable, 182262306a36Sopenharmony_ci max98396->vbat); 182362306a36Sopenharmony_ci if (ret < 0) 182462306a36Sopenharmony_ci return ret; 182562306a36Sopenharmony_ci } 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci /* update interleave mode info */ 182862306a36Sopenharmony_ci if (device_property_read_bool(&i2c->dev, "adi,interleave_mode")) 182962306a36Sopenharmony_ci max98396->interleave_mode = true; 183062306a36Sopenharmony_ci else 183162306a36Sopenharmony_ci max98396->interleave_mode = false; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci /* voltage/current slot & gpio configuration */ 183462306a36Sopenharmony_ci max98396_read_device_property(&i2c->dev, max98396); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci /* Reset the Device */ 183762306a36Sopenharmony_ci max98396->reset_gpio = devm_gpiod_get_optional(&i2c->dev, 183862306a36Sopenharmony_ci "reset", GPIOD_OUT_HIGH); 183962306a36Sopenharmony_ci if (IS_ERR(max98396->reset_gpio)) { 184062306a36Sopenharmony_ci ret = PTR_ERR(max98396->reset_gpio); 184162306a36Sopenharmony_ci dev_err(&i2c->dev, "Unable to request GPIO pin: %d.\n", ret); 184262306a36Sopenharmony_ci return ret; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci if (max98396->reset_gpio) { 184662306a36Sopenharmony_ci usleep_range(5000, 6000); 184762306a36Sopenharmony_ci gpiod_set_value_cansleep(max98396->reset_gpio, 0); 184862306a36Sopenharmony_ci /* Wait for the hw reset done */ 184962306a36Sopenharmony_ci usleep_range(5000, 6000); 185062306a36Sopenharmony_ci } 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci ret = regmap_read(max98396->regmap, 185362306a36Sopenharmony_ci GET_REG_ADDR_REV_ID(max98396->device_id), ®); 185462306a36Sopenharmony_ci if (ret < 0) { 185562306a36Sopenharmony_ci dev_err(&i2c->dev, "%s: failed to read revision of the device.\n", id->name); 185662306a36Sopenharmony_ci return ret; 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci dev_info(&i2c->dev, "%s revision ID: 0x%02X\n", id->name, reg); 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci /* codec registration */ 186162306a36Sopenharmony_ci if (max98396->device_id == CODEC_TYPE_MAX98396) 186262306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 186362306a36Sopenharmony_ci &soc_codec_dev_max98396, 186462306a36Sopenharmony_ci max98396_dai, 186562306a36Sopenharmony_ci ARRAY_SIZE(max98396_dai)); 186662306a36Sopenharmony_ci else 186762306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 186862306a36Sopenharmony_ci &soc_codec_dev_max98397, 186962306a36Sopenharmony_ci max98397_dai, 187062306a36Sopenharmony_ci ARRAY_SIZE(max98397_dai)); 187162306a36Sopenharmony_ci if (ret < 0) 187262306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci return ret; 187562306a36Sopenharmony_ci} 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_cistatic const struct i2c_device_id max98396_i2c_id[] = { 187862306a36Sopenharmony_ci { "max98396", CODEC_TYPE_MAX98396}, 187962306a36Sopenharmony_ci { "max98397", CODEC_TYPE_MAX98397}, 188062306a36Sopenharmony_ci { }, 188162306a36Sopenharmony_ci}; 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98396_i2c_id); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci#if defined(CONFIG_OF) 188662306a36Sopenharmony_cistatic const struct of_device_id max98396_of_match[] = { 188762306a36Sopenharmony_ci { .compatible = "adi,max98396", }, 188862306a36Sopenharmony_ci { .compatible = "adi,max98397", }, 188962306a36Sopenharmony_ci { } 189062306a36Sopenharmony_ci}; 189162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98396_of_match); 189262306a36Sopenharmony_ci#endif 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci#ifdef CONFIG_ACPI 189562306a36Sopenharmony_cistatic const struct acpi_device_id max98396_acpi_match[] = { 189662306a36Sopenharmony_ci { "ADS8396", 0 }, 189762306a36Sopenharmony_ci { "ADS8397", 0 }, 189862306a36Sopenharmony_ci {}, 189962306a36Sopenharmony_ci}; 190062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, max98396_acpi_match); 190162306a36Sopenharmony_ci#endif 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_cistatic struct i2c_driver max98396_i2c_driver = { 190462306a36Sopenharmony_ci .driver = { 190562306a36Sopenharmony_ci .name = "max98396", 190662306a36Sopenharmony_ci .of_match_table = of_match_ptr(max98396_of_match), 190762306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(max98396_acpi_match), 190862306a36Sopenharmony_ci .pm = &max98396_pm, 190962306a36Sopenharmony_ci }, 191062306a36Sopenharmony_ci .probe = max98396_i2c_probe, 191162306a36Sopenharmony_ci .id_table = max98396_i2c_id, 191262306a36Sopenharmony_ci}; 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_cimodule_i2c_driver(max98396_i2c_driver) 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98396 driver"); 191762306a36Sopenharmony_ciMODULE_AUTHOR("Ryan Lee <ryans.lee@analog.com>"); 191862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1919