162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// Copyright (c) 2021, Maxim Integrated 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/acpi.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/i2c.h> 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/regmap.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/cdev.h> 1162306a36Sopenharmony_ci#include <sound/pcm.h> 1262306a36Sopenharmony_ci#include <sound/pcm_params.h> 1362306a36Sopenharmony_ci#include <sound/soc.h> 1462306a36Sopenharmony_ci#include <linux/gpio.h> 1562306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1662306a36Sopenharmony_ci#include <linux/of.h> 1762306a36Sopenharmony_ci#include <linux/of_gpio.h> 1862306a36Sopenharmony_ci#include <sound/tlv.h> 1962306a36Sopenharmony_ci#include "max98520.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic struct reg_default max98520_reg[] = { 2262306a36Sopenharmony_ci {MAX98520_R2000_SW_RESET, 0x00}, 2362306a36Sopenharmony_ci {MAX98520_R2001_STATUS_1, 0x00}, 2462306a36Sopenharmony_ci {MAX98520_R2002_STATUS_2, 0x00}, 2562306a36Sopenharmony_ci {MAX98520_R2020_THERM_WARN_THRESH, 0x46}, 2662306a36Sopenharmony_ci {MAX98520_R2021_THERM_SHDN_THRESH, 0x64}, 2762306a36Sopenharmony_ci {MAX98520_R2022_THERM_HYSTERESIS, 0x02}, 2862306a36Sopenharmony_ci {MAX98520_R2023_THERM_FOLDBACK_SET, 0x31}, 2962306a36Sopenharmony_ci {MAX98520_R2027_THERM_FOLDBACK_EN, 0x01}, 3062306a36Sopenharmony_ci {MAX98520_R2030_CLK_MON_CTRL, 0x00}, 3162306a36Sopenharmony_ci {MAX98520_R2037_ERR_MON_CTRL, 0x01}, 3262306a36Sopenharmony_ci {MAX98520_R2040_PCM_MODE_CFG, 0xC0}, 3362306a36Sopenharmony_ci {MAX98520_R2041_PCM_CLK_SETUP, 0x04}, 3462306a36Sopenharmony_ci {MAX98520_R2042_PCM_SR_SETUP, 0x08}, 3562306a36Sopenharmony_ci {MAX98520_R2043_PCM_RX_SRC1, 0x00}, 3662306a36Sopenharmony_ci {MAX98520_R2044_PCM_RX_SRC2, 0x00}, 3762306a36Sopenharmony_ci {MAX98520_R204F_PCM_RX_EN, 0x00}, 3862306a36Sopenharmony_ci {MAX98520_R2090_AMP_VOL_CTRL, 0x00}, 3962306a36Sopenharmony_ci {MAX98520_R2091_AMP_PATH_GAIN, 0x03}, 4062306a36Sopenharmony_ci {MAX98520_R2092_AMP_DSP_CFG, 0x02}, 4162306a36Sopenharmony_ci {MAX98520_R2094_SSM_CFG, 0x01}, 4262306a36Sopenharmony_ci {MAX98520_R2095_AMP_CFG, 0xF0}, 4362306a36Sopenharmony_ci {MAX98520_R209F_AMP_EN, 0x00}, 4462306a36Sopenharmony_ci {MAX98520_R20B0_ADC_SR, 0x00}, 4562306a36Sopenharmony_ci {MAX98520_R20B1_ADC_RESOLUTION, 0x00}, 4662306a36Sopenharmony_ci {MAX98520_R20B2_ADC_PVDD0_CFG, 0x02}, 4762306a36Sopenharmony_ci {MAX98520_R20B3_ADC_THERMAL_CFG, 0x02}, 4862306a36Sopenharmony_ci {MAX98520_R20B4_ADC_READBACK_CTRL, 0x00}, 4962306a36Sopenharmony_ci {MAX98520_R20B5_ADC_READBACK_UPDATE, 0x00}, 5062306a36Sopenharmony_ci {MAX98520_R20B6_ADC_PVDD_READBACK_MSB, 0x00}, 5162306a36Sopenharmony_ci {MAX98520_R20B7_ADC_PVDD_READBACK_LSB, 0x00}, 5262306a36Sopenharmony_ci {MAX98520_R20B8_ADC_TEMP_READBACK_MSB, 0x00}, 5362306a36Sopenharmony_ci {MAX98520_R20B9_ADC_TEMP_READBACK_LSB, 0x00}, 5462306a36Sopenharmony_ci {MAX98520_R20BA_ADC_LOW_PVDD_READBACK_MSB, 0xFF}, 5562306a36Sopenharmony_ci {MAX98520_R20BB_ADC_LOW_READBACK_LSB, 0x01}, 5662306a36Sopenharmony_ci {MAX98520_R20BC_ADC_HIGH_TEMP_READBACK_MSB, 0x00}, 5762306a36Sopenharmony_ci {MAX98520_R20BD_ADC_HIGH_TEMP_READBACK_LSB, 0x00}, 5862306a36Sopenharmony_ci {MAX98520_R20CF_MEAS_ADC_CFG, 0x00}, 5962306a36Sopenharmony_ci {MAX98520_R20D0_DHT_CFG1, 0x00}, 6062306a36Sopenharmony_ci {MAX98520_R20D1_LIMITER_CFG1, 0x08}, 6162306a36Sopenharmony_ci {MAX98520_R20D2_LIMITER_CFG2, 0x00}, 6262306a36Sopenharmony_ci {MAX98520_R20D3_DHT_CFG2, 0x14}, 6362306a36Sopenharmony_ci {MAX98520_R20D4_DHT_CFG3, 0x02}, 6462306a36Sopenharmony_ci {MAX98520_R20D5_DHT_CFG4, 0x04}, 6562306a36Sopenharmony_ci {MAX98520_R20D6_DHT_HYSTERESIS_CFG, 0x07}, 6662306a36Sopenharmony_ci {MAX98520_R20D8_DHT_EN, 0x00}, 6762306a36Sopenharmony_ci {MAX98520_R210E_AUTO_RESTART_BEHAVIOR, 0x00}, 6862306a36Sopenharmony_ci {MAX98520_R210F_GLOBAL_EN, 0x00}, 6962306a36Sopenharmony_ci {MAX98520_R21FF_REVISION_ID, 0x00}, 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int max98520_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 7562306a36Sopenharmony_ci struct max98520_priv *max98520 = 7662306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 7762306a36Sopenharmony_ci unsigned int format = 0; 7862306a36Sopenharmony_ci unsigned int invert = 0; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 8362306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 8662306a36Sopenharmony_ci invert = MAX98520_PCM_MODE_CFG_PCM_BCLKEDGE; 8762306a36Sopenharmony_ci break; 8862306a36Sopenharmony_ci default: 8962306a36Sopenharmony_ci dev_err(component->dev, "DAI invert mode unsupported\n"); 9062306a36Sopenharmony_ci return -EINVAL; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 9462306a36Sopenharmony_ci MAX98520_R2041_PCM_CLK_SETUP, 9562306a36Sopenharmony_ci MAX98520_PCM_MODE_CFG_PCM_BCLKEDGE, 9662306a36Sopenharmony_ci invert); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* interface format */ 9962306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 10062306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 10162306a36Sopenharmony_ci format = MAX98520_PCM_FORMAT_I2S; 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 10462306a36Sopenharmony_ci format = MAX98520_PCM_FORMAT_LJ; 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 10762306a36Sopenharmony_ci format = MAX98520_PCM_FORMAT_TDM_MODE1; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 11062306a36Sopenharmony_ci format = MAX98520_PCM_FORMAT_TDM_MODE0; 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci default: 11362306a36Sopenharmony_ci return -EINVAL; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 11762306a36Sopenharmony_ci MAX98520_R2040_PCM_MODE_CFG, 11862306a36Sopenharmony_ci MAX98520_PCM_MODE_CFG_FORMAT_MASK, 11962306a36Sopenharmony_ci format << MAX98520_PCM_MODE_CFG_FORMAT_SHIFT); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* BCLKs per LRCLK */ 12562306a36Sopenharmony_cistatic const int bclk_sel_table[] = { 12662306a36Sopenharmony_ci 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic int max98520_get_bclk_sel(int bclk) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci int i; 13262306a36Sopenharmony_ci /* match BCLKs per LRCLK */ 13362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { 13462306a36Sopenharmony_ci if (bclk_sel_table[i] == bclk) 13562306a36Sopenharmony_ci return i + 2; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic int max98520_set_clock(struct snd_soc_component *component, 14162306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci struct max98520_priv *max98520 = 14462306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 14562306a36Sopenharmony_ci /* BCLK/LRCLK ratio calculation */ 14662306a36Sopenharmony_ci int blr_clk_ratio = params_channels(params) * max98520->ch_size; 14762306a36Sopenharmony_ci int value; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if (!max98520->tdm_mode) { 15062306a36Sopenharmony_ci /* BCLK configuration */ 15162306a36Sopenharmony_ci value = max98520_get_bclk_sel(blr_clk_ratio); 15262306a36Sopenharmony_ci if (!value) { 15362306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 15462306a36Sopenharmony_ci params_format(params)); 15562306a36Sopenharmony_ci return -EINVAL; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 15962306a36Sopenharmony_ci MAX98520_R2041_PCM_CLK_SETUP, 16062306a36Sopenharmony_ci MAX98520_PCM_CLK_SETUP_BSEL_MASK, 16162306a36Sopenharmony_ci value); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci dev_dbg(component->dev, "%s tdm_mode:%d out\n", __func__, max98520->tdm_mode); 16462306a36Sopenharmony_ci return 0; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic int max98520_dai_hw_params(struct snd_pcm_substream *substream, 16862306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 16962306a36Sopenharmony_ci struct snd_soc_dai *dai) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 17262306a36Sopenharmony_ci struct max98520_priv *max98520 = 17362306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 17462306a36Sopenharmony_ci unsigned int sampling_rate = 0; 17562306a36Sopenharmony_ci unsigned int chan_sz = 0; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* pcm mode configuration */ 17862306a36Sopenharmony_ci switch (snd_pcm_format_width(params_format(params))) { 17962306a36Sopenharmony_ci case 16: 18062306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_16; 18162306a36Sopenharmony_ci break; 18262306a36Sopenharmony_ci case 24: 18362306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_24; 18462306a36Sopenharmony_ci break; 18562306a36Sopenharmony_ci case 32: 18662306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_32; 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci default: 18962306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 19062306a36Sopenharmony_ci params_format(params)); 19162306a36Sopenharmony_ci goto err; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci max98520->ch_size = snd_pcm_format_width(params_format(params)); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 19762306a36Sopenharmony_ci MAX98520_R2040_PCM_MODE_CFG, 19862306a36Sopenharmony_ci MAX98520_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci dev_dbg(component->dev, "format supported %d", 20162306a36Sopenharmony_ci params_format(params)); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* sampling rate configuration */ 20462306a36Sopenharmony_ci switch (params_rate(params)) { 20562306a36Sopenharmony_ci case 8000: 20662306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_8000; 20762306a36Sopenharmony_ci break; 20862306a36Sopenharmony_ci case 11025: 20962306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_11025; 21062306a36Sopenharmony_ci break; 21162306a36Sopenharmony_ci case 12000: 21262306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_12000; 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci case 16000: 21562306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_16000; 21662306a36Sopenharmony_ci break; 21762306a36Sopenharmony_ci case 22050: 21862306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_22050; 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci case 24000: 22162306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_24000; 22262306a36Sopenharmony_ci break; 22362306a36Sopenharmony_ci case 32000: 22462306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_32000; 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci case 44100: 22762306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_44100; 22862306a36Sopenharmony_ci break; 22962306a36Sopenharmony_ci case 48000: 23062306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_48000; 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci case 88200: 23362306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_88200; 23462306a36Sopenharmony_ci break; 23562306a36Sopenharmony_ci case 96000: 23662306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_96000; 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci case 176400: 23962306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_176400; 24062306a36Sopenharmony_ci break; 24162306a36Sopenharmony_ci case 192000: 24262306a36Sopenharmony_ci sampling_rate = MAX98520_PCM_SR_192000; 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci default: 24562306a36Sopenharmony_ci dev_err(component->dev, "rate %d not supported\n", 24662306a36Sopenharmony_ci params_rate(params)); 24762306a36Sopenharmony_ci goto err; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci dev_dbg(component->dev, " %s ch_size: %d, sampling rate : %d out\n", __func__, 25162306a36Sopenharmony_ci snd_pcm_format_width(params_format(params)), params_rate(params)); 25262306a36Sopenharmony_ci /* set DAI_SR to correct LRCLK frequency */ 25362306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 25462306a36Sopenharmony_ci MAX98520_R2042_PCM_SR_SETUP, 25562306a36Sopenharmony_ci MAX98520_PCM_SR_MASK, 25662306a36Sopenharmony_ci sampling_rate); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return max98520_set_clock(component, params); 25962306a36Sopenharmony_cierr: 26062306a36Sopenharmony_ci dev_dbg(component->dev, "%s out error", __func__); 26162306a36Sopenharmony_ci return -EINVAL; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic int max98520_dai_tdm_slot(struct snd_soc_dai *dai, 26562306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 26662306a36Sopenharmony_ci int slots, int slot_width) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 26962306a36Sopenharmony_ci struct max98520_priv *max98520 = 27062306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 27162306a36Sopenharmony_ci int bsel; 27262306a36Sopenharmony_ci unsigned int chan_sz = 0; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (!tx_mask && !rx_mask && !slots && !slot_width) 27562306a36Sopenharmony_ci max98520->tdm_mode = false; 27662306a36Sopenharmony_ci else 27762306a36Sopenharmony_ci max98520->tdm_mode = true; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* BCLK configuration */ 28062306a36Sopenharmony_ci bsel = max98520_get_bclk_sel(slots * slot_width); 28162306a36Sopenharmony_ci if (bsel == 0) { 28262306a36Sopenharmony_ci dev_err(component->dev, "BCLK %d not supported\n", 28362306a36Sopenharmony_ci slots * slot_width); 28462306a36Sopenharmony_ci return -EINVAL; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 28862306a36Sopenharmony_ci MAX98520_R2041_PCM_CLK_SETUP, 28962306a36Sopenharmony_ci MAX98520_PCM_CLK_SETUP_BSEL_MASK, 29062306a36Sopenharmony_ci bsel); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Channel size configuration */ 29362306a36Sopenharmony_ci switch (slot_width) { 29462306a36Sopenharmony_ci case 16: 29562306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_16; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci case 24: 29862306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_24; 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci case 32: 30162306a36Sopenharmony_ci chan_sz = MAX98520_PCM_MODE_CFG_CHANSZ_32; 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci default: 30462306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 30562306a36Sopenharmony_ci slot_width); 30662306a36Sopenharmony_ci return -EINVAL; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 31062306a36Sopenharmony_ci MAX98520_R2040_PCM_MODE_CFG, 31162306a36Sopenharmony_ci MAX98520_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* Rx slot configuration */ 31462306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 31562306a36Sopenharmony_ci MAX98520_R2044_PCM_RX_SRC2, 31662306a36Sopenharmony_ci MAX98520_PCM_DMIX_CH0_SRC_MASK, 31762306a36Sopenharmony_ci rx_mask); 31862306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 31962306a36Sopenharmony_ci MAX98520_R2044_PCM_RX_SRC2, 32062306a36Sopenharmony_ci MAX98520_PCM_DMIX_CH1_SRC_MASK, 32162306a36Sopenharmony_ci rx_mask << MAX98520_PCM_DMIX_CH1_SHIFT); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci return 0; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci#define MAX98520_RATES SNDRV_PCM_RATE_8000_192000 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci#define MAX98520_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 32962306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98520_dai_ops = { 33262306a36Sopenharmony_ci .set_fmt = max98520_dai_set_fmt, 33362306a36Sopenharmony_ci .hw_params = max98520_dai_hw_params, 33462306a36Sopenharmony_ci .set_tdm_slot = max98520_dai_tdm_slot, 33562306a36Sopenharmony_ci}; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic int max98520_dac_event(struct snd_soc_dapm_widget *w, 33862306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci struct snd_soc_component *component = 34162306a36Sopenharmony_ci snd_soc_dapm_to_component(w->dapm); 34262306a36Sopenharmony_ci struct max98520_priv *max98520 = 34362306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci switch (event) { 34662306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 34762306a36Sopenharmony_ci dev_dbg(component->dev, " AMP ON\n"); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R209F_AMP_EN, 1); 35062306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R210F_GLOBAL_EN, 1); 35162306a36Sopenharmony_ci usleep_range(30000, 31000); 35262306a36Sopenharmony_ci break; 35362306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 35462306a36Sopenharmony_ci dev_dbg(component->dev, " AMP OFF\n"); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R210F_GLOBAL_EN, 0); 35762306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R209F_AMP_EN, 0); 35862306a36Sopenharmony_ci usleep_range(30000, 31000); 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci default: 36162306a36Sopenharmony_ci return 0; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic const char * const max98520_switch_text[] = { 36762306a36Sopenharmony_ci "Left", "Right", "LeftRight"}; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic const struct soc_enum dai_sel_enum = 37062306a36Sopenharmony_ci SOC_ENUM_SINGLE(MAX98520_R2043_PCM_RX_SRC1, 37162306a36Sopenharmony_ci 0, 3, max98520_switch_text); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98520_dai_controls = 37462306a36Sopenharmony_ci SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98520_left_input_mixer_controls[] = { 37762306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH0", MAX98520_R2044_PCM_RX_SRC2, 0, 0x0, 0), 37862306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH1", MAX98520_R2044_PCM_RX_SRC2, 0, 0x1, 0), 37962306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH2", MAX98520_R2044_PCM_RX_SRC2, 0, 0x2, 0), 38062306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH3", MAX98520_R2044_PCM_RX_SRC2, 0, 0x3, 0), 38162306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH4", MAX98520_R2044_PCM_RX_SRC2, 0, 0x4, 0), 38262306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH5", MAX98520_R2044_PCM_RX_SRC2, 0, 0x5, 0), 38362306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH6", MAX98520_R2044_PCM_RX_SRC2, 0, 0x6, 0), 38462306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH7", MAX98520_R2044_PCM_RX_SRC2, 0, 0x7, 0), 38562306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH8", MAX98520_R2044_PCM_RX_SRC2, 0, 0x8, 0), 38662306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH9", MAX98520_R2044_PCM_RX_SRC2, 0, 0x9, 0), 38762306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH10", MAX98520_R2044_PCM_RX_SRC2, 0, 0xa, 0), 38862306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH11", MAX98520_R2044_PCM_RX_SRC2, 0, 0xb, 0), 38962306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH12", MAX98520_R2044_PCM_RX_SRC2, 0, 0xc, 0), 39062306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH13", MAX98520_R2044_PCM_RX_SRC2, 0, 0xd, 0), 39162306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH14", MAX98520_R2044_PCM_RX_SRC2, 0, 0xe, 0), 39262306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH15", MAX98520_R2044_PCM_RX_SRC2, 0, 0xf, 0), 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98520_right_input_mixer_controls[] = { 39662306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH0", MAX98520_R2044_PCM_RX_SRC2, 4, 0x0, 0), 39762306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH1", MAX98520_R2044_PCM_RX_SRC2, 4, 0x1, 0), 39862306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH2", MAX98520_R2044_PCM_RX_SRC2, 4, 0x2, 0), 39962306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH3", MAX98520_R2044_PCM_RX_SRC2, 4, 0x3, 0), 40062306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH4", MAX98520_R2044_PCM_RX_SRC2, 4, 0x4, 0), 40162306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH5", MAX98520_R2044_PCM_RX_SRC2, 4, 0x5, 0), 40262306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH6", MAX98520_R2044_PCM_RX_SRC2, 4, 0x6, 0), 40362306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH7", MAX98520_R2044_PCM_RX_SRC2, 4, 0x7, 0), 40462306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH8", MAX98520_R2044_PCM_RX_SRC2, 4, 0x8, 0), 40562306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH9", MAX98520_R2044_PCM_RX_SRC2, 4, 0x9, 0), 40662306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH10", MAX98520_R2044_PCM_RX_SRC2, 4, 0xa, 0), 40762306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH11", MAX98520_R2044_PCM_RX_SRC2, 4, 0xb, 0), 40862306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH12", MAX98520_R2044_PCM_RX_SRC2, 4, 0xc, 0), 40962306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH13", MAX98520_R2044_PCM_RX_SRC2, 4, 0xd, 0), 41062306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH14", MAX98520_R2044_PCM_RX_SRC2, 4, 0xe, 0), 41162306a36Sopenharmony_ci SOC_DAPM_SINGLE("PCM_INPUT_CH15", MAX98520_R2044_PCM_RX_SRC2, 4, 0xf, 0), 41262306a36Sopenharmony_ci}; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98520_dapm_widgets[] = { 41562306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", 41662306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0, max98520_dac_event, 41762306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 41862306a36Sopenharmony_ci SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, &max98520_dai_controls), 41962306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("BE_OUT"), 42062306a36Sopenharmony_ci /* Left Input Selection */ 42162306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("Left Input Selection", SND_SOC_NOPM, 0, 0, 42262306a36Sopenharmony_ci &max98520_left_input_mixer_controls[0], 42362306a36Sopenharmony_ci ARRAY_SIZE(max98520_left_input_mixer_controls)), 42462306a36Sopenharmony_ci /* Right Input Selection */ 42562306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("Right Input Selection", SND_SOC_NOPM, 0, 0, 42662306a36Sopenharmony_ci &max98520_right_input_mixer_controls[0], 42762306a36Sopenharmony_ci ARRAY_SIZE(max98520_right_input_mixer_controls)), 42862306a36Sopenharmony_ci}; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(max98520_digital_tlv, -6300, 50, 1); 43162306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(max98520_spk_tlv, -600, 300, 0); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98520_dht_lim_thresh_tlv, 43462306a36Sopenharmony_ci 0, 15, TLV_DB_SCALE_ITEM(-1500, 100, 0), 43562306a36Sopenharmony_ci); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98520_dht_hysteresis_tlv, 43862306a36Sopenharmony_ci 0, 3, TLV_DB_SCALE_ITEM(100, 100, 0), 43962306a36Sopenharmony_ci 4, 7, TLV_DB_SCALE_ITEM(600, 200, 0), 44062306a36Sopenharmony_ci); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98520_dht_rotation_point_tlv, 44362306a36Sopenharmony_ci 0, 1, TLV_DB_SCALE_ITEM(-1500, 300, 0), 44462306a36Sopenharmony_ci 2, 4, TLV_DB_SCALE_ITEM(-1000, 200, 0), 44562306a36Sopenharmony_ci 5, 10, TLV_DB_SCALE_ITEM(-500, 100, 0), 44662306a36Sopenharmony_ci); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98520_dht_supply_hr_tlv, 44962306a36Sopenharmony_ci 0, 16, TLV_DB_SCALE_ITEM(-2000, 250, 0), 45062306a36Sopenharmony_ci); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98520_dht_max_atten_tlv, 45362306a36Sopenharmony_ci 1, 20, TLV_DB_SCALE_ITEM(-2000, 100, 0), 45462306a36Sopenharmony_ci); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic const char * const max98520_dht_attack_rate_text[] = { 45762306a36Sopenharmony_ci "20us", "40us", "80us", "160us", "320us", "640us", 45862306a36Sopenharmony_ci "1.28ms", "2.56ms", "5.12ms", "10.24ms", "20.48ms", "40.96ms", 45962306a36Sopenharmony_ci "81.92ms", "163.84ms" 46062306a36Sopenharmony_ci}; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98520_dht_attack_rate_enum, 46362306a36Sopenharmony_ci MAX98520_R20D4_DHT_CFG3, 0, 46462306a36Sopenharmony_ci max98520_dht_attack_rate_text); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic const char * const max98520_dht_release_rate_text[] = { 46762306a36Sopenharmony_ci "2ms", "4ms", "8ms", "16ms", "32ms", "64ms", "128ms", "256ms", "512ms", 46862306a36Sopenharmony_ci "1.024s", "2.048s", "4.096s", "8.192s", "16.384s" 46962306a36Sopenharmony_ci}; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98520_dht_release_rate_enum, 47262306a36Sopenharmony_ci MAX98520_R20D5_DHT_CFG4, 0, 47362306a36Sopenharmony_ci max98520_dht_release_rate_text); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic bool max98520_readable_register(struct device *dev, unsigned int reg) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci switch (reg) { 47862306a36Sopenharmony_ci case MAX98520_R2000_SW_RESET: 47962306a36Sopenharmony_ci case MAX98520_R2027_THERM_FOLDBACK_EN: 48062306a36Sopenharmony_ci case MAX98520_R2030_CLK_MON_CTRL: 48162306a36Sopenharmony_ci case MAX98520_R2037_ERR_MON_CTRL: 48262306a36Sopenharmony_ci case MAX98520_R204F_PCM_RX_EN: 48362306a36Sopenharmony_ci case MAX98520_R209F_AMP_EN: 48462306a36Sopenharmony_ci case MAX98520_R20CF_MEAS_ADC_CFG: 48562306a36Sopenharmony_ci case MAX98520_R20D8_DHT_EN: 48662306a36Sopenharmony_ci case MAX98520_R21FF_REVISION_ID: 48762306a36Sopenharmony_ci case MAX98520_R2001_STATUS_1... MAX98520_R2002_STATUS_2: 48862306a36Sopenharmony_ci case MAX98520_R2020_THERM_WARN_THRESH... MAX98520_R2023_THERM_FOLDBACK_SET: 48962306a36Sopenharmony_ci case MAX98520_R2040_PCM_MODE_CFG... MAX98520_R2044_PCM_RX_SRC2: 49062306a36Sopenharmony_ci case MAX98520_R2090_AMP_VOL_CTRL... MAX98520_R2092_AMP_DSP_CFG: 49162306a36Sopenharmony_ci case MAX98520_R2094_SSM_CFG... MAX98520_R2095_AMP_CFG: 49262306a36Sopenharmony_ci case MAX98520_R20B0_ADC_SR... MAX98520_R20BD_ADC_HIGH_TEMP_READBACK_LSB: 49362306a36Sopenharmony_ci case MAX98520_R20D0_DHT_CFG1... MAX98520_R20D6_DHT_HYSTERESIS_CFG: 49462306a36Sopenharmony_ci case MAX98520_R210E_AUTO_RESTART_BEHAVIOR... MAX98520_R210F_GLOBAL_EN: 49562306a36Sopenharmony_ci case MAX98520_R2161_BOOST_TM1... MAX98520_R2163_BOOST_TM3: 49662306a36Sopenharmony_ci return true; 49762306a36Sopenharmony_ci default: 49862306a36Sopenharmony_ci return false; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci}; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic bool max98520_volatile_reg(struct device *dev, unsigned int reg) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci switch (reg) { 50562306a36Sopenharmony_ci case MAX98520_R210F_GLOBAL_EN: 50662306a36Sopenharmony_ci case MAX98520_R21FF_REVISION_ID: 50762306a36Sopenharmony_ci case MAX98520_R2000_SW_RESET: 50862306a36Sopenharmony_ci case MAX98520_R2001_STATUS_1 ... MAX98520_R2002_STATUS_2: 50962306a36Sopenharmony_ci case MAX98520_R20B4_ADC_READBACK_CTRL 51062306a36Sopenharmony_ci ... MAX98520_R20BD_ADC_HIGH_TEMP_READBACK_LSB: 51162306a36Sopenharmony_ci return true; 51262306a36Sopenharmony_ci default: 51362306a36Sopenharmony_ci return false; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98520_snd_controls[] = { 51862306a36Sopenharmony_ci/* Volume */ 51962306a36Sopenharmony_ciSOC_SINGLE_TLV("Digital Volume", MAX98520_R2090_AMP_VOL_CTRL, 52062306a36Sopenharmony_ci 0, 0x7F, 1, max98520_digital_tlv), 52162306a36Sopenharmony_ciSOC_SINGLE_TLV("Speaker Volume", MAX98520_R2091_AMP_PATH_GAIN, 52262306a36Sopenharmony_ci 0, 0x5, 0, max98520_spk_tlv), 52362306a36Sopenharmony_ci/* Volume Ramp Up/Down Enable*/ 52462306a36Sopenharmony_ciSOC_SINGLE("Ramp Up Switch", MAX98520_R2092_AMP_DSP_CFG, 52562306a36Sopenharmony_ci MAX98520_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0), 52662306a36Sopenharmony_ciSOC_SINGLE("Ramp Down Switch", MAX98520_R2092_AMP_DSP_CFG, 52762306a36Sopenharmony_ci MAX98520_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0), 52862306a36Sopenharmony_ci/* Clock Monitor Enable */ 52962306a36Sopenharmony_ciSOC_SINGLE("CLK Monitor Switch", MAX98520_R2037_ERR_MON_CTRL, 53062306a36Sopenharmony_ci MAX98520_CTRL_CMON_EN_SHIFT, 1, 0), 53162306a36Sopenharmony_ci/* Clock Monitor Config */ 53262306a36Sopenharmony_ciSOC_SINGLE("CLKMON Autorestart Switch", MAX98520_R2030_CLK_MON_CTRL, 53362306a36Sopenharmony_ci MAX98520_CMON_AUTORESTART_SHIFT, 1, 0), 53462306a36Sopenharmony_ci/* Dither Enable */ 53562306a36Sopenharmony_ciSOC_SINGLE("Dither Switch", MAX98520_R2092_AMP_DSP_CFG, 53662306a36Sopenharmony_ci MAX98520_DSP_SPK_DITH_EN_SHIFT, 1, 0), 53762306a36Sopenharmony_ci/* DC Blocker Enable */ 53862306a36Sopenharmony_ciSOC_SINGLE("DC Blocker Switch", MAX98520_R2092_AMP_DSP_CFG, 53962306a36Sopenharmony_ci MAX98520_DSP_SPK_DCBLK_EN_SHIFT, 1, 0), 54062306a36Sopenharmony_ci/* Speaker Safe Mode Enable */ 54162306a36Sopenharmony_ciSOC_SINGLE("Speaker Safemode Switch", MAX98520_R2092_AMP_DSP_CFG, 54262306a36Sopenharmony_ci MAX98520_DSP_SPK_SAFE_EN_SHIFT, 1, 0), 54362306a36Sopenharmony_ci/* AMP SSM Enable */ 54462306a36Sopenharmony_ciSOC_SINGLE("CP Bypass Switch", MAX98520_R2094_SSM_CFG, 54562306a36Sopenharmony_ci MAX98520_SSM_RCVR_MODE_SHIFT, 1, 0), 54662306a36Sopenharmony_ci/* Dynamic Headroom Tracking */ 54762306a36Sopenharmony_ciSOC_SINGLE("DHT Switch", MAX98520_R20D8_DHT_EN, 0, 1, 0), 54862306a36Sopenharmony_ciSOC_SINGLE("DHT Limiter Mode", MAX98520_R20D2_LIMITER_CFG2, 54962306a36Sopenharmony_ci MAX98520_DHT_LIMITER_MODE_SHIFT, 1, 0), 55062306a36Sopenharmony_ciSOC_SINGLE("DHT Hysteresis Switch", MAX98520_R20D6_DHT_HYSTERESIS_CFG, 55162306a36Sopenharmony_ci MAX98520_DHT_HYSTERESIS_SWITCH_SHIFT, 1, 0), 55262306a36Sopenharmony_ciSOC_SINGLE_TLV("DHT Rot Pnt", MAX98520_R20D0_DHT_CFG1, 55362306a36Sopenharmony_ci MAX98520_DHT_VROT_PNT_SHIFT, 10, 1, max98520_dht_rotation_point_tlv), 55462306a36Sopenharmony_ciSOC_SINGLE_TLV("DHT Supply Headroom", MAX98520_R20D1_LIMITER_CFG1, 55562306a36Sopenharmony_ci MAX98520_DHT_SUPPLY_HR_SHIFT, 16, 0, max98520_dht_supply_hr_tlv), 55662306a36Sopenharmony_ciSOC_SINGLE_TLV("DHT Limiter Threshold", MAX98520_R20D2_LIMITER_CFG2, 55762306a36Sopenharmony_ci MAX98520_DHT_LIMITER_THRESHOLD_SHIFT, 0xF, 1, max98520_dht_lim_thresh_tlv), 55862306a36Sopenharmony_ciSOC_SINGLE_TLV("DHT Max Attenuation", MAX98520_R20D3_DHT_CFG2, 55962306a36Sopenharmony_ci MAX98520_DHT_MAX_ATTEN_SHIFT, 20, 1, max98520_dht_max_atten_tlv), 56062306a36Sopenharmony_ciSOC_SINGLE_TLV("DHT Hysteresis", MAX98520_R20D6_DHT_HYSTERESIS_CFG, 56162306a36Sopenharmony_ci MAX98520_DHT_HYSTERESIS_SHIFT, 0x7, 0, max98520_dht_hysteresis_tlv), 56262306a36Sopenharmony_ciSOC_ENUM("DHT Attack Rate", max98520_dht_attack_rate_enum), 56362306a36Sopenharmony_ciSOC_ENUM("DHT Release Rate", max98520_dht_release_rate_enum), 56462306a36Sopenharmony_ci/* ADC configuration */ 56562306a36Sopenharmony_ciSOC_SINGLE("ADC PVDD CH Switch", MAX98520_R20CF_MEAS_ADC_CFG, 0, 1, 0), 56662306a36Sopenharmony_ciSOC_SINGLE("ADC PVDD FLT Switch", MAX98520_R20B2_ADC_PVDD0_CFG, MAX98520_FLT_EN_SHIFT, 1, 0), 56762306a36Sopenharmony_ciSOC_SINGLE("ADC TEMP FLT Switch", MAX98520_R20B3_ADC_THERMAL_CFG, MAX98520_FLT_EN_SHIFT, 1, 0), 56862306a36Sopenharmony_ciSOC_SINGLE("ADC PVDD MSB", MAX98520_R20B6_ADC_PVDD_READBACK_MSB, 0, 0xFF, 0), 56962306a36Sopenharmony_ciSOC_SINGLE("ADC PVDD LSB", MAX98520_R20B7_ADC_PVDD_READBACK_LSB, 0, 0x01, 0), 57062306a36Sopenharmony_ciSOC_SINGLE("ADC TEMP MSB", MAX98520_R20B8_ADC_TEMP_READBACK_MSB, 0, 0xFF, 0), 57162306a36Sopenharmony_ciSOC_SINGLE("ADC TEMP LSB", MAX98520_R20B9_ADC_TEMP_READBACK_LSB, 0, 0x01, 0), 57262306a36Sopenharmony_ci}; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98520_audio_map[] = { 57562306a36Sopenharmony_ci /* Plabyack */ 57662306a36Sopenharmony_ci {"DAI Sel Mux", "Left", "Amp Enable"}, 57762306a36Sopenharmony_ci {"DAI Sel Mux", "Right", "Amp Enable"}, 57862306a36Sopenharmony_ci {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 57962306a36Sopenharmony_ci {"BE_OUT", NULL, "DAI Sel Mux"}, 58062306a36Sopenharmony_ci}; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98520_dai[] = { 58362306a36Sopenharmony_ci { 58462306a36Sopenharmony_ci .name = "max98520-aif1", 58562306a36Sopenharmony_ci .playback = { 58662306a36Sopenharmony_ci .stream_name = "HiFi Playback", 58762306a36Sopenharmony_ci .channels_min = 1, 58862306a36Sopenharmony_ci .channels_max = 2, 58962306a36Sopenharmony_ci .rates = MAX98520_RATES, 59062306a36Sopenharmony_ci .formats = MAX98520_FORMATS, 59162306a36Sopenharmony_ci }, 59262306a36Sopenharmony_ci .ops = &max98520_dai_ops, 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci}; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int max98520_probe(struct snd_soc_component *component) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct max98520_priv *max98520 = 60062306a36Sopenharmony_ci snd_soc_component_get_drvdata(component); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* Software Reset */ 60362306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R2000_SW_RESET, 1); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* L/R mono mix configuration : "DAI Sel" for 0x2043 */ 60662306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R2043_PCM_RX_SRC1, 0x2); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* PCM input channles configuration : "Left Input Selection" for 0x2044 */ 60962306a36Sopenharmony_ci /* PCM input channles configuration : "Right Input Selection" for 0x2044 */ 61062306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R2044_PCM_RX_SRC2, 0x10); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* Enable DC blocker */ 61362306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, MAX98520_R2092_AMP_DSP_CFG, 1, 1); 61462306a36Sopenharmony_ci /* Enable Clock Monitor Auto-restart */ 61562306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R2030_CLK_MON_CTRL, 0x1); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* set Rx Enable */ 61862306a36Sopenharmony_ci regmap_update_bits(max98520->regmap, 61962306a36Sopenharmony_ci MAX98520_R204F_PCM_RX_EN, 62062306a36Sopenharmony_ci MAX98520_PCM_RX_EN_MASK, 62162306a36Sopenharmony_ci 1); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci return 0; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic int __maybe_unused max98520_suspend(struct device *dev) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct max98520_priv *max98520 = dev_get_drvdata(dev); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci regcache_cache_only(max98520->regmap, true); 63162306a36Sopenharmony_ci regcache_mark_dirty(max98520->regmap); 63262306a36Sopenharmony_ci return 0; 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistatic int __maybe_unused max98520_resume(struct device *dev) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci struct max98520_priv *max98520 = dev_get_drvdata(dev); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci regcache_cache_only(max98520->regmap, false); 64062306a36Sopenharmony_ci regmap_write(max98520->regmap, MAX98520_R2000_SW_RESET, 1); 64162306a36Sopenharmony_ci regcache_sync(max98520->regmap); 64262306a36Sopenharmony_ci return 0; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic const struct dev_pm_ops max98520_pm = { 64662306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(max98520_suspend, max98520_resume) 64762306a36Sopenharmony_ci}; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_max98520 = { 65062306a36Sopenharmony_ci .probe = max98520_probe, 65162306a36Sopenharmony_ci .controls = max98520_snd_controls, 65262306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98520_snd_controls), 65362306a36Sopenharmony_ci .dapm_widgets = max98520_dapm_widgets, 65462306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98520_dapm_widgets), 65562306a36Sopenharmony_ci .dapm_routes = max98520_audio_map, 65662306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98520_audio_map), 65762306a36Sopenharmony_ci .idle_bias_on = 1, 65862306a36Sopenharmony_ci .use_pmdown_time = 1, 65962306a36Sopenharmony_ci .endianness = 1, 66062306a36Sopenharmony_ci}; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic const struct regmap_config max98520_regmap = { 66362306a36Sopenharmony_ci .reg_bits = 16, 66462306a36Sopenharmony_ci .val_bits = 8, 66562306a36Sopenharmony_ci .max_register = MAX98520_R21FF_REVISION_ID, 66662306a36Sopenharmony_ci .reg_defaults = max98520_reg, 66762306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98520_reg), 66862306a36Sopenharmony_ci .readable_reg = max98520_readable_register, 66962306a36Sopenharmony_ci .volatile_reg = max98520_volatile_reg, 67062306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 67162306a36Sopenharmony_ci}; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic void max98520_power_on(struct max98520_priv *max98520, bool poweron) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci if (max98520->reset_gpio) 67662306a36Sopenharmony_ci gpiod_set_value_cansleep(max98520->reset_gpio, !poweron); 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistatic int max98520_i2c_probe(struct i2c_client *i2c) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci int ret; 68262306a36Sopenharmony_ci int reg = 0; 68362306a36Sopenharmony_ci struct max98520_priv *max98520; 68462306a36Sopenharmony_ci struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci ret = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA); 68762306a36Sopenharmony_ci if (!ret) { 68862306a36Sopenharmony_ci dev_err(&i2c->dev, "I2C check functionality failed\n"); 68962306a36Sopenharmony_ci return -ENXIO; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci max98520 = devm_kzalloc(&i2c->dev, sizeof(*max98520), GFP_KERNEL); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (!max98520) 69562306a36Sopenharmony_ci return -ENOMEM; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci i2c_set_clientdata(i2c, max98520); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci /* regmap initialization */ 70062306a36Sopenharmony_ci max98520->regmap = devm_regmap_init_i2c(i2c, &max98520_regmap); 70162306a36Sopenharmony_ci if (IS_ERR(max98520->regmap)) { 70262306a36Sopenharmony_ci ret = PTR_ERR(max98520->regmap); 70362306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); 70462306a36Sopenharmony_ci return ret; 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci /* Power on device */ 70862306a36Sopenharmony_ci max98520->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_HIGH); 70962306a36Sopenharmony_ci if (max98520->reset_gpio) { 71062306a36Sopenharmony_ci if (IS_ERR(max98520->reset_gpio)) { 71162306a36Sopenharmony_ci ret = PTR_ERR(max98520->reset_gpio); 71262306a36Sopenharmony_ci dev_err(&i2c->dev, "Unable to request GPIO pin: %d.\n", ret); 71362306a36Sopenharmony_ci return ret; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci max98520_power_on(max98520, 1); 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* Check Revision ID */ 72062306a36Sopenharmony_ci ret = regmap_read(max98520->regmap, MAX98520_R21FF_REVISION_ID, ®); 72162306a36Sopenharmony_ci if (ret < 0) { 72262306a36Sopenharmony_ci dev_err(&i2c->dev, 72362306a36Sopenharmony_ci "Failed to read: 0x%02X\n", MAX98520_R21FF_REVISION_ID); 72462306a36Sopenharmony_ci return ret; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci dev_info(&i2c->dev, "MAX98520 revisionID: 0x%02X\n", reg); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci /* codec registration */ 72962306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 73062306a36Sopenharmony_ci &soc_codec_dev_max98520, 73162306a36Sopenharmony_ci max98520_dai, ARRAY_SIZE(max98520_dai)); 73262306a36Sopenharmony_ci if (ret < 0) 73362306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return ret; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic const struct i2c_device_id max98520_i2c_id[] = { 73962306a36Sopenharmony_ci { "max98520", 0}, 74062306a36Sopenharmony_ci { }, 74162306a36Sopenharmony_ci}; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98520_i2c_id); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci#if defined(CONFIG_OF) 74662306a36Sopenharmony_cistatic const struct of_device_id max98520_of_match[] = { 74762306a36Sopenharmony_ci { .compatible = "maxim,max98520", }, 74862306a36Sopenharmony_ci { } 74962306a36Sopenharmony_ci}; 75062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98520_of_match); 75162306a36Sopenharmony_ci#endif 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_cistatic struct i2c_driver max98520_i2c_driver = { 75462306a36Sopenharmony_ci .driver = { 75562306a36Sopenharmony_ci .name = "max98520", 75662306a36Sopenharmony_ci .of_match_table = of_match_ptr(max98520_of_match), 75762306a36Sopenharmony_ci .pm = &max98520_pm, 75862306a36Sopenharmony_ci }, 75962306a36Sopenharmony_ci .probe = max98520_i2c_probe, 76062306a36Sopenharmony_ci .id_table = max98520_i2c_id, 76162306a36Sopenharmony_ci}; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_cimodule_i2c_driver(max98520_i2c_driver) 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98520 driver"); 76662306a36Sopenharmony_ciMODULE_AUTHOR("George Song <george.song@maximintegrated.com>"); 76762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 76862306a36Sopenharmony_ci 769